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.encoder;
021    
022    
023    import java.io.ByteArrayOutputStream;
024    import java.io.IOException;
025    
026    import org.apache.directory.server.kerberos.shared.messages.Encodable;
027    import org.apache.directory.server.kerberos.shared.messages.components.Authenticator;
028    import org.apache.directory.shared.asn1.der.ASN1OutputStream;
029    import org.apache.directory.shared.asn1.der.DERApplicationSpecific;
030    import org.apache.directory.shared.asn1.der.DERGeneralString;
031    import org.apache.directory.shared.asn1.der.DERInteger;
032    import org.apache.directory.shared.asn1.der.DERSequence;
033    import org.apache.directory.shared.asn1.der.DERTaggedObject;
034    
035    
036    /**
037     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038     * @version $Rev$, $Date$
039     */
040    public class AuthenticatorEncoder implements Encoder, EncoderFactory
041    {
042        /**
043         * Application code constant for the {@link Authenticator} (2).
044         */
045        private static final int APPLICATION_CODE = 2;
046    
047    
048        /**
049         * Encodes an {@link Authenticator} into a byte array.
050         *
051         * @param authenticator
052         * @return The byte array.
053         * @throws IOException
054         */
055        public byte[] encode( Encodable authenticator ) throws IOException
056        {
057            ByteArrayOutputStream baos = new ByteArrayOutputStream();
058            ASN1OutputStream aos = new ASN1OutputStream( baos );
059    
060            DERSequence replySequence = encodeInitialSequence( ( Authenticator ) authenticator );
061            aos.writeObject( DERApplicationSpecific.valueOf( APPLICATION_CODE, replySequence ) );
062            aos.close();
063    
064            return baos.toByteArray();
065        }
066    
067    
068        public Encoder getEncoder()
069        {
070            return new AuthenticatorEncoder();
071        }
072    
073    
074        /**
075         * Encodes an {@link Authenticator} into a {@link DERSequence}.
076         * 
077         * -- Unencrypted authenticator
078         * Authenticator ::=    [APPLICATION 2] SEQUENCE
079         * {
080         *                authenticator-vno[0]          INTEGER,
081         *                crealm[1]                     Realm,
082         *                cname[2]                      PrincipalName,
083         *                cksum[3]                      Checksum OPTIONAL,
084         *                cusec[4]                      INTEGER,
085         *                ctime[5]                      KerberosTime,
086         *                subkey[6]                     EncryptionKey OPTIONAL,
087         *                seq-number[7]                 INTEGER OPTIONAL,
088         *  
089         *                authorization-data[8]         AuthorizationData OPTIONAL
090         * }
091         * 
092         * @param authenticator 
093         * @return The {@link DERSequence}.
094         */
095        private DERSequence encodeInitialSequence( Authenticator authenticator )
096        {
097            String clientRealm = authenticator.getClientPrincipal().getRealm();
098    
099            DERSequence sequence = new DERSequence();
100    
101            sequence.add( new DERTaggedObject( 0, DERInteger.valueOf( authenticator.getVersionNumber() ) ) );
102            sequence.add( new DERTaggedObject( 1, DERGeneralString.valueOf( clientRealm ) ) );
103            sequence.add( new DERTaggedObject( 2, PrincipalNameEncoder.encode( authenticator.getClientPrincipal() ) ) );
104    
105            // OPTIONAL
106            if ( authenticator.getChecksum() != null )
107            {
108                sequence.add( new DERTaggedObject( 3, ChecksumEncoder.encode( authenticator.getChecksum() ) ) );
109            }
110    
111            sequence.add( new DERTaggedObject( 4, DERInteger.valueOf( authenticator.getClientMicroSecond() ) ) );
112            sequence.add( new DERTaggedObject( 5, KerberosTimeEncoder.encode( authenticator.getClientTime() ) ) );
113    
114            // OPTIONAL
115            if ( authenticator.getSubSessionKey() != null )
116            {
117                sequence.add( new DERTaggedObject( 6, EncryptionKeyEncoder
118                    .encodeSequence( authenticator.getSubSessionKey() ) ) );
119            }
120    
121            // OPTIONAL
122            if ( authenticator.getSequenceNumber() > 0 )
123            {
124                sequence.add( new DERTaggedObject( 7, DERInteger.valueOf( authenticator.getSequenceNumber() ) ) );
125            }
126    
127            // OPTIONAL
128            if ( authenticator.getAuthorizationData() != null )
129            {
130                sequence.add( new DERTaggedObject( 8, AuthorizationDataEncoder
131                    .encode( authenticator.getAuthorizationData() ) ) );
132            }
133    
134            return sequence;
135        }
136    }