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.PaDataType;
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 * The Pre-Authentication data. Tha ASN.1 GRAMMAR IS :
039 *
040 * PA-DATA ::= SEQUENCE {
041 * -- NOTE: first tag is [1], not [0]
042 * padata-type [1] Int32,
043 * padata-value [2] OCTET STRING -- might be encoded AP-REQ
044 * }
045 *
046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
047 * @version $Rev: 642496 $, $Date: 2008-03-29 05:09:22 +0200 (Sat, 29 Mar 2008) $
048 */
049 public class PaData extends AbstractAsn1Object
050 {
051 /** The logger */
052 private static final Logger log = LoggerFactory.getLogger( PaData.class );
053
054 /** Speedup for logs */
055 private static final boolean IS_DEBUG = log.isDebugEnabled();
056
057 /** The Pre-authentication type */
058 private PaDataType paDataType;
059
060 /** The authentication data */
061 private byte[] paDataValue;
062
063 // Storage for computed lengths
064 private transient int paDataTypeTagLength;
065 private transient int paDataValueTagLength;
066 private transient int preAuthenticationDataSeqLength;
067
068
069 /**
070 * Creates a new instance of PreAuthenticationData.
071 */
072 public PaData()
073 {
074 }
075
076
077 /**
078 * Creates a new instance of PreAuthenticationData.
079 *
080 * @param paDataType
081 * @param paDataValue
082 */
083 public PaData( PaDataType paDataType, byte[] paDataValue )
084 {
085 this.paDataType = paDataType;
086 this.paDataValue = paDataValue;
087 }
088
089
090 /**
091 * Returns the {@link PaDataType}.
092 *
093 * @return The {@link PaDataType}.
094 */
095 public PaDataType getPaDataType()
096 {
097 return paDataType;
098 }
099
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 }