

#include "common.js"


importPackage(javax.swing);
importPackage(java.util);
importPackage(java.security);
importPackage(java.security.spec);

var assetArray = new Array(
	'Znicte palebne prostredky nepritele',
	'Provedte utok na letadlovou lod',
	'Vypustte jaderne strely'
);

var publicKeyMap = new HashMap();
publicKeyMap.put('petr', "/home/petr/workspace/acp/src/acp/s3_sup_public_key.der");

var rng = new SecureRandom();
var CHALLENGE_SIZE = 16;

var requestedAsset;
var userName;
var challengeSent;
var tempPublicKeyEncoded;
var tempPublicKey;

var transactionIndex = 0;


function onMessage (transaction, receivedMessage) {
	var messageType = receivedMessage.getMessageType();

	if (messageType == MESSAGE_TYPE_START) {
		if (receivedMessage.findAvpWithType (AVP_PROVE))
			transactionIndex = 1;
		else
			transactionIndex = 0;
	}

	if (transactionIndex == 0) {
		switch (messageType) {
			case MESSAGE_TYPE_START:
				processStartAuthServer (transaction, receivedMessage);
				break;
			
			case MESSAGE_TYPE_RESPONSE:
				processResponseAuthServer (transaction, receivedMessage);
				break;
		
			default:
				server.destroyTransaction (transaction);
				break;
		}
	}
	else {
		switch (messageType) {
			case MESSAGE_TYPE_START:
				processStartAssetServer (transaction, receivedMessage);
				break;
			
			case MESSAGE_TYPE_RESPONSE:
				processResponseAssetServer (transaction, receivedMessage);
				break;
		
			default:
				server.destroyTransaction (transaction);
				break;
		}
	}
}

function processStartAuthServer (transaction, receivedMessage) {
	// Process received message
	var avpAsset = receivedMessage.findAvpWithType (AVP_ASSET_G);
	var assetType = bytesToString(avpAsset.getValue());
	
	var avpUser = receivedMessage.findAvpWithType (AVP_NAME_SUP_G);
	userName = bytesToString(avpUser.getValue());

	var avpPubKey = receivedMessage.findAvpWithType (AVP_PUB_KEY_SUP);
	tempPublicKeyEncoded = avpPubKey.getValue();

	var keySpec = X509EncodedKeySpec (tempPublicKeyEncoded);
	var keyFactory = KeyFactory.getInstance ("RSA");
	tempPublicKey = keyFactory.generatePublic(keySpec);

	// Send message
	challengeSent = new newByteArray (CHALLENGE_SIZE);
	rng.nextBytes (challengeSent);
	
	var avpChallenge = server.createAvp();	
	avpChallenge.setType (AVP_MESS_CHAL);
	avpChallenge.setValue (challengeSent);
	
	var messageToSend = server.createMessage();
	messageToSend.setMessageType (MESSAGE_TYPE_REQUEST);
	messageToSend.addAvp (avpChallenge);
	
	transaction.sendMessage (messageToSend);
}

function processResponseAuthServer (transaction, receivedMessage) {
	// Process received message
	var avpResponse = receivedMessage.findAvpWithType (AVP_MESS_RES);
	var response = avpResponse.getValue();

	var path = publicKeyMap.get (userName);
	var publicKey = readPublicKey (path);

	// Send message
	var messageToSend = server.createMessage();
	messageToSend.setMessageType (MESSAGE_TYPE_FINISH);

	var avpResult = server.createAvp();
	avpResult.setType (AVP_RESULT);

	var isOk = checkSignatureResponse (publicKey, response, challengeSent, tempPublicKeyEncoded);
	
	if (isOk) {
		var authPrivateKey = readPrivateKey("/home/petr/workspace/acp/src/acp/s3_auth_private_key.der");
		var certificate = createCertificate (authPrivateKey, new Array (stringToBytes (userName), tempPublicKeyEncoded));
		
		var avpAsset = server.createAvp();
		avpAsset.setType (AVP_ASSET_CONTENT);
		avpAsset.setValue (certificate);
	
		messageToSend.addAvp (avpAsset);

		avpResult.setValue (byteToArray (RESULT_OK));
	}
	else {
		avpResult.setValue (byteToArray (RESULT_ERROR));
	}

	messageToSend.addAvp (avpResult);
	transaction.sendMessage (messageToSend);
}

function processStartAssetServer (transaction, receivedMessage) {
	// Process received message
	var avpAsset = receivedMessage.findAvpWithType (AVP_ASSET_L);

	if (avpAsset == null)
		return;
	
	var assetValue = avpAsset.getValue();

	if (assetValue.length != 1)
		return;
	
	requestedAsset = assetValue[0];

	var avpPubKey = receivedMessage.findAvpWithType (AVP_PROVE);
	proveEncoded = avpPubKey.getValue();

	// Send message
	challengeSent = new newByteArray (CHALLENGE_SIZE);
	rng.nextBytes (challengeSent);
	
	var avpChallenge = server.createAvp();	
	avpChallenge.setType (AVP_MESS_CHAL);
	avpChallenge.setValue (challengeSent);
	
	var messageToSend = server.createMessage();
	messageToSend.setMessageType (MESSAGE_TYPE_REQUEST);
	messageToSend.addAvp (avpChallenge);
	
	transaction.sendMessage (messageToSend);
}

function processResponseAssetServer (transaction, receivedMessage) {
	// Process received message
	var avpResponse = receivedMessage.findAvpWithType (AVP_MESS_RES);
	var response = avpResponse.getValue();
	
	var authPublicKey = readPublicKey("/home/petr/workspace/acp/src/acp/s3_auth_public_key.der");
	var certificate = decodeCertificate (authPublicKey, proveEncoded);

	if (certificate != null) {
		userName = bytesToString(certificate[0]);

		var keySpec = new X509EncodedKeySpec (certificate[1]);
		var keyFactory = KeyFactory.getInstance ("RSA");
		tempPublicKey = keyFactory.generatePublic(keySpec);

		// Send message
		var messageToSend = server.createMessage();
		messageToSend.setMessageType (MESSAGE_TYPE_FINISH);

		var avpResult = server.createAvp();
		avpResult.setType (AVP_RESULT);

		var isOk = checkSignatureResponse (tempPublicKey, response, challengeSent, newByteArray (0));

		if (isOk) {
			var asset = '' + assetArray[requestedAsset];
			var avpAssetContent = server.createAvp();
	
			avpAssetContent.setType (AVP_ASSET_CONTENT);
			avpAssetContent.setValue (stringToBytes (asset));

			messageToSend.addAvp (avpAssetContent);

			avpResult.setValue (byteToArray (RESULT_OK));

		}
		else {
			avpResult.setValue (byteToArray (RESULT_ERROR));
		}
	}
	else {
		avpResult.setValue (byteToArray (RESULT_ERROR));
	}

	messageToSend.addAvp (avpResult);
	transaction.sendMessage (messageToSend);
	transactionIndex = 1;
}

