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.nio.ByteBuffer;
025    import java.util.Enumeration;
026    
027    import javax.security.auth.kerberos.KerberosPrincipal;
028    
029    import org.apache.directory.server.kerberos.shared.KerberosMessageType;
030    import org.apache.directory.server.kerberos.shared.messages.KdcReply;
031    import org.apache.directory.server.kerberos.shared.messages.components.Ticket;
032    import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
033    import org.apache.directory.server.kerberos.shared.messages.value.KerberosPrincipalModifier;
034    import org.apache.directory.server.kerberos.shared.messages.value.PaData;
035    import org.apache.directory.shared.asn1.der.ASN1InputStream;
036    import org.apache.directory.shared.asn1.der.DERApplicationSpecific;
037    import org.apache.directory.shared.asn1.der.DEREncodable;
038    import org.apache.directory.shared.asn1.der.DERGeneralString;
039    import org.apache.directory.shared.asn1.der.DERInteger;
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: 540371 $, $Date: 2007-05-21 17:00:43 -0700 (Mon, 21 May 2007) $
047     */
048    public class KdcReplyDecoder
049    {
050        /**
051         * Decodes a {@link ByteBuffer} into a {@link KdcReply}.
052         * 
053         * AS-REP ::=    [APPLICATION 11] KDC-REP
054         * TGS-REP ::=   [APPLICATION 13] KDC-REP
055         *
056         * @param in
057         * @return The {@link KdcReply}.
058         * @throws IOException
059         */
060        public KdcReply decode( ByteBuffer in ) throws IOException
061        {
062            ASN1InputStream ais = new ASN1InputStream( in );
063    
064            DERApplicationSpecific app = ( DERApplicationSpecific ) ais.readObject();
065    
066            DERSequence kdcreq = ( DERSequence ) app.getObject();
067    
068            return decodeKdcReplySequence( kdcreq );
069        }
070    
071    
072        /*
073         KDC-REP ::=   SEQUENCE {
074         pvno[0]                    INTEGER,
075         msg-type[1]                INTEGER,
076         padata[2]                  SEQUENCE OF PA-DATA OPTIONAL,
077         crealm[3]                  Realm,
078         cname[4]                   PrincipalName,
079         ticket[5]                  Ticket,
080         enc-part[6]                EncryptedData
081         }*/
082        private KdcReply decodeKdcReplySequence( DERSequence sequence ) throws IOException
083        {
084            KerberosMessageType msgType = null;
085            PaData[] paData = null;
086            Ticket ticket = null;
087            EncryptedData encPart = null;
088    
089            KerberosPrincipalModifier modifier = new KerberosPrincipalModifier();
090    
091            for ( Enumeration<DEREncodable> e = sequence.getObjects(); e.hasMoreElements(); )
092            {
093                DERTaggedObject object = ( DERTaggedObject ) e.nextElement();
094                int tag = object.getTagNo();
095                DEREncodable derObject = object.getObject();
096    
097                switch ( tag )
098                {
099                    case 0:
100                        // DERInteger tag0 = ( DERInteger ) derObject;
101                        // int pvno = tag0.intValue();
102                        break;
103                        
104                    case 1:
105                        DERInteger tag1 = ( DERInteger ) derObject;
106                        msgType = KerberosMessageType.getTypeByOrdinal( tag1.intValue() );
107                        break;
108                        
109                    case 2:
110                        DERSequence tag2 = ( DERSequence ) derObject;
111                        paData = PreAuthenticationDataDecoder.decodeSequence( tag2 );
112                        break;
113                        
114                    case 3:
115                        DERGeneralString tag3 = ( DERGeneralString ) derObject;
116                        modifier.setRealm( tag3.getString() );
117                        break;
118                        
119                    case 4:
120                        DERSequence tag4 = ( DERSequence ) derObject;
121                        modifier.setPrincipalName( PrincipalNameDecoder.decode( tag4 ) );
122                        break;
123                        
124                    case 5:
125                        DERApplicationSpecific tag5 = ( DERApplicationSpecific ) derObject;
126                        ticket = TicketDecoder.decode( tag5 );
127                        break;
128                        
129                    case 6:
130                        DERSequence tag6 = ( DERSequence ) derObject;
131                        encPart = ( EncryptedDataDecoder.decode( tag6 ) );
132                        break;
133                }
134            }
135    
136            KerberosPrincipal clientPrincipal = modifier.getKerberosPrincipal();
137    
138            return new KdcReply( paData, clientPrincipal, ticket, encPart, msgType );
139        }
140    }