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 org.apache.directory.server.kerberos.shared.messages.ErrorMessage;
028    import org.apache.directory.server.kerberos.shared.messages.ErrorMessageModifier;
029    import org.apache.directory.server.kerberos.shared.messages.value.KerberosPrincipalModifier;
030    import org.apache.directory.shared.asn1.der.ASN1InputStream;
031    import org.apache.directory.shared.asn1.der.DERApplicationSpecific;
032    import org.apache.directory.shared.asn1.der.DEREncodable;
033    import org.apache.directory.shared.asn1.der.DERGeneralString;
034    import org.apache.directory.shared.asn1.der.DERGeneralizedTime;
035    import org.apache.directory.shared.asn1.der.DERInteger;
036    import org.apache.directory.shared.asn1.der.DEROctetString;
037    import org.apache.directory.shared.asn1.der.DERSequence;
038    import org.apache.directory.shared.asn1.der.DERTaggedObject;
039    
040    
041    /**
042     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043     * @version $Rev$, $Date$
044     */
045    public class ErrorMessageDecoder
046    {
047        /**
048         * Decodes a {@link ByteBuffer} into an {@link ErrorMessage}.
049         * 
050         * KRB-ERROR       ::= [APPLICATION 30] SEQUENCE
051         *
052         * @param in
053         * @return The {@link ErrorMessage}.
054         * @throws IOException
055         */
056        public ErrorMessage decode( ByteBuffer in ) throws IOException
057        {
058            ASN1InputStream ais = new ASN1InputStream( in );
059    
060            DERApplicationSpecific app = ( DERApplicationSpecific ) ais.readObject();
061    
062            DERSequence errorMessage = ( DERSequence ) app.getObject();
063    
064            return decodeErrorMessageSequence( errorMessage );
065        }
066    
067    
068        /*
069         KRB-ERROR       ::= [APPLICATION 30] SEQUENCE {
070         pvno            [0] INTEGER (5),
071         msg-type        [1] INTEGER (30),
072         ctime           [2] KerberosTime OPTIONAL,
073         cusec           [3] Microseconds OPTIONAL,
074         stime           [4] KerberosTime,
075         susec           [5] Microseconds,
076         error-code      [6] Int32,
077         crealm          [7] Realm OPTIONAL,
078         cname           [8] PrincipalName OPTIONAL,
079         realm           [9] Realm -- service realm --,
080         sname           [10] PrincipalName -- service name --,
081         e-text          [11] KerberosString OPTIONAL,
082         e-data          [12] OCTET STRING OPTIONAL
083         }
084         */
085        private ErrorMessage decodeErrorMessageSequence( DERSequence sequence )
086        {
087            ErrorMessageModifier errorModifier = new ErrorMessageModifier();
088            KerberosPrincipalModifier clientModifier = new KerberosPrincipalModifier();
089            KerberosPrincipalModifier serverModifier = 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                    case 1:
104                        // DERInteger tag1 = ( DERInteger ) derObject;
105                        // msgType = MessageType.getTypeByOrdinal( tag1.intValue() );
106                        break;
107                    case 2:
108                        DERGeneralizedTime tag2 = ( DERGeneralizedTime ) derObject;
109                        errorModifier.setClientTime( KerberosTimeDecoder.decode( tag2 ) );
110                        break;
111                    case 3:
112                        DERInteger tag3 = ( DERInteger ) derObject;
113                        errorModifier.setClientMicroSecond( tag3.intValue() );
114                        break;
115                    case 4:
116                        DERGeneralizedTime tag4 = ( DERGeneralizedTime ) derObject;
117                        errorModifier.setServerTime( KerberosTimeDecoder.decode( tag4 ) );
118                        break;
119                    case 5:
120                        DERInteger tag5 = ( DERInteger ) derObject;
121                        errorModifier.setServerMicroSecond( tag5.intValue() );
122                        break;
123                    case 6:
124                        DERInteger tag6 = ( DERInteger ) derObject;
125                        errorModifier.setErrorCode( tag6.intValue() );
126                        break;
127                    case 7:
128                        DERGeneralString tag7 = ( DERGeneralString ) derObject;
129                        clientModifier.setRealm( tag7.getString() );
130                        break;
131                    case 8:
132                        DERSequence tag8 = ( DERSequence ) derObject;
133                        clientModifier.setPrincipalName( PrincipalNameDecoder.decode( tag8 ) );
134                        break;
135                    case 9:
136                        DERGeneralString tag9 = ( DERGeneralString ) derObject;
137                        serverModifier.setRealm( tag9.getString() );
138                        break;
139                    case 10:
140                        DERSequence tag10 = ( DERSequence ) derObject;
141                        serverModifier.setPrincipalName( PrincipalNameDecoder.decode( tag10 ) );
142                        break;
143                    case 11:
144                        DERGeneralString tag11 = ( DERGeneralString ) derObject;
145                        errorModifier.setExplanatoryText( tag11.getString() );
146                        break;
147                    case 12:
148                        DEROctetString tag12 = ( DEROctetString ) derObject;
149                        errorModifier.setExplanatoryData( tag12.getOctets() );
150                        break;
151                }
152            }
153    
154            errorModifier.setClientPrincipal( clientModifier.getKerberosPrincipal() );
155            errorModifier.setServerPrincipal( serverModifier.getKerberosPrincipal() );
156    
157            return errorModifier.getErrorMessage();
158        }
159    }