// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb5.lib;

import krb5.lib.asn1.*;
import java.util.Vector;

/**
 * Encrypted ticket part
 */
public class EncTicketPart {

	/**
	 * Ticket flags
	 */
	public TicketFlags flags;

	/**
	 * Key
	 */
	public EncryptionKey key;

	/**
	 * Realm
	 */
	public Realm crealm;

	/**
	 * Name
	 */
	public PrincipalName cname;

	/**
	 * Transited encoding
	 */
	public TransitedEncoding transited;

	/**
	 * Authentication time
	 */
	public KerberosTime authtime;

	/**
	 * Start time
	 */
	public KerberosTime starttime; //optional

	/**
	 * End time
	 */
	public KerberosTime endtime;

	/**
	 * Renew till
	 */
	public KerberosTime renewTill; //optional

	/**
	 * Addresses
	 */
	public HostAddresses caddr; //optional

	/**
	 * Authorization data
	 */
	public AuthorizationData authorizationData; //optional

	/**
	 * Class constructor
	 *
	 * @param new_flags is of type TicketFlags
	 * @param new_key is of type EncryptionKey
	 * @param new_crealm is of type Realm
	 * @param new_cname is of type PrincipalName
	 * @param new_transited is of type TransitedEncoding
	 * @param new_authtime is of type KerberosTime
	 * @param new_starttime is of type KerberosTime
	 * @param new_endtime is of type KerberosTime
	 * @param new_renewTill is of type KerberosTime
	 * @param new_caddr is of type HostAddresses
	 * @param new_authorizationData is of type AuthorizationData
	 * @see krb5.lib.TicketFlags
	 * @see krb5.lib.EncryptionKey
	 * @see krb5.lib.Realm
	 * @see krb5.lib.PrincipalName
	 * @see krb5.lib.TransitedEncoding
	 * @see krb5.lib.KerberosTime
	 * @see krb5.lib.HostAddresses
	 * @see krb5.lib.AuthorizationData
	 */
	public EncTicketPart(
		TicketFlags new_flags,
		EncryptionKey new_key,
		Realm new_crealm,
		PrincipalName new_cname,
		TransitedEncoding new_transited,
		KerberosTime new_authtime,
		KerberosTime new_starttime,
		KerberosTime new_endtime,
		KerberosTime new_renewTill,
		HostAddresses new_caddr,
		AuthorizationData new_authorizationData
	) {
		flags = new_flags;
		key = new_key;
		crealm = new_crealm;
		cname = new_cname;
		transited = new_transited;
		authtime = new_authtime;
		starttime = new_starttime;
		endtime = new_endtime;
		renewTill = new_renewTill;
		caddr = new_caddr;
		authorizationData = new_authorizationData;
	}

	/**
	 * Class constructor
	 *
	 * @param data is of type byte[]
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @exception RealmException an exception
	 * @exception KrbApErrException an exception
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.BitStringException
	 * @see krb5.lib.RealmException
	 * @see krb5.lib.KrbApErrException
	 */
	public EncTicketPart(byte[] data)
		throws Asn1Exception, BitStringException, RealmException,
		KrbApErrException {
		this(new EncodeRef(data));
	}

	/**
	 * Class constructor
	 *
	 * @param ref is of type EncodeRef
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @exception RealmException an exception
	 * @exception KrbApErrException an exception
	 * @see krb5.lib.asn1.EncodeRef
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.BitStringException
	 * @see krb5.lib.RealmException
	 * @see krb5.lib.KrbApErrException
	 */
	public EncTicketPart(EncodeRef ref)
		throws Asn1Exception, BitStringException, RealmException,
		KrbApErrException {
		if (decode.TagApp(ref) != Krb5.KRB_ENC_TKT_PART)
			//XXX may not be the correct error code for a tag
			//mismatch on an encrypted structure
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);
		EncodeRef subRef = decode.Sequence(ref.startOfData());

		if (decode.Tag(subRef) == 0) {
			flags = new TicketFlags(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 1) {
			key = new EncryptionKey(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 2) {
			crealm = new Realm(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 3) {
			cname = new PrincipalName(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 4) {
			transited = new TransitedEncoding(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 5) {
			authtime = new KerberosTime(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 6) {
			starttime = new KerberosTime(subRef.startOfData());
			subRef.next();
		}

		if (decode.Tag(subRef) == 7) {
			endtime = new KerberosTime(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 8) {
			renewTill = new KerberosTime(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 9) {
			caddr = new HostAddresses(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 10) {
			authorizationData = new AuthorizationData(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence())
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);
	}

	/**
	 * Encodes the object in asn1
	 *
	 * @return byte[] is a result
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @see krb5.lib.BitStringException
	 * @see krb5.lib.Asn1Exception
	 */
	public byte[] asn1Encode() throws Asn1Exception,
		BitStringException {
		Vector tempEncTicketPart = new Vector();

		tempEncTicketPart.addElement(
			encode.prependExplicitTag(0, flags.asn1Encode()));
		tempEncTicketPart.addElement(
			encode.prependExplicitTag(1, key.asn1Encode()));
		tempEncTicketPart.addElement(
			encode.prependExplicitTag(2, crealm.asn1Encode()));
		tempEncTicketPart.addElement(
			encode.prependExplicitTag(3, cname.asn1Encode()));
		tempEncTicketPart.addElement(
			encode.prependExplicitTag(4, transited.asn1Encode()));
		tempEncTicketPart.addElement(
			encode.prependExplicitTag(5, authtime.asn1Encode()));

		if (starttime != null)
			tempEncTicketPart.addElement(
				encode.prependExplicitTag(6, starttime.asn1Encode()));

		tempEncTicketPart.addElement(
			encode.prependExplicitTag(7, endtime.asn1Encode()));

		if (renewTill != null)
			tempEncTicketPart.addElement(
				encode.prependExplicitTag(8, renewTill.asn1Encode()));

		if (caddr != null)
			tempEncTicketPart.addElement(
				encode.prependExplicitTag(9, caddr.asn1Encode()));

		if (authorizationData != null)
			tempEncTicketPart.addElement(
				encode.prependExplicitTag(10, authorizationData.asn1Encode()));

		byte[][] enc_ticket_part = new byte[tempEncTicketPart.size()][];
		for (int i = 0; i < tempEncTicketPart.size(); i++)
			enc_ticket_part[i] = (byte[])(tempEncTicketPart.elementAt(i));

		return encode.prependExplicitTag(asn1Class.APPLICATION,
			Krb5.KRB_ENC_TKT_PART, encode.Sequence(enc_ticket_part));
	}

}