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.messages;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  
26  import org.apache.directory.api.asn1.EncoderException;
27  import org.apache.directory.api.asn1.ber.tlv.BerValue;
28  import org.apache.directory.api.asn1.ber.tlv.TLV;
29  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
30  import org.apache.directory.api.util.Strings;
31  import org.apache.directory.server.i18n.I18n;
32  import org.apache.directory.shared.kerberos.KerberosConstants;
33  import org.apache.directory.shared.kerberos.KerberosMessageType;
34  import org.apache.directory.shared.kerberos.KerberosTime;
35  import org.apache.directory.shared.kerberos.components.EncryptionKey;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  
40  /**
41   * Encrypted part of the application response.
42   *  It will store the object described by the ASN.1 grammar :
43   * <pre>
44   * EncAPRepPart    ::= [APPLICATION 27] SEQUENCE {
45   *         ctime           [0] KerberosTime,
46   *         cusec           [1] Microseconds,
47   *         subkey          [2] &lt;EncryptionKey&gt; OPTIONAL,
48   *         seq-number      [3] UInt32 OPTIONAL
49   * }
50   * </pre>
51   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
52   */
53  public class EncApRepPart extends KerberosMessage
54  {
55      /** The logger */
56      private static final Logger LOG = LoggerFactory.getLogger( EncApRepPart.class );
57  
58      /** Speedup for logs */
59      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
60  
61      /** The client time */
62      private KerberosTime ctime;
63  
64      /** the microsecond part of the client's timestamp */
65      private int cusec;
66  
67      /** Encryption key */
68      private EncryptionKey subkey; //optional
69  
70      /** Sequence number */
71      private Integer seqNumber; //optional
72  
73      // Storage for computed lengths
74      private int ctimeLength;
75      private int cusecLength;
76      private int subKeyLength;
77      private int seqNumberLength;
78      private int encApRepPartSeqLength;
79      private int encApRepPartLength;
80  
81  
82      /**
83       * Creates a new instance of EncApRepPart.
84       */
85      public EncApRepPart()
86      {
87          super( KerberosMessageType.ENC_AP_REP_PART );
88      }
89  
90  
91      /**
92       * Returns the client {@link KerberosTime}.
93       *
94       * @return The client {@link KerberosTime}.
95       */
96      public KerberosTime getCTime()
97      {
98          return ctime;
99      }
100 
101 
102     /**
103      * @param ctime the ctime to set
104      */
105     public void setCTime( KerberosTime ctime )
106     {
107         this.ctime = ctime;
108     }
109 
110 
111     /**
112      * @return the cusec
113      */
114     public int getCusec()
115     {
116         return cusec;
117     }
118 
119 
120     /**
121      * @param cusec the cusec to set
122      */
123     public void setCusec( int cusec )
124     {
125         this.cusec = cusec;
126     }
127 
128 
129     /**
130      * @return the subkey
131      */
132     public EncryptionKey getSubkey()
133     {
134         return subkey;
135     }
136 
137 
138     /**
139      * @param subkey the subkey to set
140      */
141     public void setSubkey( EncryptionKey subkey )
142     {
143         this.subkey = subkey;
144     }
145 
146 
147     /**
148      * @return the seqNumber
149      */
150     public Integer getSeqNumber()
151     {
152         return seqNumber;
153     }
154 
155 
156     /**
157      * @param seqNumber the seqNumber to set
158      */
159     public void setSeqNumber( Integer seqNumber )
160     {
161         this.seqNumber = seqNumber;
162     }
163 
164 
165     /**
166      * Compute the Authenticator length
167      * <pre>
168      * Authenticator :
169      * 
170      * 0x7B L1 EncApRepPart [APPLICATION 27]
171      *  |
172      *  +--&gt; 0x30 L2 SEQ
173      *        |
174      *        +--&gt; 0xA0 11 ctime tag
175      *        |     |
176      *        |     +--&gt; 0x18 0x0F ttt ctime (KerberosTime)
177      *        |
178      *        +--&gt; 0xA1 L3 cusec tag
179      *        |     |
180      *        |     +--&gt; 0x02 L3-1 cusec (INTEGER)
181      *        |
182      *        +--&gt; 0xA2 L4 subkey (EncryptionKey)
183      *        |
184      *        +--&gt; 0xA3 L5 seq-number tag
185      *              |
186      *              +--&gt; 0x02 L5-1 NN seq-number (INTEGER)
187      * </pre>
188      */
189     @Override
190     public int computeLength()
191     {
192         // Compute the ctime length.
193         ctimeLength = 1 + 1 + 0x0F;
194         encApRepPartSeqLength = 1 + TLV.getNbBytes( ctimeLength ) + ctimeLength;
195 
196         // Compute the cusec length
197         cusecLength = 1 + 1 + BerValue.getNbBytes( cusec );
198         encApRepPartSeqLength += 1 + TLV.getNbBytes( cusecLength ) + cusecLength;
199 
200         // Compute the subkey length, if any
201         if ( subkey != null )
202         {
203             subKeyLength = subkey.computeLength();
204             encApRepPartSeqLength += 1 + TLV.getNbBytes( subKeyLength ) + subKeyLength;
205         }
206 
207         // Compute the sequence size, if any
208         if ( seqNumber != null )
209         {
210             seqNumberLength = 1 + 1 + BerValue.getNbBytes( seqNumber );
211             encApRepPartSeqLength += 1 + TLV.getNbBytes( seqNumberLength ) + seqNumberLength;
212         }
213 
214         encApRepPartLength = 1 + TLV.getNbBytes( encApRepPartSeqLength ) + encApRepPartSeqLength;
215 
216         return 1 + TLV.getNbBytes( encApRepPartLength ) + encApRepPartLength;
217     }
218 
219 
220     /**
221      * Encode the EncApRepPart message to a PDU. 
222      * <pre>
223      * EncApRepPart :
224      * 
225      * 0x7B LL
226      *   0x30 LL
227      *     0xA0 0x11 
228      *       0x18 0x0F ttt ctime 
229      *     0xA1 LL 
230      *       0x02 LL NN cusec
231      *    [0xA2 LL
232      *       0x30 LL abcd] subkey
233      *    [0xA3 LL
234      *       0x02 LL NN] seq-number
235      * </pre>
236      * @return The constructed PDU.
237      */
238     @Override
239     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
240     {
241         if ( buffer == null )
242         {
243             buffer = ByteBuffer.allocate( computeLength() );
244         }
245 
246         try
247         {
248             // The EncApRepPart APPLICATION Tag
249             buffer.put( ( byte ) KerberosConstants.ENC_AP_REP_PART_TAG );
250             buffer.put( TLV.getBytes( encApRepPartLength ) );
251 
252             // The EncApRepPart SEQ Tag
253             buffer.put( ( byte ) UniversalTag.SEQUENCE.getValue() );
254             buffer.put( TLV.getBytes( encApRepPartSeqLength ) );
255 
256             // The ctime ------------------------------------------------------
257             // The tag
258             buffer.put( ( byte ) KerberosConstants.ENC_AP_REP_PART_CTIME_TAG );
259             buffer.put( ( byte ) 0x11 );
260 
261             // The value
262             buffer.put( ( byte ) UniversalTag.GENERALIZED_TIME.getValue() );
263             buffer.put( ( byte ) 0x0F );
264             buffer.put( ctime.getBytes() );
265 
266             // The cusec ------------------------------------------------------
267             // The tag
268             buffer.put( ( byte ) KerberosConstants.ENC_AP_REP_PART_CUSEC_TAG );
269             buffer.put( TLV.getBytes( cusecLength ) );
270 
271             // The value
272             BerValue.encode( buffer, cusec );
273 
274             // The subkey if any ----------------------------------------------
275             if ( subkey != null )
276             {
277                 // The tag
278                 buffer.put( ( byte ) KerberosConstants.ENC_AP_REP_PART_SUB_KEY_TAG );
279                 buffer.put( TLV.getBytes( subKeyLength ) );
280 
281                 // The value
282                 subkey.encode( buffer );
283             }
284 
285             // The seq-number, if any -----------------------------------------
286             if ( seqNumber != null )
287             {
288                 // The tag
289                 buffer.put( ( byte ) KerberosConstants.ENC_AP_REP_PART_SEQ_NUMBER_TAG );
290                 buffer.put( TLV.getBytes( seqNumberLength ) );
291 
292                 // The value
293                 BerValue.encode( buffer, seqNumber );
294             }
295 
296         }
297         catch ( BufferOverflowException boe )
298         {
299             LOG.error( I18n.err( I18n.ERR_139, 1 + TLV.getNbBytes( encApRepPartLength )
300                 + encApRepPartLength, buffer.capacity() ) );
301             throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
302         }
303 
304         if ( IS_DEBUG )
305         {
306             LOG.debug( "EncApRepPart encoding : {}", Strings.dumpBytes( buffer.array() ) );
307             LOG.debug( "EncApRepPart initial value : {}", this );
308         }
309 
310         return buffer;
311     }
312 
313 
314     /**
315      * @see Object#toString()
316      */
317     public String toString()
318     {
319         StringBuilder sb = new StringBuilder();
320 
321         sb.append( "EncApRepPart : \n" );
322 
323         sb.append( "    ctime : " ).append( ctime ).append( '\n' );
324         sb.append( "    cusec : " ).append( cusec ).append( '\n' );
325 
326         if ( subkey != null )
327         {
328             sb.append( "    subkey : " ).append( subkey ).append( '\n' );
329         }
330 
331         if ( seqNumber != null )
332         {
333             sb.append( "    seq-number : " ).append( seqNumber ).append( '\n' );
334         }
335 
336         return sb.toString();
337     }
338 }