// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb5.lib;

import krb5.lib.asn1.*;
import krb5.lib.ccache.*;

/**
 * Kerberos Application Response
 */
public class KrbApRep {
    
    /**
	 * Output buffer
	 */    
	byte[] obuf;
	
    /**
	 * Input buffer
	 */	
	byte[] ibuf;
	
	/**
	 * Encrypted application response part
	 * @see krb5.lib.EncAPRepPart
	 */	
	EncAPRepPart enc_part;

	/**
	 * Class constructor specifying Kerberos application request, encrypted key and sequence number
	 *
	 * @param ap_req is of type KrbApReq
	 * @param subKey is of type EncryptionKey
	 * @param seqNumber is of type Integer
	 * @exception KrbException an exception
	 * @see krb5.lib.KrbApReq
	 * @see krb5.lib.EncryptionKey
	 * @see krb5.lib.KrbException
	 */
	public KrbApRep(
		KrbApReq ap_req,
		EncryptionKey subKey,
		Integer seqNumber
		) throws KrbException {
		obuf = ApiUtil.ap_rep(
			ap_req.creds().key,
			ap_req.ctime(),
			subKey,
			seqNumber
		);
	}

	/**
	 * Returns the response
	 *
	 * @return byte[] is a result
	 */
	public byte[] msg() {
		return obuf;
	}

	/**
	 * Class constructor specifying message and the Kerberos Credential
	 *
	 * @param msg is of type byte[]
	 * @param tgs_creds is of type Credentials
	 * @exception KrbException an exception
	 * @see krb5.lib.Credentials
	 * @see krb5.lib.KrbException
	 */
	public KrbApRep(byte[] msg, Credentials tgs_creds) throws KrbException {
		ibuf = msg;
		EncodeRef ref = new EncodeRef(ibuf);
		APRep rep = null;
		try {
			rep = new APRep(ref);
    	} catch (Asn1Exception e) {
			rep = null;
    		KRBError err = new KRBError(ref);
    		String eText;
    		if (err.eText.charAt(err.eText.length() - 1) == 0)
    		    eText = err.eText.substring(0, err.eText.length() - 1);
    		else
    		    eText = err.eText;
 			throw new KrbException(err.errorCode, eText);
   		}

		byte[] enc_ap_rep_part =
			rep.encPart.decrypt(tgs_creds.key);
		ref = new EncodeRef(enc_ap_rep_part);
		enc_part = new EncAPRepPart(ref);
	}

	/**
	 * Authenticates the kerberos application request
	 *
	 * @param ap_req is of type KrbApReq
	 * @exception KrbException an exception
	 * @see krb5.lib.KrbApReq
	 * @see krb5.lib.KrbException
	 */
	public void authenticate(KrbApReq ap_req) throws KrbException {
		if (enc_part.ctime.getSeconds() != ap_req.ctime().getSeconds() ||
			enc_part.cusec != ap_req.ctime().getMicroSeconds())
			throw new KrbApErrException(Krb5.KRB_AP_ERR_MUT_FAIL);
	}

	/**
	 * Returns the subject key
	 *
	 * @return EncryptionKey is a result
	 * @see krb5.lib.EncryptionKey
	 */
	public EncryptionKey getSubKey() {
		if (enc_part != null) {
			return enc_part.subKey;
		}
		return null;
	}

	/**
	 * Returns sequence number
	 *
	 * @return Integer is a result
	 * @see java.lang.Integer
	 */
	public Integer getSeqNumber() {
		if (enc_part != null) {
			return enc_part.seqNumber;
		}
		return null;
	}

}
