// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb4.lib;

import java.io.*;
import java.util.*;

public class Krb4ASReq {
	public byte pvno;
	public byte msgType;
	boolean littleEndian;
	public String cname;
	public String cinst;
	public String crealm;
	public long timestamp;
	public long lifetime;
	public String sname;
	public String sinst;
	public byte[] obuf;
	public byte[] ibuf;

	public Krb4ASReq(
		String new_cname,
		String new_cinst,
		String new_crealm,
		String new_sinst
	) throws Krb4Exception, IOException {
		this(
			new_cname,
			new_cinst,
			new_crealm,
			new Date().getTime(),
			Krb4.DEFAULT_TKT_LIFE * 5L * 60L * 1000L,
			Krb4.TICKET_GRANTING_TICKET,
			new_sinst
		);
	}

	public Krb4ASReq(
		String new_cname,
		String new_cinst,
		String new_crealm,
		long new_timestamp,
		long new_lifetime,
		String new_sname,
		String new_sinst
	) throws Krb4Exception, IOException {
		pvno = (byte)Krb4.KRB_PROT_VERSION;
		msgType = (byte)Krb4.AUTH_MSG_KDC_REQUEST;
		littleEndian = true;
		cname = new_cname;
		cinst = new_cinst;
		crealm = new_crealm;
		timestamp = new_timestamp;
		lifetime = new_lifetime;
		sname = new_sname;
		sinst = new_sinst;
		obuf = encode();
	}

	public byte[] encode() throws Krb4Exception, IOException {
		ByteArrayOutputStream o = new ByteArrayOutputStream();
		o.write(pvno);
		byte temp = (byte)((msgType << 1) +
			(littleEndian ? 1 : 0));
		o.write(temp);
		o.write(Krb4Encode.toBytes(cname));
		o.write(Krb4Encode.toBytes(cinst));
		o.write(Krb4Encode.toBytes(crealm));
		o.write(Krb4Encode.toBytes((int)(timestamp / 1000L)));
		o.write((byte)(lifetime / (1000L * 60L * 5L)));
		o.write(Krb4Encode.toBytes(sname));
		o.write(Krb4Encode.toBytes(sinst));
		return o.toByteArray();
	}

	public void send(String kdc) throws IOException {
		send(kdc, Krb4.KRB_PORT);
	}

	public void send(String kdc, int port) throws IOException {
		UDPClient kdcClient = new UDPClient(kdc, port);
		kdcClient.send(obuf);
		ibuf = kdcClient.receive();
	}

	public Krb4ASRep getKrb4ASRep() throws Krb4Exception {
		Krb4ASRep rep = null;
		try {
			rep = new Krb4ASRep(ibuf);
		} catch (Krb4Exception e) {
			rep = null;
			if (e.returnCode() == Krb4.RD_AP_MSG_TYPE) {
				Krb4KDCErr err = new Krb4KDCErr(ibuf);
				throw new Krb4Exception(err.error_code);
			}
			else
				throw e;
		}
		return rep;
	}
}
