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 }