//SecureUDPServer.java

import java.io.*;
import java.net.*;
import krb5.lib.*;

class SecureUDPServer {
	static UDPServer server;

	public static void main(String args[]) {
		int port = 8889;
		try {
			server = new UDPServer(port);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		do {
			subMain(args);
		}
		while(true);
	}

	public static void subMain(String args[]) {
		String password = "khttp";
		String principal = "khttp/drdoom.osf.org@drdoom.osf.org";
		try {
			System.out.println("listening...");

			byte[] ibuf = server.receive();

			System.out.println("received ap_req");

			KrbApReq ap_req = new KrbApReq(ibuf);
			ServiceName servName = new ServiceName(principal);
			EncryptionKey key = new EncryptionKey(password,
				servName.getSalt());
			ap_req.authenticate(
				key,
				null //new HostAddress(server.getInetAddress())
			);
			System.out.println("authenticated");
			System.out.println("client=\"" + ap_req.creds().client + "\"");
			System.out.println();

			LocalSeqNumber seqNumber = new LocalSeqNumber(
				ap_req.getSeqNumber());

			KrbApRep ap_rep = new KrbApRep(
				ap_req,
				null, //EncryptionKey subSessionKey
				null //Integer startingSeqNumber
			);

			System.out.println("sending ap_rep");
			server.send(ap_rep.msg());

			do {
				ibuf = server.receive();

				System.out.println("received");

				KrbRdPriv krb_priv = new KrbRdPriv(
					ibuf,
					ap_req.creds(),
					null, //EncryptionKey subSessionKey
					seqNumber,
					new HostAddress(server.getReceivedPacketAddress()),
					new HostAddress(),
					true, //boolean timestampRequired
					true //boolean seqNumberRequired
				);

				System.out.println("decrypted");

				byte[] userData = krb_priv.data();

				System.out.println("userData=\"" + new String(userData, 0) + "\"");

				String str = "<" + new String(userData, 0) + ">";
				byte[] userData2 = new byte[str.length()];
				str.getBytes(0, str.length(), userData2, 0);
				
				KrbMkPriv krb_priv_reply = new KrbMkPriv(
					userData2,
					ap_req.creds(),
					null, //EncryptionKey subSessionKey
					new KerberosTime(KerberosTime.NOW),
					seqNumber,
					new HostAddress(),
					new HostAddress(InetAddress.getLocalHost())
				);

				System.out.println("sending");
				server.send(krb_priv_reply.msg());
				System.out.println();
			}
			while(false);
		}
		catch (KrbException e) {
			e.printStackTrace();
			System.out.println(e.krbErrorMessage());
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		//System.out.println("ok");
	}
}