View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.shared.kerberos.components;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.apache.directory.api.asn1.Asn1Object;
29  import org.apache.directory.api.asn1.EncoderException;
30  import org.apache.directory.api.asn1.ber.tlv.BerValue;
31  import org.apache.directory.api.asn1.ber.tlv.TLV;
32  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
33  import org.apache.directory.api.util.Strings;
34  import org.apache.directory.server.i18n.I18n;
35  import org.apache.directory.shared.kerberos.KerberosConstants;
36  import org.apache.directory.shared.kerberos.KerberosTime;
37  import org.apache.directory.shared.kerberos.codec.types.LastReqType;
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  
41  
42  /**
43   * The LastReq structure.
44   * 
45   * The ASN.1 grammar is :
46   * <pre>
47   * LastReq         ::=     SEQUENCE OF SEQUENCE {
48   *         lr-type         [0] Int32,
49   *         lr-value        [1] KerberosTime
50   * }
51   * </pre>
52   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
53   */
54  public class LastReq implements Asn1Object
55  {
56      /** The logger */
57      private static final Logger LOG = LoggerFactory.getLogger( LastReq.class );
58  
59      /** Speedup for logs */
60      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
61  
62      /** The list of LastReq elements */
63      private List<LastReqEntry> lastReqs = new ArrayList<>();
64  
65      /** The current LastReqEntry being processed */
66      private LastReqEntry currentLR;
67  
68      // Storage for computed lengths
69      private int lrTypeTagLen[];
70      private int lrValueTagLen[];
71      private int lastReqSeqLen[];
72      private int lastReqSeqSeqLen;
73  
74  
75      /**
76       * Creates a new instance of LastReq.
77       */
78      public LastReq()
79      {
80      }
81  
82  
83      /**
84       * @return the CurrentLr type
85       */
86      public LastReqType getCurrentLrType()
87      {
88          return currentLR.getLrType();
89      }
90  
91  
92      /**
93       * Set the CurrentLr type
94       */
95      public void setCurrentLrType( LastReqType lrType )
96      {
97          currentLR.setLrType( lrType );
98      }
99  
100 
101     /**
102      * @return the CurrentLr value
103      */
104     public KerberosTime getCurrentLrValue()
105     {
106         return currentLR.getLrValue();
107     }
108 
109 
110     /**
111      * Set the CurrentLr value
112      */
113     public void setCurrentLrValue( KerberosTime lrValue )
114     {
115         currentLR.setLrValue( lrValue );
116     }
117 
118 
119     /**
120      * @return the CurrentLR
121      */
122     public LastReqEntry getCurrentLR()
123     {
124         return currentLR;
125     }
126 
127 
128     /**
129      * Create a new currentLR
130      */
131     public void createNewLR()
132     {
133         currentLR = new LastReqEntry();
134         lastReqs.add( currentLR );
135     }
136 
137 
138     /**
139      * Add a new LastReqEntry
140      * @param lastReqEntry The enry to add
141      */
142     public void addEntry( LastReqEntry lastReqEntry )
143     {
144         lastReqs.add( lastReqEntry );
145     }
146 
147 
148     /**
149      * @return the LastReqs
150      */
151     public List<LastReqEntry> getLastReqs()
152     {
153         return lastReqs;
154     }
155 
156 
157     /**
158      * Compute the LastReq length
159      * 
160      * <pre>
161      * LastReq :
162      * 
163      * 0x30 L1 LastReq
164      *  |
165      *  +--&gt; 0x30 L2 
166      *        |
167      *        +--&gt; 0xA0 L3 lr-type tag
168      *        |     |
169      *        |     +--&gt; 0x02 L3-1 lrType (int)
170      *        |
171      *        +--&gt; 0xA1 0x11 lr-value tag
172      *              |
173      *              +--&gt; 0x18 0x0F ttt (KerberosString)
174      *  </pre>
175      */
176     public int computeLength()
177     {
178         int i = 0;
179         lastReqSeqLen = new int[lastReqs.size()];
180         lrTypeTagLen = new int[lastReqs.size()];
181         lrValueTagLen = new int[lastReqs.size()];
182         lastReqSeqSeqLen = 0;
183 
184         for ( LastReqEntry lre : lastReqs )
185         {
186             int lrTypeLen = BerValue.getNbBytes( lre.getLrType().getValue() );
187             lrTypeTagLen[i] = 1 + TLV.getNbBytes( lrTypeLen ) + lrTypeLen;
188             byte[] lrValyeBytes = lre.getLrValue().getBytes();
189             lrValueTagLen[i] = 1 + TLV.getNbBytes( lrValyeBytes.length ) + lrValyeBytes.length;
190 
191             lastReqSeqLen[i] = 1 + TLV.getNbBytes( lrTypeTagLen[i] ) + lrTypeTagLen[i] +
192                 1 + TLV.getNbBytes( lrValueTagLen[i] ) + lrValueTagLen[i];
193 
194             lastReqSeqSeqLen += 1 + TLV.getNbBytes( lastReqSeqLen[i] ) + lastReqSeqLen[i];
195             i++;
196         }
197 
198         return 1 + TLV.getNbBytes( lastReqSeqSeqLen ) + lastReqSeqSeqLen;
199     }
200 
201 
202     /**
203      * Encode the LastReq message to a PDU. 
204      * 
205      * <pre>
206      * LastReq :
207      * 
208      * 0x30 LL
209      *   0x30 LL
210      *     0xA0 LL 
211      *       0x02 0x01 lrType
212      *     0xA1 0x11 
213      *       0x18 0x0F lrValue
214      * </pre>
215      * 
216      * @param buffer The buffer where to put the PDU. It should have been allocated
217      * before, with the right size.
218      * @return The constructed PDU.
219      */
220     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
221     {
222         if ( buffer == null )
223         {
224             throw new EncoderException( I18n.err( I18n.ERR_148 ) );
225         }
226 
227         try
228         {
229             // The lastRequest SEQ OF Tag
230             buffer.put( UniversalTag.SEQUENCE.getValue() );
231             buffer.put( TLV.getBytes( lastReqSeqSeqLen ) );
232 
233             int i = 0;
234 
235             for ( LastReqEntry lre : lastReqs )
236             {
237                 buffer.put( UniversalTag.SEQUENCE.getValue() );
238                 buffer.put( TLV.getBytes( lastReqSeqLen[i] ) );
239 
240                 // the lrType
241                 buffer.put( ( byte ) KerberosConstants.LAST_REQ_LR_TYPE_TAG );
242                 buffer.put( TLV.getBytes( lrTypeTagLen[i] ) );
243                 BerValue.encode( buffer, lre.getLrType().getValue() );
244 
245                 // the lrValue tag
246                 buffer.put( ( byte ) KerberosConstants.LAST_REQ_LR_VALUE_TAG );
247                 buffer.put( TLV.getBytes( lrValueTagLen[i] ) );
248 
249                 // the lrValue value
250                 buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
251                 buffer.put( ( byte ) 0x0F );
252                 buffer.put( lre.getLrValue().getBytes() );
253             }
254         }
255         catch ( BufferOverflowException boe )
256         {
257             LOG.error( I18n.err( I18n.ERR_139, 1 + TLV.getNbBytes( lastReqSeqSeqLen )
258                 + lastReqSeqSeqLen, buffer.capacity() ) );
259             throw new EncoderException( I18n.err( I18n.ERR_138 ) , boe);
260         }
261 
262         if ( IS_DEBUG )
263         {
264             LOG.debug( "LastReq encoding : {}", Strings.dumpBytes( buffer.array() ) );
265             LOG.debug( "LastReq initial value : {}", this );
266         }
267 
268         return buffer;
269     }
270 
271 
272     /**
273      * @see Object#toString()
274      */
275     public String toString( String tabs )
276     {
277         StringBuilder sb = new StringBuilder();
278 
279         sb.append( tabs ).append( "LastReq : \n" );
280 
281         for ( LastReqEntry lre : lastReqs )
282         {
283             sb.append( lre.toString( tabs + "    " ) );
284         }
285 
286         return sb.toString();
287     }
288 
289 
290     /**
291      * @see Object#toString()
292      */
293     public String toString()
294     {
295         return toString( "" );
296     }
297 }