/*
 * GNU.FREE 2002
 *
 * Copyright (c) 1999, 2000, 2001, 2002
 * The Free Software Foundation (www.fsf.org)
 *
 * GNU.FREE Co-ordinator: Jason Kitcat <jeep@free-project.org>
 *
 * GNU site: http://www.gnu.org/software/free/
 * 
 * FREE e-democracy site: http://www.free-project.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program (COPYING); if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
  
package PollManager;

import java.io.*;
import java.net.*;
import java.util.*;
import Free.util.*;

/**
 * Comms is the key class for launching communications with servers.
 *
 * The class launches a thread for TCP/IP communications and also contains
 * the methods for building packets. These packets are then held in
 * <code>message</code> for retrieval by <code>TCPClient</code>
 *
 * @version 1.0 8 September 2001
 * @author Jason Kitcat
 */
public class Comms {

	private Thread talker;
	private Runnable tk;
	protected TimeOutThread timer;
	
	/** constant to hold address of electoral roll server */
//#ifdef INSTALL
	protected static final String ER_address = "212.42.168.209";
	/** constant to store value being used as GNU.FREE port number
	 * For security reasons I recommend this is changed regularly
	 */
//#ifdef INSTALL
	protected static final int freePort = 1111;
	/** public and private keys for communications */
//#ifdef INSTALL
	protected static final String er_public_key = "001101000108009539E6A8D4A7F01D33BBF0E9E273373874AC8A3D226FC75E7F8C464B673E0DF6BEA371B169EC1EDA382A4D5BBD1973963C0B57BE8B0EE16ADF3194D2EAE630B15E2E1BEF2AC34AA8061341D3F6D6010F72210A671F8653A3FC0B03F6F31FB0E480444AE98658D95404EE62C2A5C063F830A4DB52EEB2E02EE6E9310C2A95875CE1D8A1DE8BA03271198A15076F1D65574C1A8C1FF39FAEE8A43EDE11DE22E41ED8E3B1DBC57E58C978259B7A846998E5CFCEDF1EB75F12A6481FD86AA29E2F9184F0BF522F0553EF806927D167187F4F3A7233EB6F3080A7E131C0911EF82C08A86FE4C0F0B6F53E580F81568C59BFE4C131B78F1E66B879858D6C05060058B1";
//#ifdef INSTALL
	protected static final String pm_private_key = "";
	
	/** For returning data from <code>TCPClient</code>. Not currently used. */
	private String fromServer;
	/** The HMAC key from the server's seed */
	private String server_hmac_key;
	/** The server's seed to build the HMAC key */
	private String server_hmac_seed;
	/** The HMAC key from the client's seed */
	private String client_hmac_key;
	/** The client's seed to build the HMAC key */
	private String client_hmac_seed;
	/** The packet sequence number */
	private int sequence_number;
	/** Holds the check time/date stamp for GNU.FREE security protocol */
	private Date check;
	/** Holds the session key for GNU.FREE security protocol */
	private String session_key;
	/** A string holding the packet to be initially sent to a server */
	private String message;
	/** A string holding the packet to be sent after the first in cases where message is an I packet */
	private String message_two;
	/** Stores the type of packet being sent, using the same flags as for
	 * section 1 of a GNU.FREE packet. This is used to determine which server
	 * to send <code>message</code> to.
	 */
	private char type;
	
	/* constructor */
	protected Comms() {
	
		// unneccessary but just in case!
		message = "";
		message_two = "";
		sequence_number = 0;
		fromServer = "";
	
	}

	/* simple acessor method */
	protected void setFromServer(String x) {
	
		fromServer = x;
	
	}
	
	/* simple acessor method */
	protected Date getCheck() {
	
		return check;
	
	}
	
	/* simple acessor method */
	protected void noCheck() {
	
		check = null;
	
	}
	
	/* simple acessor method */
	protected String getsession_key() {
	
		return session_key;
	
	}
	
	/* simple acessor method */
	protected void setsession_key(String x) {
	
		session_key = x;
	
	}
	
	/* simple acessor method */
	protected String getMessage() {
	
		return message;
	
	}

	/* simple acessor method */
	protected String getMessage_two() {
	
		return message_two;
	
	}

	/* simple acessor method */
	protected char getType() {
	
		return type;
	
	}

	/* simple acessor method */
	protected String getServer_hmac_key() {
	
		return server_hmac_key;
	
	}
	
	/* simple acessor method */
	protected void setServer_hmac_key(String x) {
	
		server_hmac_key = x;
	
	}
	
	/* simple acessor method */
	protected String getClient_hmac_key() {
	
		return client_hmac_key;
	
	}
	
	/* simple acessor method */
	protected void setClient_hmac_key(String x) {
	
		client_hmac_key = x;
	
	}
	
	/* simple acessor method */
	protected String getClient_hmac_seed() {
	
		return client_hmac_seed;
	
	}
	
	/* simple acessor method */
	protected String getServer_hmac_seed() {
	
		return server_hmac_seed;
	
	}
	
	/* simple acessor method */
	protected void setServer_hmac_seed(String x) {
	
		server_hmac_seed = x;
	
	}
	
	/* simple acessor method */
	protected int getSequence_number() {
	
		return sequence_number;
	
	}
	
	/* simple acessor method */
	protected void setSequence_number(int x) {
	
		sequence_number = x;
	
	}

	/**
	 * sendPMCheck dispatches a packet to the ERServer for voter authentication.
	 * Since 1.5 the PIN and password have been sent as digests.
	 *
	 * @param name  Name of user
	 * @param code  A unique code for this election only
	 * @param passw  Self explanatory
	 */
	protected void sendPMCheck(String name, String code, String passw) {
	
		tk = new TCPClient();
		talker = new Thread(tk);

		String reply, data;
		
		PollManager.carryOn = true;
		
		type = 'P';
			
		try {
			setsession_key(RSAEncrypt.makeSessionKey());
			setSequence_number(0);
		
			client_hmac_seed = RSAEncrypt.makeSessionKey();  // Initialise protocol values
			client_hmac_key = AuthSys.seedToKey(client_hmac_seed);

			message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"I|" + client_hmac_seed + "|" + AuthSys.makeDigest("I|" + client_hmac_seed));  // send protocol init
			
			message_two = new Packet('P',name + "-" + AuthSys.makeDigest(code) + "-" + AuthSys.makeDigest(passw),getsession_key(),er_public_key,getClient_hmac_key(),2).toCryptString(true); //real data
			//message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"P|" + name + "-" + AuthSys.makeDigest(code) + "-" + AuthSys.makeDigest(passw) + "|" + AuthSys.makeDigest("P|" + name + "-" + AuthSys.makeDigest(code) + "-" + AuthSys.makeDigest(passw)));
		
			timer = new TimeOutThread();
			timer.start(); // start timeout system
		
	 		talker.start();  // start communications
		 	
		 	reply = fromServer;
		 	
	 	} catch (Exception e) {
	 		PollManager.frame3.showError(PollManager.messages.getString("sendA_IO_err") + e.getMessage());
	 		PollManager.frame3.showError(PollManager.messages.getString("try_again"));
	 	}
	
	} //EOF sendAuth
	 

	/**
	 * sendPMVoted creates check date for security and sends a voted packet.
	 *
	 * @param name  Name of user
	 * @param code  A unique code for this election only
	 * @param password  Self explanatory
	 */
	 protected void sendPMVoted(String name, String code, String password) {	 
		
		tk = new TCPClient();
		talker = new Thread(tk);

		String reply;
		
		PollManager.carryOn = true;
		
		check = new Date();

		try {
			setsession_key(RSAEncrypt.makeSessionKey());
			setSequence_number(0);
		
			client_hmac_seed = RSAEncrypt.makeSessionKey();  // Initialise protocol values
			client_hmac_key = AuthSys.seedToKey(client_hmac_seed);
			
			message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"I|" + client_hmac_seed + "|" + AuthSys.makeDigest("I|" + client_hmac_seed));  // send protocol init
			
			message_two = new Packet('S',check.toString() + "-" + name + "-" + AuthSys.makeDigest(code) + "-" + AuthSys.makeDigest(password),getsession_key(),er_public_key,getClient_hmac_key(),2).toCryptString(true); //real data
			//message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"S|" + check.toString() + "-" + name + "-" + AuthSys.makeDigest(code) + "-" + AuthSys.makeDigest(password) + "|" + AuthSys.makeDigest("S|" + check.toString() + "-" + name + "-" + AuthSys.makeDigest(code) + "-" + AuthSys.makeDigest(password)));

			type = 'S';
			
			timer = new TimeOutThread();
			timer.start(); // start timeout system
		
	 		talker.start();  // start communications

			reply = fromServer;
			
	 	} catch (Exception e) {
	 		PollManager.frame2.showError(PollManager.messages.getString("sendV_IO_err") + e.getMessage());
	 	}
	 			
	 }  //EOF sendPMVoted


	/**
	 * sendDiag dispatches any diagnostic packets for debugging.
	 *
	 * @param msg  Data for packet
	 */
	 protected void sendDiag(String msg) {	 
		
		tk = new TCPClient();
		talker = new Thread(tk);

		String reply;
		
		PollManager.carryOn = true;
		
		type = 'D';
	
		try {
			setsession_key(RSAEncrypt.makeSessionKey());
			setSequence_number(0);
		
			client_hmac_seed = RSAEncrypt.makeSessionKey();  // Initialise protocol values
			client_hmac_key = AuthSys.seedToKey(client_hmac_seed);
			
			message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"I|" + client_hmac_seed + "|" + AuthSys.makeDigest("I|" + client_hmac_seed));  // send protocol init
			
			message_two = new Packet('D',msg,getsession_key(),er_public_key,getClient_hmac_key(),2).toCryptString(true); //real data
			
			timer = new TimeOutThread();
			timer.start(); // start timeout system
		
	 		talker.start();  // start communications
		 	
		 	reply = fromServer;
		 	
	 	} catch (Exception e) {
	 		PollManager.frame3.showError(PollManager.messages.getString("sendD_IO_err") + e.getMessage());
	 	}
	 			
	 }  //EOF sendDiag

	
} //EOF Class