//tgstest.java

import java.io.*;
import java.net.*;
import krb5.lib.*;
import krb5.lib.asn1.*;
import krb5.lib.crypto.*;
import asn1test;

class tgstest {
	public static void main(String args[]) {
		String principal = "sanfilip";
		String password = "somewha0";
		String realm = "sanfilip.osf.org";
		String kdc = "sanfilip.osf.org";
		String service = "khttp/sanfilip.osf.org";

		//String principal = "sanfilip";
		//String password = "sanfilip";
		//String realm = "booboo.osf.org";
		//String kdc = "link.osf.org";
		//String service = "krbtgt/booboo.osf.org";

		//String principal = "sanfilip";
		//String password = "somewha0";
		//String realm = "cordelia.cell.osf.org";
		//String kdc = "homer.osf.org";
		//String service = "khttp/cordelia.cell.osf.org";

		//String principal = "cell_admin";
		//String password = "oil&gold";
		//String realm = "wisedev.opengroup.org";
		//String kdc = "sweden.osf.org";
		//String service = "krbtgt/wisedev.opengroup.org";

		int kdcport = 88;

		try {

			byte[] obuf = libtest.as_req(
				new KDCOptions(),
				new PrincipalName(principal, Krb5.KRB_NT_UNKNOWN),
				new Realm(realm)
			);

			InetAddress iaddr = InetAddress.getByName(kdc);
			DatagramPacket dgPacketOut = new DatagramPacket(obuf, obuf.length,
				iaddr, kdcport);
			byte ibuf[] = new byte[1024];
			DatagramPacket dgPacketIn = new DatagramPacket(ibuf, ibuf.length);

			System.out.println("as_req: " + obuf.length + " bytes");
			krb5.lib.asn1.util.print(obuf);
			System.out.println("\npress enter to send as_req");
			System.in.read();

			DatagramSocket dgSocket = new DatagramSocket();
			dgSocket.send(dgPacketOut);
			dgSocket.receive(dgPacketIn);

			System.out.println("as_rep: " + dgPacketIn.getLength() +
				" bytes");

			byte[] temp = new byte[dgPacketIn.getLength()];
			System.arraycopy(dgPacketIn.getData(), 0, temp, 0,
				dgPacketIn.getLength());

			System.out.println(util.byte2hexString(temp));
			System.out.println();
			krb5.lib.asn1.util.print(temp);

			EncodeRef ref = new EncodeRef(temp);
			ASRep rep = null;
			try {
			    rep = new ASRep(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;
        		System.out.println("krb_error " + err.errorCode + " " + eText);
    		}
    		if (rep == null)
    		    return;
	
			byte[] enc_as_rep_part =
				rep.encPart.decrypt(password + realm + principal);
			ref = new EncodeRef(enc_as_rep_part);
			EncASRepPart enc_part = new EncASRepPart(ref);

			krb5.lib.asn1.util.print(enc_part.asn1Encode());
			System.out.println();
			System.out.println("\npress enter to build tgs_req");
			System.in.read();

			byte[] obuf2 = libtest.tgs_req(
				new KDCOptions(),
				rep.ticket,
				enc_part.key,
				new PrincipalName(principal, Krb5.KRB_NT_UNKNOWN),
				new Realm(realm),
				new PrincipalName(service, Krb5.KRB_NT_SRV_HST)
			);

			System.out.println("tgs_req: " + obuf2.length + " bytes");
			krb5.lib.asn1.util.print(obuf2);
			System.out.println("\npress enter to send tgs_req");
			System.in.read();

			DatagramPacket dgPacketOut2 = new DatagramPacket(obuf2, obuf2.length,
				iaddr, kdcport);
			byte ibuf2[] = new byte[1024];
			DatagramPacket dgPacketIn2 = new DatagramPacket(ibuf2, ibuf2.length);

			DatagramSocket dgSocket2 = new DatagramSocket();
			dgSocket2.send(dgPacketOut2);
			dgSocket2.receive(dgPacketIn2);

			System.out.println("tgs_rep: " + dgPacketIn2.getLength() +
				" bytes");

			byte[] temp2 = new byte[dgPacketIn2.getLength()];
			System.arraycopy(dgPacketIn2.getData(), 0, temp2, 0,
				dgPacketIn2.getLength()); 

			System.out.println(util.byte2hexString(temp2));
			System.out.println();
			krb5.lib.asn1.util.print(temp2);
	
			EncodeRef ref2 = new EncodeRef(temp2);
			TGSRep rep2 = null;
			try {
			    rep2 = new TGSRep(ref2);
    		} catch (Asn1Exception e) {
				rep2 = null;
    		    KRBError err = new KRBError(ref2);
    		    String eText;
    		    if (err.eText.charAt(err.eText.length() - 1) == 0)
    		        eText = err.eText.substring(0, err.eText.length() - 1);
    		    else
    		        eText = err.eText;
        		System.out.println("krb_error " + err.errorCode + " " + eText);
    		}
    		if (rep2 == null)
    		    return;

			byte[] enc_tgs_rep_part =
				rep2.encPart.decrypt(enc_part.key);
			ref2 = new EncodeRef(enc_tgs_rep_part);
			EncTGSRepPart enc_part2 = new EncTGSRepPart(ref2);

			krb5.lib.asn1.util.print(enc_part2.asn1Encode());
			System.out.println();

			System.out.println("\npress enter to make krb_priv");
			System.in.read();

			byte[] userData = util.string2byte(" 01234567ABCDEFGHello; this is a secret message!");

			System.out.println("user_data=\"" + new String(userData, 0) + "\"\n");

			HostAddress sender = new HostAddress(Krb5.ADDRTYPE_INET,
					InetAddress.getLocalHost().getAddress());

			byte[] krb_priv = libtest.mk_priv(
				userData,
				enc_part2.key,
				null,
				sender,
				null
			);

			System.out.println("krb_priv: " + krb_priv.length + " bytes");
			krb5.lib.asn1.util.print(krb_priv);
			System.out.println("\npress enter to read krb_priv");
			System.in.read();

			EncodeRef ref3 = new EncodeRef(krb_priv);
			KRBPriv temp_krbPriv = new KRBPriv(ref3);

			byte[] userData2 = libtest.rd_priv(
				temp_krbPriv,
				enc_part2.key,
				null,
				sender,
				null
			);

			System.out.println("user_data=\"" + new String(userData2, 0) + "\"\n");

			System.out.println("ok");

		} catch (KrbException e) {
			e.printStackTrace();
			System.out.println("krb_error " + e.returnCode());

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}