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