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.TransitedEncodingType;
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 TransitedEncoding structure.
039 *
040 * The ASN.1 grammar is :
041 *
042 * -- encoded Transited field
043 * TransitedEncoding ::= SEQUENCE {
044 * tr-type [0] Int32 -- must be registered --,
045 * contents [1] OCTET STRING
046 * }
047 *
048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
049 * @version $Rev: 642496 $, $Date: 2008-03-29 05:09:22 +0200 (Sat, 29 Mar 2008) $
050 */
051 public class TransitedEncoding extends AbstractAsn1Object
052 {
053 /** The logger */
054 private static final Logger log = LoggerFactory.getLogger( TransitedEncoding.class );
055
056 /** Speedup for logs */
057 private static final boolean IS_DEBUG = log.isDebugEnabled();
058
059 /** The transited type. One of :
060 * NULL
061 * DOMAIN_X500_COMPRESS
062 */
063 private TransitedEncodingType trType;
064
065 /** The transited data */
066 private byte[] contents;
067
068 // Storage for computed lengths
069 private transient int trTypeLength;
070 private transient int contentsLength;
071 private transient int transitedEncodingLength;
072
073
074 /**
075 * Creates a new instance of TransitedEncoding.
076 */
077 public TransitedEncoding()
078 {
079 trType = TransitedEncodingType.NULL;
080 contents = new byte[0];
081 }
082
083
084 /**
085 * Creates a new instance of TransitedEncoding.
086 *
087 * @param trType
088 * @param contents
089 */
090 public TransitedEncoding( TransitedEncodingType trType, byte[] contents )
091 {
092 this.trType = trType;
093 this.contents = contents;
094 }
095
096
097 /**
098 * Returns the contents.
099 *
100 * @return The contents.
101 */
102 public byte[] getContents()
103 {
104 return contents;
105 }
106
107
108 /**
109 * Set the contents
110 * @param contents The contents
111 */
112 public void setContents( byte[] contents )
113 {
114 this.contents = contents;
115 }
116
117
118 /**
119 * Returns the {@link TransitedEncodingType}.
120 *
121 * @return The {@link TransitedEncodingType}.
122 */
123 public TransitedEncodingType getTrType()
124 {
125 return trType;
126 }
127
128
129 /**
130 * Set the transited encoding type
131 * @param trType The transited encoding type
132 */
133 public void setTrType( TransitedEncodingType trType )
134 {
135 this.trType = trType;
136 }
137
138
139 /**
140 * Compute the TransitedEncoding length
141 *
142 * TransitedEncoding :
143 *
144 * 0x30 L1 TransitedEncoding
145 * |
146 * +--> 0xA0 L2 trType tag
147 * | |
148 * | +--> 0x02 L2-1 trType (int)
149 * |
150 * +--> 0xA1 L3 contents tag
151 * |
152 * +--> 0x04 L3-1 contents (OCTET STRING)
153 *
154 * where L1 = L2 + lenght(0xA0) + length(L2) +
155 * L3 + lenght(0xA1) + length(L3)
156 * and
157 * L2 = L2-1 + length(0x02) + length( L2-1)
158 * L3 = L3-1 + length(0x04) + length( L3-1)
159 */
160 public int computeLength()
161 {
162 // Compute the trType. The Length will always be contained in 1 byte
163 trTypeLength = 1 + 1 + Value.getNbBytes( trType.getOrdinal() );
164 transitedEncodingLength = 1 + TLV.getNbBytes( trTypeLength ) + trTypeLength;
165
166 // Compute the keyValue
167 if ( contents == null )
168 {
169 contentsLength = 1 + 1;
170 }
171 else
172 {
173 contentsLength = 1 + TLV.getNbBytes( contents.length ) + contents.length;
174 }
175
176 transitedEncodingLength += 1 + TLV.getNbBytes( contentsLength ) + contentsLength;
177
178 // Compute the whole sequence length
179 int transitedEncodingSeqLength = 1 + Value.getNbBytes( transitedEncodingLength ) + transitedEncodingLength;
180
181 return transitedEncodingSeqLength;
182
183 }
184
185
186 /**
187 * Encode the TransitedEncoding message to a PDU.
188 *
189 * TransitedEncoding :
190 *
191 * 0x30 LL
192 * 0xA0 LL
193 * 0x02 0x01 trType
194 * 0xA1 LL
195 * 0x04 LL adData
196 *
197 * @param buffer The buffer where to put the PDU. It should have been allocated
198 * before, with the right size.
199 * @return The constructed PDU.
200 */
201 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
202 {
203 if ( buffer == null )
204 {
205 throw new EncoderException( "Cannot put a PDU in a null buffer !" );
206 }
207
208 try
209 {
210 // The AuthorizationDataEntry SEQ Tag
211 buffer.put( UniversalTag.SEQUENCE_TAG );
212 buffer.put( TLV.getBytes( transitedEncodingLength ) );
213
214 // The tr-type, first the tag, then the value
215 buffer.put( ( byte ) 0xA0 );
216 buffer.put( TLV.getBytes( trTypeLength ) );
217 Value.encode( buffer, trType.getOrdinal() );
218
219 // The contents, first the tag, then the value
220 buffer.put( ( byte ) 0xA1 );
221 buffer.put( TLV.getBytes( contentsLength ) );
222 Value.encode( buffer, contents );
223 }
224 catch ( BufferOverflowException boe )
225 {
226 log.error(
227 "Cannot encode the TransitedEncoding object, the PDU size is {} when only {} bytes has been allocated",
228 1 + TLV.getNbBytes( transitedEncodingLength ) + transitedEncodingLength, buffer.capacity() );
229 throw new EncoderException( "The PDU buffer size is too small !" );
230 }
231
232 if ( IS_DEBUG )
233 {
234 log.debug( "TransitedEncoding encoding : {}", StringTools.dumpBytes( buffer.array() ) );
235 log.debug( "TransitedEncoding initial value : {}", toString() );
236 }
237
238 return buffer;
239 }
240
241
242 /**
243 * @see Object#toString()
244 */
245 public String toString()
246 {
247 StringBuilder sb = new StringBuilder();
248
249 sb.append( "TransitedEncoding : {\n" );
250 sb.append( " tr-type: " ).append( trType ).append( '\n' );
251
252 sb.append( " contents: " ).append( StringTools.dumpBytes( contents ) ).append( "\n}\n" );
253
254 return sb.toString();
255 }
256 }