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.AuthorizationType;
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   * A single AuthorizationData
39   * 
40   * The ASN.1 grammar is :
41   * -- NOTE: AuthorizationData is always used as an OPTIONAL field and
42   * -- should not be empty.
43   * AuthorizationDataEntry       ::= SEQUENCE {
44   *        ad-type         [0] Int32,
45   *        ad-data         [1] OCTET STRING
46   * }
47   *  
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   * @version $Rev: 587531 $, $Date: 2007-10-23 16:59:10 +0200 (Di, 23 Okt 2007) $
50   */
51  public class AuthorizationDataEntry extends AbstractAsn1Object
52  {
53      /** The logger */
54      private static final Logger log = LoggerFactory.getLogger( AuthorizationDataEntry.class );
55  
56      /** Speedup for logs */
57      private static final boolean IS_DEBUG = log.isDebugEnabled();
58  
59      /** The Authorization type. One of :
60       * DER encoding of AD-IF-RELEVANT        1
61       * DER encoding of AD-KDCIssued          4
62       * DER encoding of AD-AND-OR             5
63       * DER encoding of AD-MANDATORY-FOR-KDC  8 
64       **/
65      private AuthorizationType adType;
66  
67      /** The data, encrypted */
68      private byte[] adData;
69  
70      // Storage for computed lengths
71      private transient int adTypeLength;
72      private transient int adDataLength;
73      private transient int authorizationDataEntryLength;
74  
75  
76      /**
77       * Creates a new instance of AuthorizationDataEntry.
78       */
79      public AuthorizationDataEntry()
80      {
81      }
82  
83      
84      /**
85       * Creates a new instance of AuthorizationDataEntry.
86       *
87       * @param adType The authorizationType
88       * @param adData The authorization data
89       */
90      public AuthorizationDataEntry( AuthorizationType adType, byte[] adData )
91      {
92          this.adType = adType;
93          this.adData = adData;
94      }
95  
96  
97      /**
98       * Returns the raw bytes of the authorization data.
99       *
100      * @return The raw bytes of the authorization data.
101      */
102     public byte[] getAdData()
103     {
104         return adData;
105     }
106 
107 
108     /**
109      * Set the authorization data
110      * 
111      * @param adData The data
112      */
113     public void setAdData( byte[] adData ) 
114     {
115         this.adData = adData;
116     }
117 
118     
119     /**
120      * Returns the {@link AuthorizationType}.
121      *
122      * @return The {@link AuthorizationType}.
123      */
124     public AuthorizationType getAdType()
125     {
126         return adType;
127     }
128 
129 
130     /**
131      * Set the authorization type
132      * @param adType The authorization type
133      */
134     public void setAdType( int adType ) 
135     {
136         this.adType = AuthorizationType.getTypeByOrdinal( adType );
137     }
138 
139     
140     /**
141      * Set the authorization type
142      * @param adType The authorization type
143      */
144     public void setAdType( AuthorizationType adType ) 
145     {
146         this.adType = adType;
147     }
148 
149     
150     /**
151      * Compute the AuthorizationDataEntry length
152      * 
153      * AuthorizationDataEntry :
154      * 
155      * 0x30 L1 AuthorizationDataEntry
156      *  |
157      *  +--> 0xA0 L2 adType tag
158      *  |     |
159      *  |     +--> 0x02 L2-1 adType (int)
160      *  |
161      *  +--> 0xA1 L3 adData tag
162      *        |
163      *        +--> 0x04 L3-1 adData (OCTET STRING)
164      *        
165      *  where L1 = L2 + lenght(0xA0) + length(L2) +
166      *             L3 + lenght(0xA1) + length(L3) 
167      *  and
168      *  L2 = L2-1 + length(0x02) + length( L2-1) 
169      *  L3 = L3-1 + length(0x04) + length( L3-1) 
170      */
171     public int computeLength()
172     {
173         // Compute the adType. The Length will always be contained in 1 byte
174         adTypeLength = 1 + 1 + Value.getNbBytes( adType.getOrdinal() );
175         authorizationDataEntryLength = 1 + TLV.getNbBytes( adTypeLength ) + adTypeLength;
176 
177         // Compute the keyValue
178         if ( adData == null )
179         {
180             adDataLength = 1 + 1;
181         }
182         else
183         {
184             adDataLength = 1 + TLV.getNbBytes( adData.length ) + adData.length;
185         }
186 
187         authorizationDataEntryLength += 1 + TLV.getNbBytes( adDataLength ) + adDataLength;
188 
189         // Compute the whole sequence length
190         int authorizationDataEntrySeqLength = 1 + Value.getNbBytes( authorizationDataEntryLength )
191             + authorizationDataEntryLength;
192 
193         return authorizationDataEntrySeqLength;
194 
195     }
196 
197 
198     /**
199      * Encode the AuthorizationDataEntry message to a PDU. 
200      * 
201      * AuthorizationDataEntry :
202      * 
203      * 0x30 LL
204      *   0xA0 LL 
205      *     0x02 0x01 adType
206      *   0xA1 LL 
207      *     0x04 LL adData
208      * 
209      * @param buffer The buffer where to put the PDU. It should have been allocated
210      * before, with the right size.
211      * @return The constructed PDU.
212      */
213     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
214     {
215         if ( buffer == null )
216         {
217             throw new EncoderException( "Cannot put a PDU in a null buffer !" );
218         }
219 
220         try
221         {
222             // The AuthorizationDataEntry SEQ Tag
223             buffer.put( UniversalTag.SEQUENCE_TAG );
224             buffer.put( TLV.getBytes( authorizationDataEntryLength ) );
225 
226             // The adType, first the tag, then the value
227             buffer.put( ( byte ) 0xA0 );
228             buffer.put( TLV.getBytes( adTypeLength ) );
229             Value.encode( buffer, adType.getOrdinal() );
230 
231             // The adData, first the tag, then the value
232             buffer.put( ( byte ) 0xA1 );
233             buffer.put( TLV.getBytes( adDataLength ) );
234             Value.encode( buffer, adData );
235         }
236         catch ( BufferOverflowException boe )
237         {
238             log
239                 .error(
240                     "Cannot encode the AuthorizationDataEntry object, the PDU size is {} when only {} bytes has been allocated",
241                     1 + TLV.getNbBytes( authorizationDataEntryLength ) + authorizationDataEntryLength, buffer
242                         .capacity() );
243             throw new EncoderException( "The PDU buffer size is too small !" );
244         }
245 
246         if ( IS_DEBUG )
247         {
248             log.debug( "AuthorizationDataEntry encoding : {}", StringTools.dumpBytes( buffer.array() ) );
249             log.debug( "AuthorizationDataEntry initial value : {}", toString() );
250         }
251 
252         return buffer;
253     }
254 
255 
256     /**
257      * @see Object#toString()
258      */
259     public String toString()
260     {
261         return toString( "    " );
262     }
263 
264 
265     /**
266      * @see Object#toString()
267      */
268     public String toString( String tabs )
269     {
270         StringBuilder sb = new StringBuilder();
271 
272         sb.append( tabs ).append( "AuthorizationDataEntry : {\n" );
273         sb.append( tabs ).append( "    ad-type: " ).append( adType ).append( '\n' );
274 
275         sb.append( tabs ).append( "    ad-data: " ).append( StringTools.dumpBytes( adData ) )
276             .append( "\n" + tabs + "}" );
277 
278         return sb.toString();
279     }
280 }