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.i18n.I18n;
027 import org.apache.directory.server.kerberos.shared.messages.value.types.PaDataType;
028 import org.apache.directory.shared.asn1.AbstractAsn1Object;
029 import org.apache.directory.shared.asn1.ber.tlv.TLV;
030 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
031 import org.apache.directory.shared.asn1.ber.tlv.Value;
032 import org.apache.directory.shared.asn1.codec.EncoderException;
033 import org.apache.directory.shared.ldap.util.StringTools;
034 import org.slf4j.Logger;
035 import org.slf4j.LoggerFactory;
036
037
038 /**
039 * The Pre-Authentication data. Tha ASN.1 GRAMMAR IS :
040 *
041 * PA-DATA ::= SEQUENCE {
042 * -- NOTE: first tag is [1], not [0]
043 * padata-type [1] Int32,
044 * padata-value [2] OCTET STRING -- might be encoded AP-REQ
045 * }
046 *
047 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
048 * @version $Rev: 902575 $, $Date: 2010-01-24 16:38:06 +0200 (Sun, 24 Jan 2010) $
049 */
050 public class PaData extends AbstractAsn1Object
051 {
052 /** The logger */
053 private static final Logger log = LoggerFactory.getLogger( PaData.class );
054
055 /** Speedup for logs */
056 private static final boolean IS_DEBUG = log.isDebugEnabled();
057
058 /** The Pre-authentication type */
059 private PaDataType paDataType;
060
061 /** The authentication data */
062 private byte[] paDataValue;
063
064 // Storage for computed lengths
065 private transient int paDataTypeTagLength;
066 private transient int paDataValueTagLength;
067 private transient int preAuthenticationDataSeqLength;
068
069
070 /**
071 * Creates a new instance of PreAuthenticationData.
072 */
073 public PaData()
074 {
075 }
076
077
078 /**
079 * Creates a new instance of PreAuthenticationData.
080 *
081 * @param paDataType
082 * @param paDataValue
083 */
084 public PaData( PaDataType paDataType, byte[] paDataValue )
085 {
086 this.paDataType = paDataType;
087 this.paDataValue = paDataValue;
088 }
089
090
091 /**
092 * Returns the {@link PaDataType}.
093 *
094 * @return The {@link PaDataType}.
095 */
096 public PaDataType getPaDataType()
097 {
098 return paDataType;
099 }
100
101
102 /**
103 * Set the PA-DATA type
104 *
105 * @param paDataType The PA-DATA type
106 */
107 public void setPaDataType( int paDataType )
108 {
109 this.paDataType = PaDataType.getTypeByOrdinal( paDataType );
110 }
111
112
113 /**
114 * Set the PA-DATA type
115 *
116 * @param paDataType The PA-DATA type
117 */
118 public void setPaDataType( PaDataType paDataType )
119 {
120 this.paDataType = paDataType;
121 }
122
123
124 /**
125 * Returns the raw bytes of the {@link PaData}.
126 *
127 * @return The raw bytes of the {@link PaData}.
128 */
129 public byte[] getPaDataValue()
130 {
131 return paDataValue;
132 }
133
134
135 /**
136 * Set the PA-DATA value
137 *
138 * @param paDataValue The PA-DATA value
139 */
140 public void setPaDataValue( byte[] paDataValue )
141 {
142 this.paDataValue = paDataValue;
143 }
144
145
146 /**
147 * Compute the PreAuthenticationData length
148 *
149 * PreAuthenticationData :
150 *
151 * 0x30 L1 PreAuthenticationData sequence
152 * |
153 * +--> 0xA0 L2 padata-type tag
154 * | |
155 * | +--> 0x02 L2-1 padata-type (int)
156 * |
157 * +--> 0xA1 L3 padata-value tag
158 * |
159 * +--> 0x04 L3-1 padata-value (OCTET STRING)
160 *
161 * where L1 = L2 + lenght(0xA0) + length(L2) +
162 * L3 + lenght(0xA1) + length(L3)
163 * and
164 * L2 = L2-1 + length(0x02) + length( L2-1)
165 * L3 = L3-1 + length(0x04) + length( L3-1)
166 */
167 public int computeLength()
168 {
169 // Compute the paDataType. The Length will always be contained in 1 byte
170 int paDataTypeLength = Value.getNbBytes( paDataType.getOrdinal() );
171 paDataTypeTagLength = 1 + TLV.getNbBytes( paDataTypeLength ) + paDataTypeLength;
172 preAuthenticationDataSeqLength = 1 + TLV.getNbBytes( paDataTypeTagLength ) + paDataTypeTagLength;
173
174 // Compute the paDataValue
175 if ( paDataValue == null )
176 {
177 paDataValueTagLength = 1 + 1;
178 }
179 else
180 {
181 paDataValueTagLength = 1 + TLV.getNbBytes( paDataValue.length ) + paDataValue.length;
182 }
183
184 // Compute the whole sequence length
185 preAuthenticationDataSeqLength += 1 + TLV.getNbBytes( paDataValueTagLength ) + paDataValueTagLength;
186
187 return 1 + TLV.getNbBytes( preAuthenticationDataSeqLength ) + preAuthenticationDataSeqLength;
188
189 }
190
191
192 /**
193 * Encode the PreAuthenticationData message to a PDU.
194 *
195 * PreAuthenticationData :
196 *
197 * 0x30 LL
198 * 0xA0 LL
199 * 0x02 0x01 padata-type
200 * 0xA1 LL
201 * 0x04 LL padata-value
202 *
203 * @param buffer The buffer where to put the PDU. It should have been allocated
204 * before, with the right size.
205 * @return The constructed PDU.
206 */
207 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
208 {
209 if ( buffer == null )
210 {
211 throw new EncoderException( I18n.err( I18n.ERR_148 ) );
212 }
213
214 try
215 {
216 // The Checksum SEQ Tag
217 buffer.put( UniversalTag.SEQUENCE_TAG );
218 buffer.put( TLV.getBytes( preAuthenticationDataSeqLength ) );
219
220 // The cksumtype, first the tag, then the value
221 buffer.put( ( byte ) 0xA1 );
222 buffer.put( TLV.getBytes( paDataTypeTagLength ) );
223 Value.encode( buffer, paDataType.getOrdinal() );
224
225 // The checksum, first the tag, then the value
226 buffer.put( ( byte ) 0xA2 );
227 buffer.put( TLV.getBytes( paDataValueTagLength ) );
228 Value.encode( buffer, paDataValue );
229 }
230 catch ( BufferOverflowException boe )
231 {
232 log.error( I18n.err( I18n.ERR_145, 1 + TLV.getNbBytes( preAuthenticationDataSeqLength )
233 + preAuthenticationDataSeqLength, buffer.capacity() ) );
234 throw new EncoderException( I18n.err( I18n.ERR_138 ) );
235 }
236
237 if ( IS_DEBUG )
238 {
239 log.debug( "PreAuthenticationData encoding : {}", StringTools.dumpBytes( buffer.array() ) );
240 log.debug( "PreAuthenticationData initial value : {}", toString() );
241 }
242
243 return buffer;
244 }
245
246 /**
247 * @see Object#toString()
248 */
249 public String toString()
250 {
251 return toString( "" );
252 }
253
254
255 /**
256 * @see Object#toString()
257 */
258 public String toString( String tabs )
259 {
260 StringBuilder sb = new StringBuilder();
261
262 sb.append( tabs ).append( "PreAuthenticationData : {\n" );
263 sb.append( tabs ).append( " padata-type: " ).append( paDataType ).append( '\n' );
264
265 if ( paDataValue != null )
266 {
267 sb.append( tabs + " padata-value:" ).append( StringTools.dumpBytes( paDataValue ) ).append( '\n' );
268 }
269
270 sb.append( tabs + "}\n" );
271
272 return sb.toString();
273 }
274 }