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;
026
027import org.apache.directory.api.asn1.Asn1Object;
028import org.apache.directory.api.asn1.EncoderException;
029import org.apache.directory.api.asn1.ber.tlv.BerValue;
030import org.apache.directory.api.asn1.ber.tlv.TLV;
031import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
032import org.apache.directory.api.util.Strings;
033import org.apache.directory.server.i18n.I18n;
034import org.apache.directory.shared.kerberos.KerberosConstants;
035import org.apache.directory.shared.kerberos.KerberosTime;
036import org.apache.directory.shared.kerberos.flags.TicketFlag;
037import org.apache.directory.shared.kerberos.flags.TicketFlags;
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040
041
042/**
043 * EncTicketPart   ::= [APPLICATION 3] SEQUENCE {
044 *      flags                   [0] TicketFlags,
045 *      key                     [1] EncryptionKey,
046 *      crealm                  [2] Realm,
047 *      cname                   [3] PrincipalName,
048 *      transited               [4] TransitedEncoding,
049 *      authtime                [5] KerberosTime,
050 *      starttime               [6] KerberosTime OPTIONAL,
051 *      endtime                 [7] KerberosTime,
052 *      renew-till              [8] KerberosTime OPTIONAL,
053 *      caddr                   [9] HostAddresses OPTIONAL,
054 *      authorization-data      [10] AuthorizationData OPTIONAL
055 * }
056 *
057 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
058 */
059public class EncTicketPart implements Asn1Object
060{
061    /** The logger */
062    private static final Logger log = LoggerFactory.getLogger( EncTicketPart.class );
063
064    /** Speedup for logs */
065    private static final boolean IS_DEBUG = log.isDebugEnabled();
066
067    /** the ticket's flags */
068    private TicketFlags flags = new TicketFlags();
069
070    /** the encryption key */
071    private EncryptionKey key;
072
073    /** the client's realm */
074    private String cRealm;
075
076    /** client's principal */
077    private PrincipalName cName;
078
079    /** field containing list of transited realm names */
080    private TransitedEncoding transited;
081
082    /** time of initial authentication */
083    private KerberosTime authTime;
084
085    /** time after which ticket is valid */
086    private KerberosTime startTime;
087
088    /** ticket's expiry time */
089    private KerberosTime endTime;
090
091    /** the maximum endtime that may be included in a renewal */
092    private KerberosTime renewtill;
093
094    /** the addresses from which this ticket can be used */
095    private HostAddresses clientAddresses;
096
097    /** the authorization data */
098    private AuthorizationData authorizationData;
099
100    private int flagsLen;
101    private int keyLen;
102    private int cRealmLen;
103    private byte[] cRealmBytes;
104    private int cNameLen;
105    private int transitedLen;
106    private int authTimeLen;
107    private byte[] authTimeBytes;
108    private int startTimeLen;
109    private byte[] startTimeBytes;
110    private int endTimeLen;
111    private byte[] endTimeBytes;
112    private int renewtillLen;
113    private byte[] renewtillBytes;
114    private int clientAddressesLen;
115    private int authzDataLen;
116    private int encTikcetPartSeqLen;
117    private int encTikcetPartLen;
118
119
120    /**
121     * compute length for EncTicketPart:
122     * <pre>
123     * 0x63 L1 EncTicketPart tag
124     *  |
125     *  +--&gt; 0x30 L1-2 EncTicketPart seq
126     *        |
127     *        +--&gt; 0xA0 L2 flags tag
128     *        |     |
129     *        |     +--&gt; 0x03 L2-2 flags (BitString)
130     *        |
131     *        +--&gt; 0xA1 L3 key tag
132     *        |     |
133     *        |     +--&gt; 0x30 L3-2 key (EncryptionKey)
134     *        |
135     *        +--&gt; 0xA2 L4 crealm tag
136     *        |     |
137     *        |     +--&gt; 0x1B L4-2 crealm (Realm)
138     *        |
139     *        +--&gt; 0xA3 L5 cname tag
140     *        |     |
141     *        |     +--&gt; 0x30 L5-2 cname (PrincipalName)
142     *        |
143     *        +--&gt; 0xA4 L6 transited tag
144     *        |     |
145     *        |     +--&gt; 0x30 L6-2 transited (TransitedEncoding)
146     *        |
147     *        +--&gt; 0xA5 0x11 authtime tag
148     *        |     |
149     *        |     +--&gt; 0x18 0x0F authtime (KerberosTime)
150     *        |
151     *        +--&gt; [0xA6 0x11 starttime tag
152     *        |     |
153     *        |     +--&gt; 0x18 0x0F starttime (KerberosTime)]
154     *        |
155     *        +--&gt; 0xA7 0x11 endtime tag
156     *        |     |
157     *        |     +--&gt; 0x18 0x0F endtime (KerberosTime)
158     *        |
159     *        +--&gt; [0xA8 0x11 renewtill tag
160     *        |     |
161     *        |     +--&gt; 0x18 0x0F renewtill (KerberosTime)]
162     *        |
163     *        +--&gt; [0xA9 L7 caddr tag
164     *        |     |
165     *        |     +--&gt; 0x30 L7-2 caddre (HostAddresses)]
166     *        |
167     *        +--&gt; [0xAA L8 authorization-data tag
168     *              |
169     *              +--&gt; 0x30 L8-2 authorization-data (AuthorizationData)]
170     * </pre>
171     * 
172     */
173    @Override
174    public int computeLength()
175    {
176        flagsLen = flags.getData().length;
177        flagsLen = 1 + TLV.getNbBytes( flagsLen ) + flagsLen;
178        encTikcetPartSeqLen = 1 + TLV.getNbBytes( flagsLen ) + flagsLen;
179
180        keyLen = key.computeLength();
181        encTikcetPartSeqLen += 1 + TLV.getNbBytes( keyLen ) + keyLen;
182
183        cRealmBytes = Strings.getBytesUtf8( cRealm );
184        cRealmLen = 1 + TLV.getNbBytes( cRealmBytes.length ) + cRealmBytes.length;
185        encTikcetPartSeqLen += 1 + TLV.getNbBytes( cRealmLen ) + cRealmLen;
186
187        cNameLen = cName.computeLength();
188        encTikcetPartSeqLen += 1 + TLV.getNbBytes( cNameLen ) + cNameLen;
189
190        transitedLen = transited.computeLength();
191        encTikcetPartSeqLen += 1 + TLV.getNbBytes( transitedLen ) + transitedLen;
192
193        authTimeBytes = authTime.getBytes();
194        authTimeLen = 1 + TLV.getNbBytes( authTimeBytes.length ) + authTimeBytes.length;
195        encTikcetPartSeqLen += 1 + TLV.getNbBytes( authTimeLen ) + authTimeLen;
196
197        if ( startTime != null )
198        {
199            startTimeBytes = startTime.getBytes();
200            startTimeLen = 1 + TLV.getNbBytes( startTimeBytes.length ) + startTimeBytes.length;
201            encTikcetPartSeqLen += 1 + TLV.getNbBytes( startTimeLen ) + startTimeLen;
202        }
203
204        endTimeBytes = endTime.getBytes();
205        endTimeLen = 1 + TLV.getNbBytes( endTimeBytes.length ) + endTimeBytes.length;
206        encTikcetPartSeqLen += 1 + TLV.getNbBytes( endTimeLen ) + endTimeLen;
207
208        if ( renewtill != null )
209        {
210            renewtillBytes = renewtill.getBytes();
211            renewtillLen = 1 + TLV.getNbBytes( renewtillBytes.length ) + renewtillBytes.length;
212            encTikcetPartSeqLen += 1 + TLV.getNbBytes( renewtillLen ) + renewtillLen;
213        }
214
215        if ( clientAddresses != null )
216        {
217            clientAddressesLen = clientAddresses.computeLength();
218            encTikcetPartSeqLen += 1 + TLV.getNbBytes( clientAddressesLen ) + clientAddressesLen;
219        }
220
221        if ( authorizationData != null )
222        {
223            authzDataLen = authorizationData.computeLength();
224            encTikcetPartSeqLen += 1 + TLV.getNbBytes( authzDataLen ) + authzDataLen;
225        }
226
227        encTikcetPartLen = 1 + TLV.getNbBytes( encTikcetPartSeqLen ) + encTikcetPartSeqLen;
228
229        return 1 + TLV.getNbBytes( encTikcetPartLen ) + encTikcetPartLen;
230    }
231
232
233    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
234    {
235        if ( buffer == null )
236        {
237            throw new EncoderException( I18n.err( I18n.ERR_148 ) );
238        }
239
240        try
241        {
242            // EncTicketPart application tag and length
243            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_TAG );
244            buffer.put( TLV.getBytes( encTikcetPartLen ) );
245
246            // EncTicketPart sequence tag and length
247            buffer.put( UniversalTag.SEQUENCE.getValue() );
248            buffer.put( TLV.getBytes( encTikcetPartSeqLen ) );
249
250            // flags tag and int value
251            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_FLAGS_TAG );
252            buffer.put( TLV.getBytes( flagsLen ) );
253            BerValue.encode( buffer, flags );
254
255            // key tag and value
256            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_KEY_TAG );
257            buffer.put( TLV.getBytes( keyLen ) );
258            key.encode( buffer );
259
260            // crealm tag and value
261            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_CREALM_TAG );
262            buffer.put( TLV.getBytes( cRealmLen ) );
263            buffer.put( UniversalTag.GENERAL_STRING.getValue() );
264            buffer.put( TLV.getBytes( cRealmBytes.length ) );
265            buffer.put( cRealmBytes );
266
267            // cname tag and value
268            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_CNAME_TAG );
269            buffer.put( TLV.getBytes( cNameLen ) );
270            cName.encode( buffer );
271
272            // transited tag and value
273            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_TRANSITED_TAG );
274            buffer.put( TLV.getBytes( transitedLen ) );
275            transited.encode( buffer );
276
277            // authtime tag and value
278            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_AUTHTIME_TAG );
279            buffer.put( TLV.getBytes( authTimeLen ) );
280            buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
281            buffer.put( ( byte ) 0x0F );
282            buffer.put( authTimeBytes );
283
284            if ( startTime != null )
285            {
286                // strattime tag and value
287                buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_STARTTIME_TAG );
288                buffer.put( TLV.getBytes( startTimeLen ) );
289                buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
290                buffer.put( ( byte ) 0x0F );
291                buffer.put( startTimeBytes );
292            }
293
294            // endtime tag and value
295            buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_ENDTIME_TAG );
296            buffer.put( TLV.getBytes( endTimeLen ) );
297            buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
298            buffer.put( ( byte ) 0x0F );
299            buffer.put( endTimeBytes );
300
301            if ( renewtill != null )
302            {
303                // renewtill tag and value
304                buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_RENEWTILL_TAG );
305                buffer.put( TLV.getBytes( renewtillLen ) );
306                buffer.put( UniversalTag.GENERALIZED_TIME.getValue() );
307                buffer.put( ( byte ) 0x0F );
308                buffer.put( renewtillBytes );
309            }
310
311            if ( clientAddresses != null )
312            {
313                // caddr tag and value
314                buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_CADDR_TAG );
315                buffer.put( TLV.getBytes( clientAddressesLen ) );
316                clientAddresses.encode( buffer );
317            }
318
319            if ( authorizationData != null )
320            {
321                // authorization-data tag and value
322                buffer.put( ( byte ) KerberosConstants.ENC_TICKET_PART_AUTHORIZATION_DATA_TAG );
323                buffer.put( TLV.getBytes( authzDataLen ) );
324                authorizationData.encode( buffer );
325            }
326        }
327        catch ( BufferOverflowException boe )
328        {
329            log.error( I18n.err( I18n.ERR_742_CANNOT_ENCODE_ENC_TICKET_PART, 1 + TLV.getNbBytes( encTikcetPartLen )
330                + encTikcetPartLen, buffer.capacity() ) );
331            throw new EncoderException( I18n.err( I18n.ERR_138 ), boe );
332        }
333
334        if ( IS_DEBUG )
335        {
336            log.debug( "EncTicketPart encoding : {}", Strings.dumpBytes( buffer.array() ) );
337            log.debug( "EncTicketPart initial value : {}", this );
338        }
339
340        return buffer;
341    }
342
343
344    /**
345     * @return the flags
346     */
347    public TicketFlags getFlags()
348    {
349        return flags;
350    }
351
352
353    /**
354     * @param flags the flags to set
355     */
356    public void setFlags( TicketFlags flags )
357    {
358        this.flags = flags;
359    }
360
361
362    /**
363     * @return the key
364     */
365    public EncryptionKey getKey()
366    {
367        return key;
368    }
369
370
371    /**
372     * @param key the key to set
373     */
374    public void setKey( EncryptionKey key )
375    {
376        this.key = key;
377    }
378
379
380    /**
381     * @return the cRealm
382     */
383    public String getCRealm()
384    {
385        return cRealm;
386    }
387
388
389    /**
390     * @param cRealm the cRealm to set
391     */
392    public void setCRealm( String cRealm )
393    {
394        this.cRealm = cRealm;
395    }
396
397
398    /**
399     * @return the cName
400     */
401    public PrincipalName getCName()
402    {
403        return cName;
404    }
405
406
407    /**
408     * @param cName the cName to set
409     */
410    public void setCName( PrincipalName cName )
411    {
412        this.cName = cName;
413    }
414
415
416    /**
417     * @return the transited
418     */
419    public TransitedEncoding getTransited()
420    {
421        return transited;
422    }
423
424
425    /**
426     * @param transited the transited to set
427     */
428    public void setTransited( TransitedEncoding transited )
429    {
430        this.transited = transited;
431    }
432
433
434    /**
435     * @return the authTime
436     */
437    public KerberosTime getAuthTime()
438    {
439        return authTime;
440    }
441
442
443    /**
444     * @param authTime the authTime to set
445     */
446    public void setAuthTime( KerberosTime authTime )
447    {
448        this.authTime = authTime;
449    }
450
451
452    /**
453     * @return the startTime
454     */
455    public KerberosTime getStartTime()
456    {
457        return startTime;
458    }
459
460
461    /**
462     * @param startTime the startTime to set
463     */
464    public void setStartTime( KerberosTime startTime )
465    {
466        this.startTime = startTime;
467    }
468
469
470    /**
471     * @return the endTime
472     */
473    public KerberosTime getEndTime()
474    {
475        return endTime;
476    }
477
478
479    /**
480     * @param endTime the endTime to set
481     */
482    public void setEndTime( KerberosTime endTime )
483    {
484        this.endTime = endTime;
485    }
486
487
488    /**
489     * @return the renewtill
490     */
491    public KerberosTime getRenewTill()
492    {
493        return renewtill;
494    }
495
496
497    /**
498     * @param renewtill the renewtill to set
499     */
500    public void setRenewTill( KerberosTime renewtill )
501    {
502        this.renewtill = renewtill;
503    }
504
505
506    /**
507     * @return the clientAddresses
508     */
509    public HostAddresses getClientAddresses()
510    {
511        return clientAddresses;
512    }
513
514
515    /**
516     * @param clientAddresses the clientAddresses to set
517     */
518    public void setClientAddresses( HostAddresses clientAddresses )
519    {
520        this.clientAddresses = clientAddresses;
521    }
522
523
524    /**
525     * @return the authzData
526     */
527    public AuthorizationData getAuthorizationData()
528    {
529        return authorizationData;
530    }
531
532
533    /**
534     * @param authzData the authzData to set
535     */
536    public void setAuthorizationData( AuthorizationData authzData )
537    {
538        this.authorizationData = authzData;
539    }
540
541
542    /**
543     * adds the given flag to the already existing flags.
544     * If no flags exist then creates a new TicketFlags object then sets this flag
545     * and assigns the TicketFlags to this ticket part
546     * 
547     * @param flag the flag to be set
548     */
549    public void setFlag( TicketFlag flag )
550    {
551        if ( flags == null )
552        {
553            flags = new TicketFlags();
554        }
555
556        flags.setFlag( flag.getValue() );
557    }
558
559
560    /**
561     * @see Object#toString()
562     */
563    public String toString()
564    {
565        StringBuilder sb = new StringBuilder();
566
567        sb.append( "EncTicketPart : {\n" );
568
569        sb.append( "    flags: " ).append( flags ).append( '\n' );
570        sb.append( "    key: " ).append( key ).append( '\n' );
571        sb.append( "    cRealm: " ).append( cRealm ).append( '\n' );
572        sb.append( "    cName: " ).append( cName ).append( '\n' );
573        sb.append( "    transited: " ).append( transited ).append( '\n' );
574        sb.append( "    authTime: " ).append( authTime ).append( '\n' );
575
576        if ( startTime != null )
577        {
578            sb.append( "    startTime: " ).append( startTime ).append( '\n' );
579        }
580
581        sb.append( "    endTime: " ).append( endTime ).append( '\n' );
582
583        if ( renewtill != null )
584        {
585            sb.append( "    renewtill: " ).append( renewtill ).append( '\n' );
586        }
587
588        if ( clientAddresses != null )
589        {
590            sb.append( "    clientAddresses: " ).append( clientAddresses ).append( '\n' );
591        }
592
593        if ( authorizationData != null )
594        {
595            sb.append( "    authzData: " ).append( authorizationData ).append( '\n' );
596        }
597
598        sb.append( "}\n" );
599
600        return sb.toString();
601    }
602
603}