001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.server.kerberos.shared.messages.value;
021
022
023 import java.nio.BufferOverflowException;
024 import java.nio.ByteBuffer;
025
026 import org.apache.directory.server.kerberos.shared.messages.value.types.AuthorizationType;
027 import org.apache.directory.shared.asn1.AbstractAsn1Object;
028 import org.apache.directory.shared.asn1.ber.tlv.TLV;
029 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
030 import org.apache.directory.shared.asn1.ber.tlv.Value;
031 import org.apache.directory.shared.asn1.codec.EncoderException;
032 import org.apache.directory.shared.ldap.util.StringTools;
033 import org.slf4j.Logger;
034 import org.slf4j.LoggerFactory;
035
036
037 /**
038 * A single AuthorizationData
039 *
040 * The ASN.1 grammar is :
041 * -- NOTE: AuthorizationData is always used as an OPTIONAL field and
042 * -- should not be empty.
043 * AuthorizationDataEntry ::= SEQUENCE {
044 * ad-type [0] Int32,
045 * ad-data [1] OCTET STRING
046 * }
047 *
048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
049 * @version $Rev: 587531 $, $Date: 2007-10-23 17:59:10 +0300 (Tue, 23 Oct 2007) $
050 */
051 public class AuthorizationDataEntry extends AbstractAsn1Object
052 {
053 /** The logger */
054 private static final Logger log = LoggerFactory.getLogger( AuthorizationDataEntry.class );
055
056 /** Speedup for logs */
057 private static final boolean IS_DEBUG = log.isDebugEnabled();
058
059 /** The Authorization type. One of :
060 * DER encoding of AD-IF-RELEVANT 1
061 * DER encoding of AD-KDCIssued 4
062 * DER encoding of AD-AND-OR 5
063 * DER encoding of AD-MANDATORY-FOR-KDC 8
064 **/
065 private AuthorizationType adType;
066
067 /** The data, encrypted */
068 private byte[] adData;
069
070 // Storage for computed lengths
071 private transient int adTypeLength;
072 private transient int adDataLength;
073 private transient int authorizationDataEntryLength;
074
075
076 /**
077 * Creates a new instance of AuthorizationDataEntry.
078 */
079 public AuthorizationDataEntry()
080 {
081 }
082
083
084 /**
085 * Creates a new instance of AuthorizationDataEntry.
086 *
087 * @param adType The authorizationType
088 * @param adData The authorization data
089 */
090 public AuthorizationDataEntry( AuthorizationType adType, byte[] adData )
091 {
092 this.adType = adType;
093 this.adData = adData;
094 }
095
096
097 /**
098 * Returns the raw bytes of the authorization data.
099 *
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 }