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    package org.apache.directory.server.kerberos.shared.io.decoder;
021    
022    
023    import java.io.IOException;
024    import java.util.Enumeration;
025    
026    import org.apache.directory.server.kerberos.shared.messages.Encodable;
027    import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPart;
028    import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPartModifier;
029    import org.apache.directory.server.kerberos.shared.messages.value.TransitedEncoding;
030    import org.apache.directory.server.kerberos.shared.messages.value.flags.TicketFlags;
031    import org.apache.directory.server.kerberos.shared.messages.value.types.TransitedEncodingType;
032    import org.apache.directory.shared.asn1.der.ASN1InputStream;
033    import org.apache.directory.shared.asn1.der.DERApplicationSpecific;
034    import org.apache.directory.shared.asn1.der.DERBitString;
035    import org.apache.directory.shared.asn1.der.DEREncodable;
036    import org.apache.directory.shared.asn1.der.DERGeneralString;
037    import org.apache.directory.shared.asn1.der.DERGeneralizedTime;
038    import org.apache.directory.shared.asn1.der.DERInteger;
039    import org.apache.directory.shared.asn1.der.DEROctetString;
040    import org.apache.directory.shared.asn1.der.DERSequence;
041    import org.apache.directory.shared.asn1.der.DERTaggedObject;
042    
043    
044    /**
045     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
046     * @version $Rev: 591019 $, $Date: 2007-11-01 15:16:34 +0100 (Thu, 01 Nov 2007) $
047     */
048    public class EncTicketPartDecoder implements Decoder, DecoderFactory
049    {
050        public Decoder getDecoder()
051        {
052            return new EncTicketPartDecoder();
053        }
054    
055    
056        public Encodable decode( byte[] encodedTicket ) throws IOException
057        {
058            ASN1InputStream ais = new ASN1InputStream( encodedTicket );
059    
060            DERApplicationSpecific app = ( DERApplicationSpecific ) ais.readObject();
061    
062            DERSequence sequence = ( DERSequence ) app.getObject();
063    
064            return decodeEncTicketPartSequence( sequence );
065        }
066    
067    
068        /*
069         -- Encrypted part of ticket
070         EncTicketPart ::=     [APPLICATION 3] SEQUENCE {
071         flags[0]             TicketFlags,
072         key[1]               EncryptionKey,
073         crealm[2]            Realm,
074         cname[3]             PrincipalName,
075         transited[4]         TransitedEncoding,
076         authtime[5]          KerberosTime,
077         starttime[6]         KerberosTime OPTIONAL,
078         endtime[7]           KerberosTime,
079         renew-till[8]        KerberosTime OPTIONAL,
080         caddr[9]             HostAddresses OPTIONAL,
081         authorization-data[10]   AuthorizationData OPTIONAL
082         }*/
083        private EncTicketPart decodeEncTicketPartSequence( DERSequence sequence )
084        {
085            EncTicketPartModifier modifier = new EncTicketPartModifier();
086    
087            for ( Enumeration<DEREncodable> e = sequence.getObjects(); e.hasMoreElements(); )
088            {
089                DERTaggedObject object = ( DERTaggedObject ) e.nextElement();
090                int tag = object.getTagNo();
091                DEREncodable derObject = object.getObject();
092    
093                switch ( tag )
094                {
095                    case 0:
096                        DERBitString tag0 = ( DERBitString ) derObject;
097                        modifier.setFlags( new TicketFlags( tag0.getOctets() ) );
098                        break;
099                        
100                    case 1:
101                        DERSequence tag1 = ( DERSequence ) derObject;
102                        modifier.setSessionKey( EncryptionKeyDecoder.decode( tag1 ) );
103                        break;
104                        
105                    case 2:
106                        DERGeneralString tag2 = ( DERGeneralString ) derObject;
107                        modifier.setClientRealm( tag2.getString() );
108                        break;
109                        
110                    case 3:
111                        DERSequence tag3 = ( DERSequence ) derObject;
112                        modifier.setClientName( PrincipalNameDecoder.decode( tag3 ) );
113                        break;
114                        
115                    case 4:
116                        DERSequence tag4 = ( DERSequence ) derObject;
117                        modifier.setTransitedEncoding( decodeTransitedEncoding( tag4 ) );
118                        break;
119                        
120                    case 5:
121                        DERGeneralizedTime tag5 = ( DERGeneralizedTime ) derObject;
122                        modifier.setAuthTime( KerberosTimeDecoder.decode( tag5 ) );
123                        break;
124                        
125                    case 6:
126                        DERGeneralizedTime tag6 = ( DERGeneralizedTime ) derObject;
127                        modifier.setStartTime( KerberosTimeDecoder.decode( tag6 ) );
128                        break;
129                        
130                    case 7:
131                        DERGeneralizedTime tag7 = ( DERGeneralizedTime ) derObject;
132                        modifier.setEndTime( KerberosTimeDecoder.decode( tag7 ) );
133                        break;
134                        
135                    case 8:
136                        DERGeneralizedTime tag8 = ( DERGeneralizedTime ) derObject;
137                        modifier.setRenewTill( KerberosTimeDecoder.decode( tag8 ) );
138                        break;
139                        
140                    case 9:
141                        DERSequence tag9 = ( DERSequence ) derObject;
142                        modifier.setClientAddresses( HostAddressDecoder.decodeSequence( tag9 ) );
143                        break;
144                        
145                    case 10:
146                        DERSequence tag10 = ( DERSequence ) derObject;
147                        modifier.setAuthorizationData( AuthorizationDataDecoder.decodeSequence( tag10 ) );
148                        break;
149                }
150            }
151            return modifier.getEncTicketPart();
152        }
153    
154    
155        /*
156         * TransitedEncoding ::= SEQUENCE {
157         *   tr-type[0] INTEGER, -- must be
158         *   registered contents[1] OCTET STRING
159         * }
160         */
161        protected TransitedEncoding decodeTransitedEncoding( DERSequence sequence )
162        {
163            TransitedEncodingType type = TransitedEncodingType.NULL;
164            byte[] contents = null;
165    
166            for ( Enumeration<DEREncodable> e = sequence.getObjects(); e.hasMoreElements(); )
167            {
168                DERTaggedObject object = ( DERTaggedObject ) e.nextElement();
169                int tag = object.getTagNo();
170                DEREncodable derObject = object.getObject();
171    
172                switch ( tag )
173                {
174                    case 0:
175                        DERInteger tag0 = ( DERInteger ) derObject;
176                        type = TransitedEncodingType.getTypeByOrdinal( tag0.intValue() );
177                        break;
178                        
179                    case 1:
180                        DEROctetString tag1 = ( DEROctetString ) derObject;
181                        contents = tag1.getOctets();
182                        break;
183                }
184            }
185    
186            return new TransitedEncoding( type, contents );
187        }
188    }