//SafeUDPServer.java

import java.io.*;
import java.net.*;
import krb5.lib.*;
import krb5.lib.asn1.*;

class SafeUDPServer {
	public static void main(String args[]) {
		String password = "khttp";
		String principal = "khttp/drdoom.osf.org@drdoom.osf.org";
		int port = 8888;
		try {
			UDPServer server = new UDPServer(port);
			System.out.println("listening...");
			do {
				byte[] ibuf = server.receive();

				EncodeRef ref = new EncodeRef(ibuf);
				int part1_length = ref.end;
				byte[] part1 = new byte[part1_length];
				System.arraycopy(ibuf, 0, part1, 0, part1_length);
				System.out.println("received");

				KrbApReq ap_req = new KrbApReq(part1);
				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());

				ref.next();
				int part2_length = ref.end - part1_length;
				byte[] part2 = new byte[part2_length];
				System.arraycopy(ibuf, part1_length, part2, 0, part2_length);

				KrbRdSafe krb_safe = new KrbRdSafe(
					part2,
					ap_req.creds(),
					null, //EncryptionKey subSessionKey
					seqNumber,
					new HostAddress(server.getReceivedPacketAddress()),
					new HostAddress(),
					true, //boolean timestampRequired
					true //boolean seqNumberRequired
				);

				System.out.println("verified");

				byte[] userData = krb_safe.data();

				System.out.println("userData=\"" + new String(userData, 0) + "\"");

				KrbApRep ap_rep = new KrbApRep(
					ap_req,
					null, //EncryptionKey subSessionKey
					null //Integer startingSeqNumber
				);

				String str = "<" + new String(userData, 0) + ">";
				byte[] userData2 = new byte[str.length()];
				str.getBytes(0, str.length(), userData2, 0);

				KrbMkSafe krb_safe_reply = new KrbMkSafe(
					userData2,
					ap_req.creds(),
					null, //EncryptionKey subSessionKey
					new KerberosTime(KerberosTime.NOW),
					seqNumber,
					new HostAddress(),
					new HostAddress(InetAddress.getLocalHost())
				);

				ByteArrayOutputStream os = new ByteArrayOutputStream();
				os.write(ap_rep.msg());
				os.write(krb_safe_reply.msg());
				byte[] obuf = os.toByteArray();

				System.out.println("sending");
				server.send(obuf);
				System.out.println();

			}
			while(true);
		}
		catch (KrbException e) {
			e.printStackTrace();
			System.out.println(e.krbErrorMessage());
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("ok");
	}
}