//////////////////////////////////////////////////////////////////////////// 
// 
// Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1993, 1994, 1995.
// Unpublished work.  All Rights Reserved.
// 
// The software contained on this media is the property of the
// DSTC Pty Ltd.  Use of this software is strictly in accordance
// with the license agreement in the accompanying LICENSE.DOC 
// file. If your distribution of this software does not contain 
// a LICENSE.DOC file then you have no rights to use this 
// software in any manner and should contact DSTC at the address 
// below to determine an appropriate licensing arrangement.
// 
//      DSTC Pty Ltd
//      Level 7, GP South
//      University of Queensland
//      St Lucia, 4072
//      Australia
//      Tel: +61 7 3365 4310
//      Fax: +61 7 3365 4311
//      Email: jcsi@dstc.qut.edu.au
// 
// This software is being provided "AS IS" without warranty of
// any kind.  In no event shall DSTC Pty Ltd be liable for
// damage of any kind arising out of or in connection with
// the use or performance of this software.
// 
//////////////////////////////////////////////////////////////////////////// 

package com.dstc.security.kerberos.v5;

import java.util.Vector;
import java.util.Enumeration;

import com.dstc.security.kerberos.v5.base.*;
import com.dstc.security.kerberos.v5.crypto.EncryptionKey;

import com.dstc.security.asn1.Asn1;
import com.dstc.security.asn1.Asn1Exception;
import com.dstc.security.asn1.Explicit;
import com.dstc.security.asn1.Sequence;

/**
 * <p>A class representing the Kerberos ASN.1 structure KrbCredInfo.
 *
 * <pre>
 *   KrbCredInfo    ::= SEQUENCE {
 *                        key[0]                 EncryptionKey,
 *                        prealm[1]              Realm OPTIONAL,
 *                        pname[2]               PrincipalName OPTIONAL,
 *                        flags[3]               TicketFlags OPTIONAL,
 *                        authtime[4]            KerberosTime OPTIONAL,
 *                        starttime[5]           KerberosTime OPTIONAL,
 *                        endtime[6]             KerberosTime OPTIONAL
 *                        renew-till[7]          KerberosTime OPTIONAL,
 *                        srealm[8]              Realm OPTIONAL,
 *                        sname[9]               PrincipalName OPTIONAL,
 *                        caddr[10]              HostAddresses OPTIONAL
 *                      }
 * </pre>
 *
 * @author Nam Tran
 */
public final class KrbCredInfo extends Sequence 
{
  private EncryptionKey key = null;
  private Realm pRealm = null;
  private PrincipalName pName = null;
  private TicketFlags flags = null;
  private KerberosTime authTime = null;
  private KerberosTime startTime = null;
  private KerberosTime endTime = null;
  private KerberosTime renewTill = null;
  private Realm sRealm = null;
  private PrincipalName sName = null;
  private HostAddresses caddr = null;

  /**
   * Construct a KrbCredInfo
   */
  public KrbCredInfo(EncryptionKey key, Realm pRealm, PrincipalName pName,
                     TicketFlags flags, KerberosTime authTime,
                     KerberosTime startTime, KerberosTime endTime,
                     KerberosTime renewTill, Realm sRealm,
                     PrincipalName sName, HostAddresses caddr) 
  {
    this.key = key;
    Explicit exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 0);
    exp.addComponent(key);
    addComponent(exp);

    if (pRealm != null) 
    {
      this.pRealm = pRealm;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 1);
      exp.addComponent(pRealm);
      addComponent(exp);
    }

    if (pName != null) 
    {
      this.pName = pName;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 2);
      exp.addComponent(pName);
      addComponent(exp);
    }

    if (flags != null) 
    {
      this.flags = flags;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 3);
      exp.addComponent(flags);
      addComponent(exp);
    }

    if (authTime != null) 
    {
      this.authTime = authTime;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 4);
      exp.addComponent(authTime);
      addComponent(exp);
    }

    if (startTime != null) 
    {
      this.startTime = startTime;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 5);
      exp.addComponent(startTime);
      addComponent(exp);
    }

    if (endTime != null) 
    {
      this.endTime = endTime;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 6);
      exp.addComponent(endTime);
      addComponent(exp);
    }

    if (renewTill != null) 
    {
      this.renewTill = renewTill;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 7);
      exp.addComponent(renewTill);
      addComponent(exp);
    }

    if (sRealm != null) 
    {
      this.sRealm = sRealm;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 8);
      exp.addComponent(sRealm);
      addComponent(exp);
    }

    if (sName != null) 
    {
      this.sName = sName;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 9);
      exp.addComponent(sName);
      addComponent(exp);
    }

    if (caddr != null) 
    {
      this.caddr = caddr;
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 10);
      exp.addComponent(caddr);
      addComponent(exp);
    }
  }

  /**
   * Construct a KrbCredInfo from a DER encoding
   */
  public KrbCredInfo(byte[] encoded) throws Asn1Exception 
  {
    doDecode(encoded);

    Enumeration comps = getComponents().elements();
    
    Explicit exp = (Explicit) comps.nextElement();
    if (exp.getTagNumber() != 0)
      throw new Asn1Exception("Bad tag number");
    this.key = new EncryptionKey(exp.getComponent().encode());

    int prevTag = 0, tag;
    while (comps.hasMoreElements()) 
    {
      exp = (Explicit) comps.nextElement();
      tag = exp.getTagNumber();
      if (tag <= prevTag) throw new Asn1Exception("Sequence out of order");
      prevTag = tag;

      switch (tag) 
      {
        case 1:
          this.pRealm = new Realm(exp.getComponent().encode());
       break;

        case 2:
          this.pName = new PrincipalName(exp.getComponent().encode());
        break;

        case 3:
          this.flags = new TicketFlags(exp.getComponent().encode());
        break;

        case 4:
          this.authTime = new KerberosTime(exp.getComponent().encode());
        break;

        case 5:
          this.startTime = new KerberosTime(exp.getComponent().encode());
        break;

        case 6:
          this.endTime = new KerberosTime(exp.getComponent().encode());
        break;

        case 7:
          this.renewTill = new KerberosTime(exp.getComponent().encode());
        break;

        case 8:
          this.sRealm = new Realm(exp.getComponent().encode());
        break;

        case 9:
          this.sName = new PrincipalName(exp.getComponent().encode());
        break;

        case 10:
          this.caddr = new HostAddresses(exp.getComponent().encode());
        break;

        default:
  throw new Asn1Exception("Invalid context tag number in sequence");
      }
    }
  }
}
