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  
21  package org.apache.directory.shared.kerberos.messages;
22  
23  
24  import java.nio.BufferOverflowException;
25  import java.nio.ByteBuffer;
26  
27  import org.apache.directory.api.asn1.EncoderException;
28  import org.apache.directory.api.asn1.ber.tlv.BerValue;
29  import org.apache.directory.api.asn1.ber.tlv.TLV;
30  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
31  import org.apache.directory.api.util.Strings;
32  import org.apache.directory.server.i18n.I18n;
33  import org.apache.directory.shared.kerberos.KerberosConstants;
34  import org.apache.directory.shared.kerberos.KerberosMessageType;
35  import org.apache.directory.shared.kerberos.components.Checksum;
36  import org.apache.directory.shared.kerberos.components.KrbSafeBody;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  
41  /**
42   * Class representing KRB-SAFE message
43   * 
44   * <pre>
45   * KRB-SAFE        ::= [APPLICATION 20] SEQUENCE {
46   *      pvno            [0] INTEGER (5),
47   *      msg-type        [1] INTEGER (20),
48   *      safe-body       [2] KRB-SAFE-BODY,
49   *      cksum           [3] Checksum
50   * }
51   * </pre>
52   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
53   */
54  public class KrbSafe extends KerberosMessage
55  {
56      /** The logger */
57      private static final Logger log = LoggerFactory.getLogger( KrbError.class );
58  
59      /** Speedup for logs */
60      private static final boolean IS_DEBUG = log.isDebugEnabled();
61  
62      /** body of this message */
63      private KrbSafeBody krbSafeBody;
64  
65      /** the checksum */
66      private Checksum checksum;
67  
68      // Storage for computed lengths
69      private int pvnoLen;
70      private int msgTypeLength;
71      private int krbSafeBodyLen;
72      private int checksumLen;
73      private int krbSafeSeqLen;
74      private int krbSafeLen;
75  
76  
77      /**
78       * Creates a new instance of KrbSafe.
79       */
80      public KrbSafe()
81      {
82          super( KerberosMessageType.KRB_SAFE );
83      }
84  
85  
86      /**
87       * @return the krbSafeBody
88       */
89      public KrbSafeBody getSafeBody()
90      {
91          return krbSafeBody;
92      }
93  
94  
95      /**
96       * @param safeBody the KrbSafeBody to set
97       */
98      public void setSafeBody( KrbSafeBody safeBody )
99      {
100         this.krbSafeBody = safeBody;
101     }
102 
103 
104     /**
105      * @return the checksum
106      */
107     public Checksum getChecksum()
108     {
109         return checksum;
110     }
111 
112 
113     /**
114      * @param checksum the checksum to set
115      */
116     public void setChecksum( Checksum checksum )
117     {
118         this.checksum = checksum;
119     }
120 
121 
122     /**
123      * Compute the KRB-SAFE length
124      * <pre>
125      * KRB-SAFE :
126      * 
127      * 0x74 L1 KRB-SAFE APPLICATION[20]
128      *  |
129      *  +--&gt; 0x30 L2 KRB-ERROR sequence
130      *        |
131      *        +--&gt; 0xA0 0x03 pvno tag
132      *        |     |
133      *        |     +--&gt; 0x02 0x01 0x05 pvno (5)
134      *        |
135      *        +--&gt; 0xA1 0x03 msg-type tag
136      *        |     |
137      *        |     +--&gt; 0x02 0x01 0x14 msg-type (20)
138      *        |     
139      *        +--&gt; 0xA2 L3 safe-body tag
140      *        |     |
141      *        |     +--&gt; 0x30 L3-1 safe-body (KRB-SAFE-BODY)
142      *        |
143      *        +--&gt; 0xA3 L4 cksum tag
144      *              |
145      *              +--&gt; 0x30 L4-1 cksum (CHECKSUM)
146      * </pre>
147      */
148     @Override
149     public int computeLength()
150     {
151         pvnoLen = 1 + 1 + 1;
152         krbSafeSeqLen = 1 + TLV.getNbBytes( pvnoLen ) + pvnoLen;
153 
154         msgTypeLength = 1 + 1 + BerValue.getNbBytes( getMessageType().getValue() );
155         krbSafeSeqLen += 1 + TLV.getNbBytes( msgTypeLength ) + msgTypeLength;
156 
157         krbSafeBodyLen = krbSafeBody.computeLength();
158         krbSafeSeqLen += 1 + TLV.getNbBytes( krbSafeBodyLen ) + krbSafeBodyLen;
159 
160         checksumLen = checksum.computeLength();
161         krbSafeSeqLen += 1 + TLV.getNbBytes( checksumLen ) + checksumLen;
162 
163         krbSafeLen = 1 + TLV.getNbBytes( krbSafeSeqLen ) + krbSafeSeqLen;
164 
165         return 1 + TLV.getNbBytes( krbSafeLen ) + krbSafeLen;
166     }
167 
168 
169     /**
170      * {@inheritDoc}
171      */
172     @Override
173     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
174     {
175         if ( buffer == null )
176         {
177             throw new EncoderException( I18n.err( I18n.ERR_148 ) );
178         }
179 
180         try
181         {
182             // The KRB-SAFE APPLICATION tag
183             buffer.put( ( byte ) KerberosConstants.KRB_SAFE_TAG );
184             buffer.put( TLV.getBytes( krbSafeLen ) );
185 
186             // The KRB-SAFE sequence
187             buffer.put( UniversalTag.SEQUENCE.getValue() );
188             buffer.put( TLV.getBytes( krbSafeSeqLen ) );
189 
190             // pvno tag and value
191             buffer.put( ( byte ) KerberosConstants.KRB_SAFE_PVNO_TAG );
192             buffer.put( TLV.getBytes( pvnoLen ) );
193             BerValue.encode( buffer, getProtocolVersionNumber() );
194 
195             // msg-type tag and value
196             buffer.put( ( byte ) KerberosConstants.KRB_SAFE_MSGTYPE_TAG );
197             buffer.put( TLV.getBytes( msgTypeLength ) );
198             BerValue.encode( buffer, getMessageType().getValue() );
199 
200             // safe-body tag and value
201             buffer.put( ( byte ) KerberosConstants.KRB_SAFE_SAFE_BODY_TAG );
202             buffer.put( TLV.getBytes( krbSafeBodyLen ) );
203             krbSafeBody.encode( buffer );
204 
205             // cksum tag and value
206             buffer.put( ( byte ) KerberosConstants.KRB_SAFE_CKSUM_TAG );
207             buffer.put( TLV.getBytes( checksumLen ) );
208             checksum.encode( buffer );
209         }
210         catch ( BufferOverflowException boe )
211         {
212             log.error( I18n.err( I18n.ERR_736_CANNOT_ENCODE_KRBSAFE, 1 + TLV.getNbBytes( krbSafeLen )
213                 + krbSafeLen, buffer.capacity() ) );
214             throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
215         }
216 
217         if ( IS_DEBUG )
218         {
219             log.debug( "KrbSafe encoding : {}", Strings.dumpBytes( buffer.array() ) );
220             log.debug( "KrbSafe initial value : {}", this );
221         }
222 
223         return buffer;
224     }
225 
226 
227     /**
228      * @see Object#toString()
229      */
230     public String toString()
231     {
232         StringBuilder sb = new StringBuilder();
233 
234         sb.append( "KRB-SAFE : {\n" );
235         sb.append( "    pvno: " ).append( getProtocolVersionNumber() ).append( '\n' );
236         sb.append( "    msgType: " ).append( getMessageType() ).append( '\n' );
237 
238         if ( krbSafeBody != null )
239         {
240             sb.append( "    safe-body: " ).append( krbSafeBody ).append( '\n' );
241         }
242 
243         if ( checksum != null )
244         {
245             sb.append( "    cusec: " ).append( checksum ).append( '\n' );
246         }
247 
248         sb.append( "}\n" );
249 
250         return sb.toString();
251     }
252 }