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  
21  package org.apache.directory.shared.kerberos.components;
22  
23  
24  import java.nio.BufferOverflowException;
25  import java.nio.ByteBuffer;
26  
27  import org.apache.directory.api.asn1.Asn1Object;
28  import org.apache.directory.api.asn1.EncoderException;
29  import org.apache.directory.api.asn1.ber.tlv.BerValue;
30  import org.apache.directory.api.asn1.ber.tlv.TLV;
31  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
32  import org.apache.directory.api.util.Strings;
33  import org.apache.directory.server.i18n.I18n;
34  import org.apache.directory.shared.kerberos.KerberosConstants;
35  import org.apache.directory.shared.kerberos.KerberosTime;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  
40  /**
41   * The EncKrbPrivPart structure is used to store a EncKrbPrivPart associated to a type.
42   * 
43   * The ASN.1 grammar is :
44   * <pre>
45   * EncKrbPrivPart  ::= [APPLICATION 28] SEQUENCE {
46   *      user-data       [0] OCTET STRING,
47   *      timestamp       [1] KerberosTime OPTIONAL,
48   *      usec            [2] Microseconds OPTIONAL,
49   *      seq-number      [3] UInt32 OPTIONAL,
50   *      s-address       [4] HostAddress -- sender's addr --,
51   *      r-address       [5] HostAddress OPTIONAL -- recip's addr
52   * }
53   * </pre>
54   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
55   */
56  //NOTE: this ASN.1 structure is quite identical to KrbSafeBody
57  public class EncKrbPrivPart implements Asn1Object
58  {
59      /** The logger */
60      private static final Logger log = LoggerFactory.getLogger( EncKrbPrivPart.class );
61  
62      /** Speedup for logs */
63      private static final boolean IS_DEBUG = log.isDebugEnabled();
64  
65      /** the user data */
66      private byte[] userData;
67  
68      /** the current time of the sender */
69      private KerberosTime timestamp;
70  
71      /** the microsecond part of the timestamp */
72      private Integer usec;
73  
74      /** the sequence number */
75      private Integer seqNumber;
76  
77      /** the sender's address */
78      private HostAddress senderAddress;
79  
80      /** the recipient's address */
81      private HostAddress recipientAddress;
82  
83      // Storage for computed lengths
84      private int userDataLen;
85      private int timestampLen;
86      private int usecLen;
87      private int seqNumberLen;
88      private int senderAddressLen;
89      private int recipientAddressLen;
90      private int encKrbPrivPartSeqLen;
91      private int encKrbPrivPartLen;
92  
93  
94      /**
95       * @return the userData
96       */
97      public byte[] getUserData()
98      {
99          return userData;
100     }
101 
102 
103     /**
104      * @param userData the userData to set
105      */
106     public void setUserData( byte[] userData )
107     {
108         this.userData = userData;
109     }
110 
111 
112     /**
113      * @return the timestamp
114      */
115     public KerberosTime getTimestamp()
116     {
117         return timestamp;
118     }
119 
120 
121     /**
122      * @param timestamp the timestamp to set
123      */
124     public void setTimestamp( KerberosTime timestamp )
125     {
126         this.timestamp = timestamp;
127     }
128 
129 
130     /**
131      * @return the usec
132      */
133     public int getUsec()
134     {
135         if ( usec == null )
136         {
137             return 0;
138         }
139 
140         return usec;
141     }
142 
143 
144     /**
145      * @param usec the usec to set
146      */
147     public void setUsec( int usec )
148     {
149         this.usec = usec;
150     }
151 
152 
153     /**
154      * @return the seqNumber
155      */
156     public int getSeqNumber()
157     {
158         if ( seqNumber == null )
159         {
160             return 0;
161         }
162 
163         return seqNumber;
164     }
165 
166 
167     /**
168      * @param seqNumber the seqNumber to set
169      */
170     public void setSeqNumber( int seqNumber )
171     {
172         this.seqNumber = seqNumber;
173     }
174 
175 
176     /**
177      * @return the senderAddress
178      */
179     public HostAddress getSenderAddress()
180     {
181         return senderAddress;
182     }
183 
184 
185     /**
186      * @param senderAddress the senderAddress to set
187      */
188     public void setSenderAddress( HostAddress senderAddress )
189     {
190         this.senderAddress = senderAddress;
191     }
192 
193 
194     /**
195      * @return the recipientAddress
196      */
197     public HostAddress getRecipientAddress()
198     {
199         return recipientAddress;
200     }
201 
202 
203     /**
204      * @param recipientAddress the recipientAddress to set
205      */
206     public void setRecipientAddress( HostAddress recipientAddress )
207     {
208         this.recipientAddress = recipientAddress;
209     }
210 
211 
212     /**
213      * Compute the EncKrbPrivPart length:
214      * 
215      * <pre>
216      * 0x7C L0 EncKrbPrivPart
217      *  |
218      *  |
219      * 0x30 L1 EncKrbPrivPart SEQ
220      *  |
221      *  +--&gt; 0xA0 L2 user-data tag
222      *  |     |
223      *  |     +--&gt; 0x04 L2-1 user-data (Octet String)
224      *  |
225      *  +--&gt; 0xA1 0x11 timestamp tag
226      *  |     |
227      *  |     +--&gt; 0x18 0x0F timestamp (KerberosTime)
228      *  |
229      *  +--&gt; 0xA2 L3 usec tag
230      *  |     |
231      *  |     +--&gt; 0x02 L3-1 usec (Microseconds)
232      *  |
233      *  +--&gt; 0xA3 L4 seq-number tag
234      *  |     |
235      *  |     +--&gt; 0x02 L4-1 seqnumber (UInt32)
236      *  |
237      *  +--&gt; 0xA4 L5 s-address tag
238      *  |     |
239      *  |     +--&gt; 0x30 L5-1 s-address (HostAddress)
240      *  |
241      *  +--&gt; 0xA5 L6 r-address tag
242      *        |
243      *        +--&gt; 0x30 L6-1 r-address (HostAddress)
244      * </pre>       
245      */
246     @Override
247     public int computeLength()
248     {
249         userDataLen = 1 + TLV.getNbBytes( userData.length ) + userData.length;
250         encKrbPrivPartSeqLen = 1 + TLV.getNbBytes( userDataLen ) + userDataLen;
251 
252         senderAddressLen = senderAddress.computeLength();
253         encKrbPrivPartSeqLen += 1 + TLV.getNbBytes( senderAddressLen ) + senderAddressLen;
254 
255         if ( timestamp != null )
256         {
257             timestampLen = timestamp.getBytes().length;
258             timestampLen = 1 + TLV.getNbBytes( timestampLen ) + timestampLen;
259             encKrbPrivPartSeqLen += 1 + TLV.getNbBytes( timestampLen ) + timestampLen;
260         }
261 
262         if ( usec != null )
263         {
264             usecLen = BerValue.getNbBytes( usec );
265             usecLen = 1 + TLV.getNbBytes( usecLen ) + usecLen;
266             encKrbPrivPartSeqLen += 1 + TLV.getNbBytes( usecLen ) + usecLen;
267         }
268 
269         if ( seqNumber != null )
270         {
271             seqNumberLen = BerValue.getNbBytes( seqNumber );
272             seqNumberLen = 1 + TLV.getNbBytes( seqNumberLen ) + seqNumberLen;
273             encKrbPrivPartSeqLen += 1 + TLV.getNbBytes( seqNumberLen ) + seqNumberLen;
274         }
275 
276         if ( recipientAddress != null )
277         {
278             recipientAddressLen = recipientAddress.computeLength();
279             encKrbPrivPartSeqLen += 1 + TLV.getNbBytes( recipientAddressLen ) + recipientAddressLen;
280         }
281 
282         encKrbPrivPartLen = 1 + TLV.getNbBytes( encKrbPrivPartSeqLen ) + encKrbPrivPartSeqLen;
283 
284         return 1 + TLV.getNbBytes( encKrbPrivPartLen ) + encKrbPrivPartLen;
285     }
286 
287 
288     /**
289      * {@inheritDoc}
290      */
291     @Override
292     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
293     {
294         if ( buffer == null )
295         {
296             throw new EncoderException( I18n.err( I18n.ERR_148 ) );
297         }
298 
299         try
300         {
301             buffer.put( ( byte ) KerberosConstants.ENC_KRB_PRIV_PART_TAG );
302             buffer.put( TLV.getBytes( encKrbPrivPartLen ) );
303 
304             buffer.put( UniversalTag.SEQUENCE.getValue() );
305             buffer.put( TLV.getBytes( encKrbPrivPartSeqLen ) );
306 
307             // user-data
308             buffer.put( ( byte ) KerberosConstants.KRB_SAFE_BODY_USER_DATA_TAG );
309             buffer.put( TLV.getBytes( userDataLen ) );
310             BerValue.encode( buffer, userData );
311 
312             if ( timestamp != null )
313             {
314                 // timestamp tag
315                 buffer.put( ( byte ) KerberosConstants.KRB_SAFE_BODY_TIMESTAMP_TAG );
316                 buffer.put( TLV.getBytes( timestampLen ) );
317 
318                 // timestamp value
319                 buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
320                 buffer.put( ( byte ) 0x0F );
321                 buffer.put( timestamp.getBytes() );
322             }
323 
324             if ( usec != null )
325             {
326                 // usec
327                 buffer.put( ( byte ) KerberosConstants.KRB_SAFE_BODY_USEC_TAG );
328                 buffer.put( TLV.getBytes( usecLen ) );
329                 BerValue.encode( buffer, usec );
330             }
331 
332             if ( seqNumber != null )
333             {
334                 // seq-number
335                 buffer.put( ( byte ) KerberosConstants.KRB_SAFE_BODY_SEQ_NUMBER_TAG );
336                 buffer.put( TLV.getBytes( seqNumberLen ) );
337                 BerValue.encode( buffer, seqNumber );
338             }
339 
340             // s-address
341             buffer.put( ( byte ) KerberosConstants.KRB_SAFE_BODY_SENDER_ADDRESS_TAG );
342             buffer.put( TLV.getBytes( senderAddressLen ) );
343             senderAddress.encode( buffer );
344 
345             if ( recipientAddress != null )
346             {
347                 // s-address
348                 buffer.put( ( byte ) KerberosConstants.KRB_SAFE_BODY_RECIPIENT_ADDRESS_TAG );
349                 buffer.put( TLV.getBytes( recipientAddressLen ) );
350                 recipientAddress.encode( buffer );
351             }
352         }
353         catch ( BufferOverflowException boe )
354         {
355             log.error( I18n.err( I18n.ERR_735_CANNOT_ENCODE_KRBSAFEBODY, 1 + TLV.getNbBytes( encKrbPrivPartLen )
356                 + encKrbPrivPartLen, buffer.capacity() ) );
357             throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
358         }
359 
360         if ( IS_DEBUG )
361         {
362             log.debug( "EncKrbPrivPart encoding : {}", Strings.dumpBytes( buffer.array() ) );
363             log.debug( "EncKrbPrivPart initial value : {}", this );
364         }
365 
366         return buffer;
367     }
368 
369 
370     /**
371      * @see Object#toString()
372      */
373     public String toString()
374     {
375         StringBuilder sb = new StringBuilder();
376 
377         sb.append( "EncKrbPrivPart : {\n" );
378         sb.append( "    user-data: " ).append( Strings.dumpBytes( userData ) ).append( '\n' );
379 
380         if ( timestamp != null )
381         {
382             sb.append( "    timestamp: " ).append( timestamp.getDate() ).append( '\n' );
383         }
384 
385         if ( usec != null )
386         {
387             sb.append( "    usec: " ).append( usec ).append( '\n' );
388         }
389 
390         if ( seqNumber != null )
391         {
392             sb.append( "    seq-number: " ).append( seqNumber ).append( '\n' );
393         }
394 
395         sb.append( "    s-address: " ).append( senderAddress ).append( '\n' );
396 
397         if ( recipientAddress != null )
398         {
399             sb.append( "    r-address: " ).append( recipientAddress ).append( '\n' );
400         }
401 
402         sb.append( "}\n" );
403 
404         return sb.toString();
405     }
406 }