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.AuthorizationData;
36  import org.apache.directory.shared.kerberos.components.Checksum;
37  import org.apache.directory.shared.kerberos.components.EncryptionKey;
38  import org.apache.directory.shared.kerberos.components.PrincipalName;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  
43  /**
44   * A structure to hold the authenticator data.
45   *  It will store the object described by the ASN.1 grammar :
46   * <pre>
47   * Authenticator   ::= [APPLICATION 2] SEQUENCE  {
48   *         authenticator-vno       [0] INTEGER (5),
49   *         crealm                  [1] Realm,
50   *         cname                   [2] &lt;PrincipalName&gt;,
51   *         cksum                   [3] &lt;Checksum&gt; OPTIONAL,
52   *         cusec                   [4] Microseconds,
53   *         ctime                   [5] KerberosTime,
54   *         subkey                  [6] &lt;EncryptionKey&gt; OPTIONAL,
55   *         seq-number              [7] UInt32 OPTIONAL,
56   *         authorization-data      [8] &lt;AuthorizationData&gt; OPTIONAL
57   * }
58   * </pre>
59   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
60   */
61  public class Authenticator extends KerberosMessage
62  {
63      /** The logger */
64      private static final Logger LOG = LoggerFactory.getLogger( Authenticator.class );
65  
66      /** Speedup for logs */
67      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
68  
69      /** The authenticator version number */
70      private int versionNumber;
71  
72      /** The client realm */
73      private String crealm;
74  
75      /** The client principalName */
76      private PrincipalName cname;
77  
78      /** The checksum */
79      private Checksum cksum;
80  
81      /** The client microseconds */
82      private int cusec;
83  
84      /** The client time */
85      private KerberosTime ctime;
86  
87      /** The sub-session key */
88      private EncryptionKey subKey;
89  
90      /** The sequence number */
91      private Integer seqNumber;
92  
93      /** The authorization Data */
94      private AuthorizationData authorizationData;
95  
96      // Storage for computed lengths
97      private int authenticatorVnoLength;
98      private int crealmLength;
99      private byte[] crealmBytes;
100     private int cnameLength;
101     private int cksumLength;
102     private int cusecLength;
103     private int ctimeLength;
104     private int subkeyLength;
105     private int seqNumberLength;
106     private int authorizationDataLength;
107     private int authenticatorSeqLength;
108     private int authenticatorLength;
109 
110 
111     /**
112      * Creates a new instance of Authenticator.
113      */
114     public Authenticator()
115     {
116         super( KerberosMessageType.AUTHENTICATOR );
117         versionNumber = getProtocolVersionNumber();
118     }
119 
120 
121     /**
122      * Returns the {@link AuthorizationData}.
123      *
124      * @return The {@link AuthorizationData}.
125      */
126     public AuthorizationData getAuthorizationData()
127     {
128         return authorizationData;
129     }
130 
131 
132     /**
133      * @param authorizationData the authorizationData to set
134      */
135     public void setAuthorizationData( AuthorizationData authorizationData )
136     {
137         this.authorizationData = authorizationData;
138     }
139 
140 
141     /**
142      * @return the cksum
143      */
144     public Checksum getCksum()
145     {
146         return cksum;
147     }
148 
149 
150     /**
151      * @param cksum the cksum to set
152      */
153     public void setCksum( Checksum cksum )
154     {
155         this.cksum = cksum;
156     }
157 
158 
159     /**
160      * @return the cname
161      */
162     public PrincipalName getCName()
163     {
164         return cname;
165     }
166 
167 
168     /**
169      * @param cname the cname to set
170      */
171     public void setCName( PrincipalName cname )
172     {
173         this.cname = cname;
174     }
175 
176 
177     /**
178      * @return the crealm
179      */
180     public String getCRealm()
181     {
182         return crealm;
183     }
184 
185 
186     /**
187      * @param crealm the crealm to set
188      */
189     public void setCRealm( String crealm )
190     {
191         this.crealm = crealm;
192     }
193 
194 
195     /**
196      * @return the ctime
197      */
198     public KerberosTime getCtime()
199     {
200         return ctime;
201     }
202 
203 
204     /**
205      * @param ctime the ctime to set
206      */
207     public void setCTime( KerberosTime ctime )
208     {
209         this.ctime = ctime;
210     }
211 
212 
213     /**
214      * @return the cusec
215      */
216     public int getCusec()
217     {
218         return cusec;
219     }
220 
221 
222     /**
223      * @param cusec the cusec to set
224      */
225     public void setCusec( int cusec )
226     {
227         this.cusec = cusec;
228     }
229 
230 
231     /**
232      * @return the seqNumber
233      */
234     public Integer getSeqNumber()
235     {
236         return seqNumber;
237     }
238 
239 
240     /**
241      * @param seqNumber the seqNumber to set
242      */
243     public void setSeqNumber( int seqNumber )
244     {
245         this.seqNumber = Integer.valueOf( seqNumber );
246     }
247 
248 
249     /**
250      * @return the subKey
251      */
252     public EncryptionKey getSubKey()
253     {
254         return subKey;
255     }
256 
257 
258     /**
259      * @param subKey the subKey to set
260      */
261     public void setSubKey( EncryptionKey subKey )
262     {
263         this.subKey = subKey;
264     }
265 
266 
267     /**
268      * Returns the version number of the {@link Authenticator}.
269      *
270      * @return The version number of the {@link Authenticator}.
271      */
272     public int getVersionNumber()
273     {
274         return versionNumber;
275     }
276 
277 
278     /**
279      * @param versionNumber the versionNumber to set
280      */
281     public void setVersionNumber( int versionNumber )
282     {
283         this.versionNumber = versionNumber;
284     }
285 
286 
287     /**
288      * Compute the Authenticator length
289      * <pre>
290      * Authenticator :
291      * 
292      * 0x62 L1 Authenticator [APPLICATION 2]
293      *  |
294      *  +--&gt; 0x30 L2 Authenticator SEQUENCE
295      *        |
296      *        +--&gt; 0xA0 03 authenticator-vno tag
297      *        |     |
298      *        |     +--&gt; 0x02 0x01 0x05 authenticator-vno (int, 5)
299      *        |
300      *        +--&gt; 0xA1 L3 crealm tag
301      *        |     |
302      *        |     +--&gt; 0x1B L3-1 crealm (KerberosString)
303      *        |
304      *        +--&gt; 0xA2 L4 cname (PrincipalName)
305      *        |
306      *        +--&gt; 0xA3 L5 cksum (CheckSum)
307      *        |
308      *        +--&gt; 0xA4 L6 cusec tag
309      *        |     |
310      *        |     +--&gt; 0x02 L6-1 nnn cusec value (Integer)
311      *        |
312      *        +--&gt; 0xA5 0x11 ctime tag
313      *        |     |
314      *        |     +--&gt; 0x18 0x0F ttt ctime (KerberosTime)
315      *        |
316      *        +--&gt; 0xA6 L7 subkey (EncryptionKey)
317      *        |
318      *        +--&gt; 0xA7 L8 seq-number tag
319      *        |     |
320      *        |     +--&gt; 0x02 L8-1 nnn seq-number (Integer)
321      *        |
322      *        +--&gt; 0xA8 L9 authorization-data (AuthorizationData)
323      * </pre>
324      */
325     @Override
326     public int computeLength()
327     {
328         reset();
329 
330         // Compute the Authenticator version length.
331         authenticatorVnoLength = 1 + 1 + BerValue.getNbBytes( getVersionNumber() );
332         authenticatorSeqLength =  1 + TLV.getNbBytes( authenticatorVnoLength ) + authenticatorVnoLength;
333 
334         // Compute the  crealm length.
335         crealmBytes = Strings.getBytesUtf8( crealm );
336         crealmLength = 1 + TLV.getNbBytes( crealmBytes.length ) + crealmBytes.length;
337         authenticatorSeqLength += 1 + TLV.getNbBytes( crealmLength ) + crealmLength;
338 
339         // Compute the cname length
340         cnameLength = cname.computeLength();
341         authenticatorSeqLength += 1 + TLV.getNbBytes( cnameLength ) + cnameLength;
342 
343         // Compute the cksum length if any
344         if ( cksum != null )
345         {
346             cksumLength = cksum.computeLength();
347             authenticatorSeqLength += 1 + TLV.getNbBytes( cksumLength ) + cksumLength;
348         }
349 
350         // Compute the cusec length
351         cusecLength = 1 + 1 + BerValue.getNbBytes( cusec );
352         authenticatorSeqLength += 1 + TLV.getNbBytes( cusecLength ) + cusecLength;
353 
354         // Compute the ctime length
355         ctimeLength = 1 + 1 + 0x0F;
356         authenticatorSeqLength += 1 + 1 + ctimeLength;
357 
358         // Compute the subkey length if any
359         if ( subKey != null )
360         {
361             subkeyLength = subKey.computeLength();
362             authenticatorSeqLength += 1 + TLV.getNbBytes( subkeyLength ) + subkeyLength;
363         }
364 
365         // Compute the seq-number  length if any
366         if ( seqNumber != null )
367         {
368             seqNumberLength = 1 + 1 + BerValue.getNbBytes( seqNumber );
369             authenticatorSeqLength += 1 + TLV.getNbBytes( seqNumberLength ) + seqNumberLength;
370         }
371 
372         // Compute the authorization-data length if any
373         if ( authorizationData != null )
374         {
375             authorizationDataLength = authorizationData.computeLength();
376             authenticatorSeqLength += 1 + TLV.getNbBytes( authorizationDataLength ) + authorizationDataLength;
377         }
378 
379         // compute the global size
380         authenticatorLength = 1 + TLV.getNbBytes( authenticatorSeqLength ) + authenticatorSeqLength;
381 
382         return 1 + TLV.getNbBytes( authenticatorLength ) + authenticatorLength;
383     }
384 
385 
386     /**
387      * Encode the Authenticator message to a PDU.
388      * <pre>
389      * Authenticator :
390      * 
391      * 0x62 LL
392      *   0x30 LL
393      *     0xA0 0x03
394      *       0x02 0x01 0x05 authenticator-vno
395      *     0xA1 LL
396      *       0x1B LL abcd crealm
397      *     0xA2 LL
398      *       0x30 LL abcd cname
399      *    [0xA3 LL
400      *       0x30 LL abcd] cksum
401      *     0xA4 LL
402      *       0x02 LL nnn  cusec
403      *     0xA5 0x11
404      *       0x18 0x0F ttt ctime
405      *    [0xA6 LL
406      *       0x30 LL abcd] subkey
407      *    [0xA7 LL
408      *       0x02 LL nnn] seq-number
409      *    [0xA8 LL
410      *       0x30 LL abcd] authorization-data
411      * </pre>
412      * @return The constructed PDU.
413      */
414     @Override
415     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
416     {
417         if ( buffer == null )
418         {
419             buffer = ByteBuffer.allocate( computeLength() );
420         }
421 
422         try
423         {
424             // The Authenticator APPLICATION Tag
425             buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_TAG );
426             buffer.put( TLV.getBytes( authenticatorLength ) );
427 
428             // The Authenticator SEQUENCE Tag
429             buffer.put( UniversalTag.SEQUENCE.getValue() );
430             buffer.put( TLV.getBytes( authenticatorSeqLength ) );
431 
432             // The authenticator-vno ------------------------------------------
433             // The tag
434             buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_AUTHENTICATOR_VNO_TAG );
435             buffer.put( TLV.getBytes( authenticatorVnoLength ) );
436 
437             // The value
438             BerValue.encode( buffer, getVersionNumber() );
439             
440             // The crealm -----------------------------------------------------
441             // The tag
442             buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CREALM_TAG );
443             buffer.put( TLV.getBytes( crealmLength ) );
444 
445             // The value
446             buffer.put( UniversalTag.GENERAL_STRING.getValue() );
447             buffer.put( TLV.getBytes( crealmBytes.length ) );
448             buffer.put( crealmBytes );
449 
450             // The cname ------------------------------------------------------
451             // The tag
452             buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CNAME_TAG );
453             buffer.put( TLV.getBytes( cnameLength ) );
454 
455             // The value
456             cname.encode( buffer );
457 
458             // The cksum, if any ----------------------------------------------
459             if ( cksum != null )
460             {
461                 // The tag
462                 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CKSUM_TAG );
463                 buffer.put( TLV.getBytes( cksumLength ) );
464 
465                 // The value
466                 cksum.encode( buffer );
467             }
468 
469             // The cusec ------------------------------------------------------
470             // The tag
471             buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CUSEC_TAG );
472             buffer.put( TLV.getBytes( cusecLength ) );
473 
474             // The value
475             BerValue.encode( buffer, cusec );
476 
477             // The ctime ------------------------------------------------------
478             // The tag
479             buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_CTIME_TAG );
480             buffer.put( TLV.getBytes( ctimeLength ) );
481 
482             // The value
483             buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
484             buffer.put( ( byte ) 0x0F );
485             buffer.put( ctime.getBytes() );
486 
487             // The subkey if any ---------------------------------------------------
488             if ( subKey != null )
489             {
490                 // The tag
491                 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_SUBKEY_TAG );
492                 buffer.put( TLV.getBytes( subkeyLength ) );
493 
494                 // The value
495                 subKey.encode( buffer );
496             }
497 
498             // The seq-number, if any -----------------------------------------
499             if ( seqNumber != null )
500             {
501                 // The tag
502                 buffer.put( (byte)KerberosConstants.AUTHENTICATOR_SEQ_NUMBER_TAG );
503                 buffer.put( TLV.getBytes( seqNumberLength ) );
504                 
505                 // The value
506                 BerValue.encode( buffer, seqNumber );
507             }
508             
509             // The authorization-data, if any ---------------------------------
510             if ( authorizationData != null )
511             {
512                 // The tag
513                 buffer.put( ( byte ) KerberosConstants.AUTHENTICATOR_AUTHORIZATION_DATA_TAG );
514                 buffer.put( TLV.getBytes( authorizationDataLength ) );
515 
516                 // The value
517                 authorizationData.encode( buffer );
518             }
519         }
520         catch ( BufferOverflowException boe )
521         {
522             LOG.error( I18n.err( I18n.ERR_139, 1 + TLV.getNbBytes( 0 )
523                 + 0, buffer.capacity() ) );
524             throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
525         }
526 
527         if ( IS_DEBUG )
528         {
529             LOG.debug( "Authenticator encoding : {}", Strings.dumpBytes( buffer.array() ) );
530             LOG.debug( "Authenticator initial value : {}", this );
531         }
532 
533         return buffer;
534     }
535 
536 
537     /**
538      * reset the fields used while computing length
539      */
540     private void reset()
541     {
542         authenticatorVnoLength = 0;
543         crealmLength = 0;
544         crealmBytes = null;
545         cnameLength = 0;
546         cksumLength = 0;
547         cusecLength = 0;
548         ctimeLength = 0;
549         subkeyLength = 0;
550         seqNumberLength = 0;
551         authorizationDataLength = 0;
552         authenticatorSeqLength = 0;
553         authenticatorLength = 0;
554     }
555 
556 
557     /**
558      * @see Object#toString()
559      */
560     public String toString()
561     {
562         StringBuilder sb = new StringBuilder();
563 
564         sb.append( "Authenticator : \n" );
565 
566         sb.append( "    authenticator-vno : " ).append( getVersionNumber() ).append( '\n' );
567         sb.append( "    crealm : " ).append( crealm ).append( '\n' );
568         sb.append( "    cname : " ).append( cname ).append( '\n' );
569 
570         if ( cksum != null )
571         {
572             sb.append( "    cksum : " ).append( cksum ).append( '\n' );
573         }
574 
575         sb.append( "    cusec : " ).append( cusec ).append( '\n' );
576         sb.append( "    ctime : " ).append( ctime ).append( '\n' );
577 
578         if ( subKey != null )
579         {
580             sb.append( "    subkey : " ).append( subKey ).append( '\n' );
581         }
582 
583         if ( seqNumber != null )
584         {
585             sb.append( "    seq-number : " ).append( seqNumber ).append( '\n' );
586         }
587 
588         if ( authorizationData != null )
589         {
590             sb.append( "    authorization-data : " ).append( authorizationData ).append( '\n' );
591         }
592 
593         return sb.toString();
594     }
595 }