View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.shared.kerberos.components;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  import java.util.Arrays;
26  
27  import org.apache.directory.api.asn1.AbstractAsn1Object;
28  import org.apache.directory.api.asn1.EncoderException;
29  import org.apache.directory.api.asn1.ber.tlv.BerValue;
30  import org.apache.directory.api.asn1.ber.tlv.TLV;
31  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
32  import org.apache.directory.api.util.Strings;
33  import org.apache.directory.server.i18n.I18n;
34  import org.apache.directory.shared.kerberos.KerberosConstants;
35  import org.apache.directory.shared.kerberos.codec.types.TransitedEncodingType;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  
40  /**
41   * The TransitedEncoding structure.
42   * 
43   * The ASN.1 grammar is :
44   * <pre>
45   * -- encoded Transited field
46   * TransitedEncoding       ::= SEQUENCE {
47   *         tr-type         [0] Int32 -- must be registered --,
48   *         contents        [1] OCTET STRING
49   * }
50   * </pre>
51   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
52   */
53  public class TransitedEncoding extends AbstractAsn1Object
54  {
55      /** The logger */
56      private static final Logger log = LoggerFactory.getLogger( TransitedEncoding.class );
57  
58      /** Speedup for logs */
59      private static final boolean IS_DEBUG = log.isDebugEnabled();
60  
61      /** 
62       * The transited type. One of :
63       * NULL
64       * DOMAIN_X500_COMPRESS
65       */
66      private TransitedEncodingType trType;
67  
68      /** The transited data */
69      private byte[] contents;
70  
71      // Storage for computed lengths
72      private int trTypeLength;
73      private int contentsLength;
74      private int transitedEncodingLength;
75  
76  
77      /**
78       * Creates a new instance of TransitedEncoding.
79       */
80      public TransitedEncoding()
81      {
82          trType = TransitedEncodingType.NULL;
83          contents = Strings.EMPTY_BYTES;
84      }
85  
86  
87      /**
88       * Returns the contents.
89       *
90       * @return The contents.
91       */
92      public byte[] getContents()
93      {
94          return contents;
95      }
96  
97  
98      /**
99       * Set the contents
100      * @param contents The contents
101      */
102     public void setContents( byte[] contents )
103     {
104         this.contents = contents;
105     }
106 
107 
108     /**
109      * Returns the {@link TransitedEncodingType}.
110      *
111      * @return The {@link TransitedEncodingType}.
112      */
113     public TransitedEncodingType getTrType()
114     {
115         return trType;
116     }
117 
118 
119     /**
120      * Set the transited encoding type
121      * @param trType The transited encoding type
122      */
123     public void setTrType( TransitedEncodingType trType )
124     {
125         this.trType = trType;
126     }
127 
128 
129     /**
130      * Compute the TransitedEncoding length
131      * 
132      * <pre>
133      * TransitedEncoding :
134      * 
135      * 0x30 L1 TransitedEncoding
136      *  |
137      *  +--> 0xA0 L2 trType tag
138      *  |     |
139      *  |     +--> 0x02 L2-1 trType (int)
140      *  |
141      *  +--> 0xA1 L3 contents tag
142      *        |
143      *        +--> 0x04 L3-1 contents (OCTET STRING)
144      *        
145      *  where L1 = L2 + lenght(0xA0) + length(L2) +
146      *             L3 + lenght(0xA1) + length(L3) 
147      *  and
148      *  L2 = L2-1 + length(0x02) + length( L2-1) 
149      *  L3 = L3-1 + length(0x04) + length( L3-1) 
150      *  </pre>
151      */
152     public int computeLength()
153     {
154         // Compute the trType. The Length will always be contained in 1 byte
155         trTypeLength = 1 + 1 + BerValue.getNbBytes( trType.getValue() );
156         transitedEncodingLength = 1 + TLV.getNbBytes( trTypeLength ) + trTypeLength;
157 
158         // Compute the contents length
159         if ( contents == null )
160         {
161             contentsLength = 1 + 1;
162         }
163         else
164         {
165             contentsLength = 1 + TLV.getNbBytes( contents.length ) + contents.length;
166         }
167 
168         transitedEncodingLength += 1 + TLV.getNbBytes( contentsLength ) + contentsLength;
169 
170         // Compute the whole sequence length
171         int transitedEncodingSeqLength = 1 + BerValue.getNbBytes( transitedEncodingLength ) + transitedEncodingLength;
172 
173         return transitedEncodingSeqLength;
174     }
175 
176 
177     /**
178      * Encode the TransitedEncoding message to a PDU. 
179      * 
180      * TransitedEncoding :
181      * 
182      * 0x30 LL
183      *   0xA0 LL 
184      *     0x02 0x01 trType
185      *   0xA1 LL 
186      *     0x04 LL contents
187      * 
188      * @param buffer The buffer where to put the PDU. It should have been allocated
189      * before, with the right size.
190      * @return The constructed PDU.
191      */
192     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
193     {
194         if ( buffer == null )
195         {
196             throw new EncoderException( I18n.err( I18n.ERR_148 ) );
197         }
198 
199         try
200         {
201             // The AuthorizationDataEntry SEQ Tag
202             buffer.put( UniversalTag.SEQUENCE.getValue() );
203             buffer.put( TLV.getBytes( transitedEncodingLength ) );
204 
205             // The tr-type, first the tag, then the value
206             buffer.put( ( byte ) KerberosConstants.TRANSITED_ENCODING_TR_TYPE_TAG );
207             buffer.put( TLV.getBytes( trTypeLength ) );
208             BerValue.encode( buffer, trType.getValue() );
209 
210             // The contents, first the tag, then the value
211             buffer.put( ( byte ) KerberosConstants.TRANSITED_ENCODING_CONTENTS_TAG );
212             buffer.put( TLV.getBytes( contentsLength ) );
213             BerValue.encode( buffer, contents );
214         }
215         catch ( BufferOverflowException boe )
216         {
217             log.error( I18n.err( I18n.ERR_147, 1 + TLV.getNbBytes( transitedEncodingLength )
218                 + transitedEncodingLength, buffer.capacity() ) );
219             throw new EncoderException( I18n.err( I18n.ERR_138 ) );
220         }
221 
222         if ( IS_DEBUG )
223         {
224             log.debug( "TransitedEncoding encoding : {}", Strings.dumpBytes( buffer.array() ) );
225             log.debug( "TransitedEncoding initial value : {}", toString() );
226         }
227 
228         return buffer;
229     }
230 
231 
232     /**
233      * {@inheritDoc}
234      */
235     @Override
236     public int hashCode()
237     {
238         final int prime = 31;
239         int result = 1;
240         result = prime * result + Arrays.hashCode( contents );
241         result = prime * result + ( ( trType == null ) ? 0 : trType.hashCode() );
242         return result;
243     }
244 
245 
246     /**
247      * {@inheritDoc}
248      */
249     @Override
250     public boolean equals( Object obj )
251     {
252         if ( this == obj )
253         {
254             return true;
255         }
256 
257         if ( obj == null )
258         {
259             return false;
260         }
261 
262         TransitedEncoding other = ( TransitedEncoding ) obj;
263 
264         if ( !Arrays.equals( contents, other.contents ) )
265         {
266             return false;
267         }
268 
269         if ( trType != other.trType )
270         {
271             return false;
272         }
273 
274         return true;
275     }
276 
277 
278     /**
279      * @see Object#toString()
280      */
281     public String toString()
282     {
283         StringBuilder sb = new StringBuilder();
284 
285         sb.append( "TransitedEncoding : {\n" );
286         sb.append( "    tr-type: " ).append( trType ).append( '\n' );
287 
288         sb.append( "    contents: " ).append( Strings.dumpBytes( contents ) ).append( "\n}\n" );
289 
290         return sb.toString();
291     }
292 }