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.messages;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  
26  import org.apache.directory.api.asn1.EncoderException;
27  import org.apache.directory.api.asn1.ber.tlv.BerValue;
28  import org.apache.directory.api.asn1.ber.tlv.TLV;
29  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
30  import org.apache.directory.api.util.Strings;
31  import org.apache.directory.server.i18n.I18n;
32  import org.apache.directory.shared.kerberos.KerberosConstants;
33  import org.apache.directory.shared.kerberos.KerberosMessageType;
34  import org.apache.directory.shared.kerberos.codec.options.ApOptions;
35  import org.apache.directory.shared.kerberos.components.EncryptedData;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  
40  /**
41   * AP-REQ message component . It will store the object described by the ASN.1 grammar :
42   * <pre>
43   * AP-REQ          ::= [APPLICATION 14] SEQUENCE {
44   *         pvno            [0] INTEGER (5),
45   *         msg-type        [1] INTEGER (14),
46   *         ap-options      [2] APOptions,
47   *         ticket          [3] Ticket,
48   *         authenticator   [4] EncryptedData -- Authenticator
49   * }
50   * </pre>
51   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
52   */
53  public class ApReq extends KerberosMessage
54  {
55      /** The logger */
56      private static final Logger LOG = LoggerFactory.getLogger( ApReq.class );
57  
58      /** Speedup for logs */
59      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
60  
61      /** The AP options */
62      private ApOptions apOptions;
63  
64      /** The Ticket */
65      private Ticket ticket;
66  
67      /** The encryptedData, an encrypted Authenticator */
68      private EncryptedData authenticator;
69  
70      // Storage for computed lengths
71      private int pvnoLength;
72      private int msgTypeLength;
73      private int apOptionsLength;
74      private int ticketLength;
75      private int authenticatorLength;
76      private int apReqLength;
77      private int apReqSeqLength;
78  
79  
80      /**
81       * Creates a new instance of ApplicationRequest.
82       */
83      public ApReq()
84      {
85          super( KerberosMessageType.AP_REQ );
86      }
87  
88  
89      /**
90       * Returns the {@link ApOptions}.
91       *
92       * @return The {@link ApOptions}.
93       */
94      public ApOptions getApOptions()
95      {
96          return apOptions;
97      }
98  
99  
100     /**
101      * Returns the {@link Ticket}.
102      *
103      * @return The {@link Ticket}.
104      */
105     public Ticket getTicket()
106     {
107         return ticket;
108     }
109 
110 
111     /**
112      * Returns the option at a specified index.
113      *
114      * @param option
115      * @return The option.
116      */
117     public boolean getOption( int option )
118     {
119         return apOptions.get( option );
120     }
121 
122 
123     /**
124      * Sets the options
125      *
126      * @param apOptions The options to set
127      */
128     public void setOption( ApOptions apOptions )
129     {
130         this.apOptions = apOptions;
131     }
132 
133 
134     /**
135      * Clears the option at a specified index.
136      *
137      * @param option
138      */
139     public void clearOption( int option )
140     {
141         apOptions.clear( option );
142     }
143 
144 
145     /**
146      * Returns the {@link EncryptedData}.
147      *
148      * @return The {@link EncryptedData}.
149      */
150     public EncryptedData getAuthenticator()
151     {
152         return authenticator;
153     }
154 
155 
156     /**
157      * Sets the {@link EncryptedData}.
158      *
159      * @param authenticator The encrypted authenticator
160      */
161     public void setAuthenticator( EncryptedData authenticator )
162     {
163         this.authenticator = authenticator;
164     }
165 
166 
167     /**
168      * Sets the {@link ApOptions}.
169      *
170      * @param options
171      */
172     public void setApOptions( ApOptions options )
173     {
174         apOptions = options;
175     }
176 
177 
178     /**
179      * Sets the {@link Ticket}.
180      *
181      * @param ticket
182      */
183     public void setTicket( Ticket ticket )
184     {
185         this.ticket = ticket;
186     }
187 
188 
189     /**
190      * Compute the AP-REQ length
191      * <pre>
192      * AP-REQ :
193      * 
194      * 0x6E L1 AP-REQ [APPLICATION 14]
195      *  |
196      *  +--&gt; 0x30 L2
197      *        |
198      *        +--&gt; 0xA0 0x03 pvno tag
199      *        |     |
200      *        |     +--&gt; 0x02 0x01 0x05 pvno (5)
201      *        |
202      *        +--&gt; 0xA1 0x03 msg-type tag
203      *        |     |
204      *        |     +--&gt; 0x02 0x01 0x0E msg-type (14)
205      *        |
206      *        +--&gt; 0xA2 0x03 APOptions tag
207      *        |     |
208      *        |     +--&gt; 0x03 0x05 0x00 b1 b2 b3 b4 APOtions
209      *        |
210      *        +--&gt; 0xA3 L3 ticket tag
211      *        |     |
212      *        |     +--&gt; 0x61 L3-1 ticket
213      *        |
214      *        +--&gt; 0xA4 L4 authenticator tag
215      *              |
216      *              +--&gt; 0x30 L4-1 authenticator (encrypted)
217      * </pre>
218      */
219     public int computeLength()
220     {
221         reset();
222 
223         // Compute the PVNO length.
224         pvnoLength = 1 + 1 + BerValue.getNbBytes( getProtocolVersionNumber() );
225 
226         // Compute the msg-type length
227         msgTypeLength = 1 + 1 + BerValue.getNbBytes( getMessageType().getValue() );
228 
229         // Compute the APOptions length
230         apOptionsLength = 1 + 1 + apOptions.getBytes().length;
231 
232         // Compute the ticket length
233         ticketLength = ticket.computeLength();
234 
235         // Compute the authenticator length
236         authenticatorLength = authenticator.computeLength();
237 
238         // Compute the sequence size
239         apReqLength =
240             1 + TLV.getNbBytes( pvnoLength ) + pvnoLength +
241                 1 + TLV.getNbBytes( msgTypeLength ) + msgTypeLength +
242                 1 + TLV.getNbBytes( apOptionsLength ) + apOptionsLength +
243                 1 + TLV.getNbBytes( ticketLength ) + ticketLength +
244                 1 + TLV.getNbBytes( authenticatorLength ) + authenticatorLength;
245 
246         apReqSeqLength = 1 + TLV.getNbBytes( apReqLength ) + apReqLength;
247 
248         return 1 + TLV.getNbBytes( apReqSeqLength ) + apReqSeqLength;
249     }
250 
251 
252     /**
253      * Encode the AP-REQ component
254      * 
255      * @param buffer The buffer containing the encoded result
256      * @return The encoded component
257      * @throws EncoderException If the encoding failed
258      */
259     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
260     {
261         if ( buffer == null )
262         {
263             buffer = ByteBuffer.allocate( computeLength() );
264         }
265 
266         try
267         {
268             // The AP-REP Tag
269             buffer.put( ( byte ) KerberosConstants.AP_REQ_TAG );
270             buffer.put( TLV.getBytes( apReqSeqLength ) );
271 
272             // The AP-REP SEQ Tag
273             buffer.put( UniversalTag.SEQUENCE.getValue() );
274             buffer.put( TLV.getBytes( apReqLength ) );
275 
276             // The PVNO -------------------------------------------------------
277             // The tag
278             buffer.put( ( byte ) KerberosConstants.AP_REQ_PVNO_TAG );
279             buffer.put( TLV.getBytes( pvnoLength ) );
280 
281             // The value
282             BerValue.encode( buffer, getProtocolVersionNumber() );
283 
284             // The msg-type ---------------------------------------------------
285             // The tag
286             buffer.put( ( byte ) KerberosConstants.AP_REQ_MSG_TYPE_TAG );
287             buffer.put( TLV.getBytes( msgTypeLength ) );
288 
289             // The value
290             BerValue.encode( buffer, getMessageType().getValue() );
291 
292             // The ap-options -------------------------------------------------
293             // The tag
294             buffer.put( ( byte ) KerberosConstants.AP_REQ_AP_OPTIONS_TAG );
295             buffer.put( TLV.getBytes( apOptionsLength ) );
296 
297             // The value
298             BerValue.encode( buffer, apOptions );
299 
300             // The ticket -----------------------------------------------------
301             // The tag
302             buffer.put( ( byte ) KerberosConstants.AP_REQ_TICKET_TAG );
303             buffer.put( TLV.getBytes( ticketLength ) );
304 
305             // The value
306             ticket.encode( buffer );
307 
308             // The authenticator ----------------------------------------------
309             // The tag
310             buffer.put( ( byte ) KerberosConstants.AP_REQ_AUTHENTICATOR_TAG );
311             buffer.put( TLV.getBytes( authenticatorLength ) );
312 
313             // The value
314             authenticator.encode( buffer );
315         }
316         catch ( BufferOverflowException boe )
317         {
318             LOG.error( I18n.err( I18n.ERR_137, 1 + TLV.getNbBytes( apReqLength ) + apReqLength,
319                 buffer.capacity() ) );
320             throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
321         }
322 
323         if ( IS_DEBUG )
324         {
325             LOG.debug( "AP-REQ encoding : {}", Strings.dumpBytes( buffer.array() ) );
326             LOG.debug( "AP-REQ initial value : {}", this );
327         }
328 
329         return buffer;
330     }
331 
332 
333     /**
334      * reset the fields used while computing length
335      */
336     private void reset()
337     {
338         pvnoLength = 0;
339         msgTypeLength = 0;
340         apOptionsLength = 0;
341         ticketLength = 0;
342         authenticatorLength = 0;
343         apReqLength = 0;
344         apReqSeqLength = 0;
345     }
346 
347 
348     /**
349      * @see Object#toString()
350      */
351     public String toString()
352     {
353         StringBuilder sb = new StringBuilder();
354 
355         sb.append( "AP-REQ :\n" );
356         sb.append( "  pvno : " ).append( getProtocolVersionNumber() ).append( "\n" );
357         sb.append( "  msg-type : " ).append( getMessageType() ).append( "\n" );
358         sb.append( "  ap-options : " ).append( apOptions ).append( "\n" );
359         sb.append( "  ticket : " ).append( ticket ).append( "\n" );
360         sb.append( "  authenticator : " ).append( authenticator ).append( "\n" );
361 
362         return sb.toString();
363     }
364 }