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
021package org.apache.directory.shared.kerberos.components;
022
023
024import java.nio.BufferOverflowException;
025import java.nio.ByteBuffer;
026import java.util.ArrayList;
027import java.util.List;
028
029import org.apache.directory.api.asn1.Asn1Object;
030import org.apache.directory.api.asn1.EncoderException;
031import org.apache.directory.api.asn1.ber.tlv.BerValue;
032import org.apache.directory.api.asn1.ber.tlv.TLV;
033import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
034import org.apache.directory.api.util.Strings;
035import org.apache.directory.server.i18n.I18n;
036import org.apache.directory.shared.kerberos.KerberosConstants;
037import org.apache.directory.shared.kerberos.KerberosTime;
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040
041
042/**
043 * EncKrbCredPart  ::= [APPLICATION 29] SEQUENCE {
044 *      ticket-info     [0] SEQUENCE OF KrbCredInfo,
045 *      nonce           [1] UInt32 OPTIONAL,
046 *      timestamp       [2] KerberosTime OPTIONAL,
047 *      usec            [3] Microseconds OPTIONAL,
048 *      s-address       [4] HostAddress OPTIONAL,
049 *      r-address       [5] HostAddress OPTIONAL
050 * }
051 *
052 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
053 */
054public class EncKrbCredPart implements Asn1Object
055{
056    /** The logger */
057    private static final Logger log = LoggerFactory.getLogger( EncKrbCredPart.class );
058
059    /** Speedup for logs */
060    private static final boolean IS_DEBUG = log.isDebugEnabled();
061
062    /** list of KrbCredInfo */
063    private List<KrbCredInfo> ticketInfo;
064
065    /** the nonce */
066    private Integer nonce;
067
068    /** the timestamp */
069    private KerberosTime timestamp;
070
071    /** the microseconds part of the timestamp */
072    private Integer usec;
073
074    /** the sender's address */
075    private HostAddress senderAddress;
076
077    /** the recipient's address */
078    private HostAddress recipientAddress;
079
080    private int ticketInfoSeqLen;
081    private int ticketInfoLen;
082    private int nonceLen;
083    private int timestampLen;
084    private byte[] timestampBytes;
085    private int usecLen;
086    private int senderAddressLen;
087    private int recipientAddressLen;
088    private int encKrbCredPartSeqLen;
089    private int encKrbCredPartLen;
090
091
092    /**
093     * computing length of EncKrbCredPart:
094     * 
095     * <pre>
096     *  0x7D L1
097     *   |
098     *   +--&gt; 0x30 L1-2 EncKrbCredPart seq tag
099     *         |
100     *         +--&gt; 0xA0 L2 seq of KrbCredInfo tag
101     *         |     |
102     *         |     +--&gt; 0x30 L2-2 seq tag
103     *         |     |
104     *         |     +--&gt; 0x30 LL1 KrbCredInfo
105     *         |     .      ....
106     *         |     +--&gt; 0x30 LLn KrbCredInfo
107     *         |
108     *         +--&gt; 0xA1 L3 nonce tag
109     *         |     |
110     *         |     +--&gt; 0x02 L3-2 nonce (UInt32)
111     *         |
112     *         +--&gt; 0xA2 11 timestamp tag
113     *         |     |
114     *         |     +--&gt; 0x18 0x0F timestamp (KerberosTime)
115     *         |
116     *         +--&gt; 0xA3 L4 usec tag
117     *         |     |
118     *         |     +--&gt; 0x02 L4-2 usec (Microseconds)
119     *         |
120     *         +--&gt; 0xA4 L5 s-address tag
121     *         |     |
122     *         |     +--&gt; 0x30 L5-2 s-address (HostAddress)
123     *         |
124     *         +--&gt; 0xA5 L6 r-address tag
125     *               |
126     *               +--&gt; 0x30 L6-2 s-address (HostAddress) 
127     *   
128     * </pre> 
129     */
130    @Override
131    public int computeLength()
132    {
133        for ( KrbCredInfo kci : ticketInfo )
134        {
135            ticketInfoSeqLen += kci.computeLength();
136        }
137
138        ticketInfoLen = 1 + TLV.getNbBytes( ticketInfoSeqLen ) + ticketInfoSeqLen;
139
140        encKrbCredPartSeqLen = 1 + TLV.getNbBytes( ticketInfoLen ) + ticketInfoLen;
141
142        if ( nonce != null )
143        {
144            nonceLen = BerValue.getNbBytes( nonce );
145            nonceLen = 1 + TLV.getNbBytes( nonceLen ) + nonceLen;
146            encKrbCredPartSeqLen += 1 + TLV.getNbBytes( nonceLen ) + nonceLen;
147        }
148
149        if ( timestamp != null )
150        {
151            timestampBytes = timestamp.getBytes();
152            timestampLen = 1 + TLV.getNbBytes( timestampBytes.length ) + timestampBytes.length;
153            encKrbCredPartSeqLen += 1 + TLV.getNbBytes( timestampLen ) + timestampLen;
154        }
155
156        if ( usec != null )
157        {
158            usecLen = BerValue.getNbBytes( usec );
159            usecLen = 1 + TLV.getNbBytes( usecLen ) + usecLen;
160            encKrbCredPartSeqLen += 1 + TLV.getNbBytes( usecLen ) + usecLen;
161        }
162
163        if ( senderAddress != null )
164        {
165            senderAddressLen = senderAddress.computeLength();
166            encKrbCredPartSeqLen += 1 + TLV.getNbBytes( senderAddressLen ) + senderAddressLen;
167        }
168
169        if ( recipientAddress != null )
170        {
171            recipientAddressLen = recipientAddress.computeLength();
172            encKrbCredPartSeqLen += 1 + TLV.getNbBytes( recipientAddressLen ) + recipientAddressLen;
173        }
174
175        encKrbCredPartLen = 1 + TLV.getNbBytes( encKrbCredPartSeqLen ) + encKrbCredPartSeqLen;
176
177        return 1 + TLV.getNbBytes( encKrbCredPartLen ) + encKrbCredPartLen;
178    }
179
180
181    /**
182     * {@inheritDoc}
183     */
184    @Override
185    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
186    {
187        if ( buffer == null )
188        {
189            throw new EncoderException( I18n.err( I18n.ERR_148 ) );
190        }
191
192        try
193        {
194            //EncKrbCredPart application tag
195            buffer.put( ( byte ) KerberosConstants.ENC_KRB_CRED_PART_TAG );
196            buffer.put( TLV.getBytes( encKrbCredPartLen ) );
197
198            //EncKrbCredPart sequence tag
199            buffer.put( UniversalTag.SEQUENCE.getValue() );
200            buffer.put( TLV.getBytes( encKrbCredPartSeqLen ) );
201
202            // ticket-info tag
203            buffer.put( ( byte ) KerberosConstants.ENC_KRB_CRED_TICKET_INFO_TAG );
204            buffer.put( TLV.getBytes( ticketInfoLen ) );
205
206            // sequence of ticket-info seq tag
207            buffer.put( UniversalTag.SEQUENCE.getValue() );
208            buffer.put( TLV.getBytes( ticketInfoSeqLen ) );
209
210            for ( KrbCredInfo ki : ticketInfo )
211            {
212                ki.encode( buffer );
213            }
214
215            if ( nonce != null )
216            {
217                // nonce tag and value
218                buffer.put( ( byte ) KerberosConstants.ENC_KRB_CRED_PART_NONCE_TAG );
219                buffer.put( TLV.getBytes( nonceLen ) );
220                BerValue.encode( buffer, nonce );
221            }
222
223            if ( timestamp != null )
224            {
225                // timestamp tag and value
226                buffer.put( ( byte ) KerberosConstants.ENC_KRB_CRED_PART_TIMESTAMP_TAG );
227                buffer.put( TLV.getBytes( timestampLen ) );
228
229                buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
230                buffer.put( ( byte ) 0x0F );
231                buffer.put( timestampBytes );
232            }
233
234            if ( usec != null )
235            {
236                // usec tag and value
237                buffer.put( ( byte ) KerberosConstants.ENC_KRB_CRED_PART_USEC_TAG );
238                buffer.put( TLV.getBytes( usecLen ) );
239                BerValue.encode( buffer, usec );
240            }
241
242            if ( senderAddress != null )
243            {
244                // s-address tag and value
245                buffer.put( ( byte ) KerberosConstants.ENC_KRB_CRED_PART_SENDER_ADDRESS_TAG );
246                buffer.put( TLV.getBytes( senderAddressLen ) );
247                senderAddress.encode( buffer );
248            }
249
250            if ( recipientAddress != null )
251            {
252                // r-address tag and value
253                buffer.put( ( byte ) KerberosConstants.ENC_KRB_CRED_PART_RECIPIENT_ADDRESS_TAG );
254                buffer.put( TLV.getBytes( recipientAddressLen ) );
255                recipientAddress.encode( buffer );
256            }
257        }
258        catch ( BufferOverflowException boe )
259        {
260            log.error( I18n.err( I18n.ERR_740_CANNOT_ENCODE_ENC_KRB_CRED_PART, 1 + TLV.getNbBytes( encKrbCredPartLen )
261                + encKrbCredPartLen, buffer.capacity() ) );
262            throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
263        }
264
265        if ( IS_DEBUG )
266        {
267            log.debug( "EncKrbCredPart encoding : {}", Strings.dumpBytes( buffer.array() ) );
268            log.debug( "EncKrbCredPart initial value : {}", this );
269        }
270
271        return buffer;
272    }
273
274
275    /**
276     * @return the ticketInfo
277     */
278    public List<KrbCredInfo> getTicketInfo()
279    {
280        return ticketInfo;
281    }
282
283
284    /**
285     * @param ticketInfo the ticketInfo to set
286     */
287    public void setTicketInfo( List<KrbCredInfo> ticketInfo )
288    {
289        this.ticketInfo = ticketInfo;
290    }
291
292
293    /**
294     * @return the nonce
295     */
296    public Integer getNonce()
297    {
298        return nonce;
299    }
300
301
302    /**
303     * @param nonce the nonce to set
304     */
305    public void setNonce( Integer nonce )
306    {
307        this.nonce = nonce;
308    }
309
310
311    /**
312     * @return the timestamp
313     */
314    public KerberosTime getTimestamp()
315    {
316        return timestamp;
317    }
318
319
320    /**
321     * @param timestamp the timestamp to set
322     */
323    public void setTimestamp( KerberosTime timestamp )
324    {
325        this.timestamp = timestamp;
326    }
327
328
329    /**
330     * @return the usec
331     */
332    public Integer getUsec()
333    {
334        return usec;
335    }
336
337
338    /**
339     * @param usec the usec to set
340     */
341    public void setUsec( Integer usec )
342    {
343        this.usec = usec;
344    }
345
346
347    /**
348     * @return the senderAddress
349     */
350    public HostAddress getSenderAddress()
351    {
352        return senderAddress;
353    }
354
355
356    /**
357     * @param senderAddress the senderAddress to set
358     */
359    public void setSenderAddress( HostAddress senderAddress )
360    {
361        this.senderAddress = senderAddress;
362    }
363
364
365    /**
366     * @return the recipientAddress
367     */
368    public HostAddress getRecipientAddress()
369    {
370        return recipientAddress;
371    }
372
373
374    /**
375     * @param recipientAddress the recipientAddress to set
376     */
377    public void setRecipientAddress( HostAddress recipientAddress )
378    {
379        this.recipientAddress = recipientAddress;
380    }
381
382
383    /**
384     * add KrbCredInfo object to the existing list of ticket-info
385     *
386     * @param info the KrbCredInfo
387     */
388    public void addTicketInfo( KrbCredInfo info )
389    {
390        if ( info == null )
391        {
392            throw new IllegalArgumentException();
393        }
394
395        if ( ticketInfo == null )
396        {
397            ticketInfo = new ArrayList<>();
398        }
399
400        ticketInfo.add( info );
401    }
402
403
404    /**
405     * @see Object#toString()
406     */
407    public String toString()
408    {
409        StringBuilder sb = new StringBuilder();
410
411        sb.append( "EncKrbCredPart : {\n" );
412
413        sb.append( "    ticketInfo: " ).append( ticketInfo ).append( '\n' );
414
415        if ( nonce != null )
416        {
417            sb.append( "    nonce: " ).append( nonce ).append( '\n' );
418        }
419
420        if ( timestamp != null )
421        {
422            sb.append( "    timestamp: " ).append( timestamp ).append( '\n' );
423        }
424
425        if ( usec != null )
426        {
427            sb.append( "    usec: " ).append( usec ).append( '\n' );
428        }
429
430        if ( senderAddress != null )
431        {
432            sb.append( "    senderAddress: " ).append( senderAddress ).append( '\n' );
433        }
434
435        if ( recipientAddress != null )
436        {
437            sb.append( "    recipientAddress: " ).append( recipientAddress ).append( '\n' );
438        }
439
440        sb.append( "}\n" );
441
442        return sb.toString();
443    }
444}