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.Asn1Object;
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 implements Asn1Object
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      *  +--&gt; 0xA0 L2 trType tag
138      *  |     |
139      *  |     +--&gt; 0x02 L2-1 trType (int)
140      *  |
141      *  +--&gt; 0xA1 L3 contents tag
142      *        |
143      *        +--&gt; 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         return 1 + TLV.getNbBytes( transitedEncodingLength ) + transitedEncodingLength;
172     }
173 
174 
175     /**
176      * Encode the TransitedEncoding message to a PDU. 
177      * 
178      * TransitedEncoding :
179      * 
180      * 0x30 LL
181      *   0xA0 LL 
182      *     0x02 0x01 trType
183      *   0xA1 LL 
184      *     0x04 LL contents
185      * 
186      * @param buffer The buffer where to put the PDU. It should have been allocated
187      * before, with the right size.
188      * @return The constructed PDU.
189      */
190     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
191     {
192         if ( buffer == null )
193         {
194             throw new EncoderException( I18n.err( I18n.ERR_148 ) );
195         }
196 
197         try
198         {
199             // The AuthorizationDataEntry SEQ Tag
200             buffer.put( UniversalTag.SEQUENCE.getValue() );
201             buffer.put( TLV.getBytes( transitedEncodingLength ) );
202 
203             // The tr-type, first the tag, then the value
204             buffer.put( ( byte ) KerberosConstants.TRANSITED_ENCODING_TR_TYPE_TAG );
205             buffer.put( TLV.getBytes( trTypeLength ) );
206             BerValue.encode( buffer, trType.getValue() );
207 
208             // The contents, first the tag, then the value
209             buffer.put( ( byte ) KerberosConstants.TRANSITED_ENCODING_CONTENTS_TAG );
210             buffer.put( TLV.getBytes( contentsLength ) );
211             BerValue.encode( buffer, contents );
212         }
213         catch ( BufferOverflowException boe )
214         {
215             log.error( I18n.err( I18n.ERR_147, 1 + TLV.getNbBytes( transitedEncodingLength )
216                 + transitedEncodingLength, buffer.capacity() ) );
217             throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
218         }
219 
220         if ( IS_DEBUG )
221         {
222             log.debug( "TransitedEncoding encoding : {}", Strings.dumpBytes( buffer.array() ) );
223             log.debug( "TransitedEncoding initial value : {}", this );
224         }
225 
226         return buffer;
227     }
228 
229 
230     /**
231      * {@inheritDoc}
232      */
233     @Override
234     public int hashCode()
235     {
236         final int prime = 31;
237         int result = 1;
238         result = prime * result + Arrays.hashCode( contents );
239         result = prime * result + ( ( trType == null ) ? 0 : trType.hashCode() );
240         return result;
241     }
242 
243 
244     /**
245      * {@inheritDoc}
246      */
247     @Override
248     public boolean equals( Object obj )
249     {
250         if ( this == obj )
251         {
252             return true;
253         }
254 
255         if ( !( obj instanceof TransitedEncoding ) )
256         {
257             return false;
258         }
259 
260         TransitedEncoding/../../org/apache/directory/shared/kerberos/components/TransitedEncoding.html#TransitedEncoding">TransitedEncoding other = ( TransitedEncoding ) obj;
261 
262         if ( !Arrays.equals( contents, other.contents ) )
263         {
264             return false;
265         }
266 
267         return trType == other.trType;
268     }
269 
270 
271     /**
272      * @see Object#toString()
273      */
274     public String toString()
275     {
276         StringBuilder sb = new StringBuilder();
277 
278         sb.append( "TransitedEncoding : {\n" );
279         sb.append( "    tr-type: " ).append( trType ).append( '\n' );
280 
281         sb.append( "    contents: " ).append( Strings.dumpBytes( contents ) ).append( "\n}\n" );
282 
283         return sb.toString();
284     }
285 }