/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 *
 *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
 *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
 */

package sun.security.krb5.internal;

import sun.security.krb5.EncryptedData;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.RealmException;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;

/**
 * Implements the ASN.1 Authenticator type.
 *
 * <xmp>
 * KRB-CRED     ::= [APPLICATION 22] SEQUENCE {
 *      pvno            [0] INTEGER (5),
 *      msg-type        [1] INTEGER (22),
 *      tickets         [2] SEQUENCE OF Ticket,
 *      enc-part        [3] EncryptedData -- EncKrbCredPart
 * }
 * </xmp>
 *
 * <p>
 * This definition reflects the Network Working Group RFC 4120
 * specification available at
 * <a href="http://www.ietf.org/rfc/rfc4120.txt">
 * http://www.ietf.org/rfc/rfc4120.txt</a>.
 */

public class KRBCred {
        public Ticket[] tickets = null;
        public EncryptedData encPart;

        private int pvno;
        private int msgType;

        public KRBCred(Ticket[] new_tickets, EncryptedData new_encPart) throws IOException {
                pvno = Krb5.PVNO;
                msgType = Krb5.KRB_CRED;
                if (new_tickets != null) {
                    tickets = new Ticket[new_tickets.length];
                    for (int i = 0; i < new_tickets.length; i++) {
                        if (new_tickets[i] == null) {
                            throw new IOException("Cannot create a KRBCred");
                        } else {
                            tickets[i] = (Ticket)new_tickets[i].clone();
                        }
                    }
                }
                encPart = new_encPart;
        }

        public KRBCred(byte[] data) throws Asn1Exception,
                RealmException, KrbApErrException, IOException {
                init(new DerValue(data));
        }

        public KRBCred(DerValue encoding) throws Asn1Exception,
                RealmException, KrbApErrException, IOException {
                init(encoding);
        }

        /**
         * Initializes an KRBCred object.
         * @param encoding a single DER-encoded value.
         * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
         * @exception IOException if an I/O error occurs while reading encoded data.
         * @exception KrbApErrException if the value read from the DER-encoded data
         *  stream does not match the pre-defined value.
         * @exception RealmException if an error occurs while parsing a Realm object.
         */
        private void init(DerValue encoding) throws Asn1Exception,
                RealmException, KrbApErrException, IOException {
        if (((encoding.getTag() & (byte)0x1F) != (byte)0x16)
                        || (encoding.isApplication() != true)
                        || (encoding.isConstructed() != true))
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
        DerValue der, subDer;
                der = encoding.getData().getDerValue();
                if (der.getTag() != DerValue.tag_Sequence)
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
                subDer = der.getData().getDerValue();
            if ((subDer.getTag() & 0x1F) == 0x00) {
                        pvno = subDer.getData().getBigInteger().intValue();
                        if (pvno != Krb5.PVNO) {
                throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
                        }
                }
        else
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
                subDer = der.getData().getDerValue();
                if ((subDer.getTag() & 0x1F) == 0x01) {
                        msgType = subDer.getData().getBigInteger().intValue();
            if (msgType != Krb5.KRB_CRED)
                throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
                }
                else
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
        subDer = der.getData().getDerValue();
                if ((subDer.getTag() & 0x1F) == 0x02) {
                        DerValue subsubDer = subDer.getData().getDerValue();
            if (subsubDer.getTag() != DerValue.tag_SequenceOf) {
                                throw new Asn1Exception(Krb5.ASN1_BAD_ID);
                        }
            Vector<Ticket> v = new Vector<Ticket> ();
            while (subsubDer.getData().available() > 0) {
                                v.addElement(new Ticket(subsubDer.getData().getDerValue()));
                        }
            if (v.size() > 0) {
                                tickets = new Ticket[v.size()];
                                v.copyInto(tickets);
                        }
                }
                else
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
                encPart = EncryptedData.parse(der.getData(), (byte)0x03, false);

                if (der.getData().available() > 0)
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
        }


        /**
         * Encodes an KRBCred object.
         * @return the data of encoded EncAPRepPart object.
         * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
         * @exception IOException if an I/O error occurs while reading encoded data.
         */
        public byte[] asn1Encode() throws Asn1Exception, IOException {
        DerOutputStream temp, bytes, out;
        temp = new DerOutputStream();
        temp.putInteger(BigInteger.valueOf(pvno));
        out = new DerOutputStream();
        out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
                temp = new DerOutputStream();
                temp.putInteger(BigInteger.valueOf(msgType));
                out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
        temp = new DerOutputStream();
                for (int i = 0; i < tickets.length; i++) {
                        temp.write(tickets[i].asn1Encode());
                }
        bytes = new DerOutputStream();
        bytes.write(DerValue.tag_SequenceOf, temp);
        out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), bytes);
                out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), encPart.asn1Encode());
        bytes = new DerOutputStream();
        bytes.write(DerValue.tag_Sequence, out);
                out = new DerOutputStream();
                out.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte)0x16), bytes);
                return out.toByteArray();
        }

}
