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