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  
26  import org.apache.directory.api.asn1.Asn1Object;
27  import org.apache.directory.api.asn1.EncoderException;
28  import org.apache.directory.api.asn1.ber.tlv.BerValue;
29  import org.apache.directory.api.asn1.ber.tlv.TLV;
30  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
31  import org.apache.directory.api.util.Strings;
32  import org.apache.directory.server.i18n.I18n;
33  import org.apache.directory.shared.kerberos.KerberosConstants;
34  import org.apache.directory.shared.kerberos.codec.types.PaDataType;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  
39  /**
40   * The Pre-Authentication data. The ASN.1 GRAMMAR IS :
41   * <pre>
42   * PA-DATA         ::= SEQUENCE {
43   *         -- NOTE: first tag is [1], not [0]
44   *         padata-type     [1] Int32,
45   *         padata-value    [2] OCTET STRING -- might be encoded AP-REQ
46   * }
47   * </pre>
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   */
50  public class PaData implements Asn1Object
51  {
52      /** The logger */
53      private static final Logger log = LoggerFactory.getLogger( PaData.class );
54  
55      /** Speedup for logs */
56      private static final boolean IS_DEBUG = log.isDebugEnabled();
57  
58      /** The Pre-authentication type */
59      private PaDataType paDataType;
60  
61      /** The authentication data */
62      private byte[] paDataValue;
63  
64      // Storage for computed lengths
65      private int paDataTypeTagLength;
66      private int paDataValueTagLength;
67      private int preAuthenticationDataSeqLength;
68  
69  
70      /**
71       * Creates a new instance of PreAuthenticationData.
72       */
73      public PaData()
74      {
75      }
76  
77  
78      /**
79       * Creates a new instance of PreAuthenticationData.
80       *
81       * @param paDataType
82       * @param paDataValue
83       */
84      public PaData( PaDataType paDataType, byte[] paDataValue )
85      {
86          this.paDataType = paDataType;
87          this.paDataValue = paDataValue;
88      }
89  
90  
91      /**
92       * Returns the {@link PaDataType}.
93       *
94       * @return The {@link PaDataType}.
95       */
96      public PaDataType getPaDataType()
97      {
98          return paDataType;
99      }
100 
101 
102     /**
103      * Set the PA-DATA type
104      *
105      * @param paDataType The PA-DATA type
106      */
107     public void setPaDataType( int paDataType )
108     {
109         this.paDataType = PaDataType.getTypeByValue( paDataType );
110     }
111 
112 
113     /**
114      * Set the PA-DATA type
115      *
116      * @param paDataType The PA-DATA type
117      */
118     public void setPaDataType( PaDataType paDataType )
119     {
120         this.paDataType = paDataType;
121     }
122 
123 
124     /**
125      * Returns the raw bytes of the {@link PaData}.
126      *
127      * @return The raw bytes of the {@link PaData}.
128      */
129     public byte[] getPaDataValue()
130     {
131         return paDataValue;
132     }
133 
134 
135     /**
136      * Set the PA-DATA value
137      *
138      * @param paDataValue The PA-DATA value
139      */
140     public void setPaDataValue( byte[] paDataValue )
141     {
142         this.paDataValue = paDataValue;
143     }
144 
145 
146     /**
147      * Compute the PreAuthenticationData length
148      * <pre>
149      * PreAuthenticationData :
150      * 
151      * 0x30 L1 PreAuthenticationData sequence
152      *  |
153      *  +--&gt; 0xA0 L2 padata-type tag
154      *  |     |
155      *  |     +--&gt; 0x02 L2-1 padata-type (int)
156      *  |
157      *  +--&gt; 0xA1 L3 padata-value tag
158      *        |
159      *        +--&gt; 0x04 L3-1 padata-value (OCTET STRING)
160      *        
161      *  where L1 = L2 + lenght(0xA0) + length(L2) +
162      *             L3 + lenght(0xA1) + length(L3) 
163      *  and
164      *  L2 = L2-1 + length(0x02) + length( L2-1) 
165      *  L3 = L3-1 + length(0x04) + length( L3-1) 
166      *  </pre>
167      */
168     public int computeLength()
169     {
170         // Compute the paDataType. The Length will always be contained in 1 byte
171         int paDataTypeLength = BerValue.getNbBytes( paDataType.getValue() );
172         paDataTypeTagLength = 1 + TLV.getNbBytes( paDataTypeLength ) + paDataTypeLength;
173         preAuthenticationDataSeqLength = 1 + TLV.getNbBytes( paDataTypeTagLength ) + paDataTypeTagLength;
174 
175         // Compute the paDataValue
176         if ( paDataValue == null )
177         {
178             paDataValueTagLength = 1 + 1;
179         }
180         else
181         {
182             paDataValueTagLength = 1 + TLV.getNbBytes( paDataValue.length ) + paDataValue.length;
183         }
184 
185         // Compute the whole sequence length
186         preAuthenticationDataSeqLength += 1 + TLV.getNbBytes( paDataValueTagLength ) + paDataValueTagLength;
187 
188         return 1 + TLV.getNbBytes( preAuthenticationDataSeqLength ) + preAuthenticationDataSeqLength;
189 
190     }
191 
192 
193     /**
194      * Encode the PreAuthenticationData message to a PDU. 
195      * <pre>
196      * PreAuthenticationData :
197      * 
198      * 0x30 LL
199      *   0xA1 LL 
200      *     0x02 0x01 padata-type
201      *   0xA2 LL 
202      *     0x04 LL padata-value
203      * </pre>
204      * @param buffer The buffer where to put the PDU. It should have been allocated
205      * before, with the right size.
206      * @return The constructed PDU.
207      */
208     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
209     {
210         if ( buffer == null )
211         {
212             throw new EncoderException( I18n.err( I18n.ERR_148 ) );
213         }
214 
215         try
216         {
217             // The PreAuthenticationData SEQ Tag
218             buffer.put( UniversalTag.SEQUENCE.getValue() );
219             buffer.put( TLV.getBytes( preAuthenticationDataSeqLength ) );
220 
221             // The PaDataType, first the tag, then the value
222             buffer.put( ( byte ) KerberosConstants.PADATA_TYPE_TAG );
223             buffer.put( TLV.getBytes( paDataTypeTagLength ) );
224             BerValue.encode( buffer, paDataType.getValue() );
225 
226             // The PaDataValue, first the tag, then the value
227             buffer.put( ( byte ) KerberosConstants.PADATA_VALUE_TAG );
228             buffer.put( TLV.getBytes( paDataValueTagLength ) );
229             BerValue.encode( buffer, paDataValue );
230         }
231         catch ( BufferOverflowException boe )
232         {
233             log.error( I18n.err( I18n.ERR_145, 1 + TLV.getNbBytes( preAuthenticationDataSeqLength )
234                 + preAuthenticationDataSeqLength, buffer.capacity() ) );
235             throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
236         }
237 
238         if ( IS_DEBUG )
239         {
240             log.debug( "PreAuthenticationData encoding : {}", Strings.dumpBytes( buffer.array() ) );
241             log.debug( "PreAuthenticationData initial value : {}", this );
242         }
243 
244         return buffer;
245     }
246 
247 
248     /**
249      * @see Object#toString()
250      */
251     public String toString()
252     {
253         return toString( "" );
254     }
255 
256 
257     /**
258      * @see Object#toString()
259      */
260     public String toString( String tabs )
261     {
262         StringBuilder sb = new StringBuilder();
263 
264         sb.append( tabs ).append( "PreAuthenticationData : \n" );
265         sb.append( tabs ).append( "    padata-type: " ).append( paDataType ).append( '\n' );
266 
267         if ( paDataValue != null )
268         {
269             sb.append( tabs + "    padata-value:" ).append( Strings.dumpBytes( paDataValue ) ).append( '\n' );
270         }
271 
272         return sb.toString();
273     }
274 }