package SecureElection;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.security.KeyStore;
import java.util.Vector;
import javax.net.ssl.*;
import SecureElection.Common.Settings;
import SecureElection.Common.Voter;

/**
 * Created by Klas Eskilson on 15-11-16.
 */

public class CentralLegitimizationAgency {
    // constants
    private static final String CLATRUSTSTORE = Settings.KEYLOCATION + "CLATruststore.ks";
    private static final String CLAKEYSTORE   = Settings.KEYLOCATION + "CLAKeystore.ks";
    private static final String CLAPASSWORD   = "somephrase";

    private Vector<Voter> authorizedVoters = new Vector<>();

    BufferedReader serverInput, clientInput;
    PrintWriter serverOutput, clientOutput;
    SSLSocketFactory sslClientFact;

    private void setup() throws Exception {
        // load keystores
        KeyStore ks = KeyStore.getInstance("JCEKS");
        ks.load(new FileInputStream(CLAKEYSTORE),
                CLAPASSWORD.toCharArray());
        KeyStore ts = KeyStore.getInstance("JCEKS");
        ts.load(new FileInputStream(CLATRUSTSTORE),
                CLAPASSWORD.toCharArray());

        // setup key/trust managers
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, CLAPASSWORD.toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(ts);

        // setup ssl server
        SSLContext serverContext = SSLContext.getInstance("TLS");
        serverContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        SSLServerSocketFactory sslServer = serverContext.getServerSocketFactory();

        SSLServerSocket sss = (SSLServerSocket) sslServer.createServerSocket(Settings.CLA_PORT);
        sss.setEnabledCipherSuites(sss.getSupportedCipherSuites());

        // require client auth
        sss.setNeedClientAuth(true);

        // prepare incoming connections
        SSLSocket incoming = (SSLSocket) sss.accept();
        serverInput = new BufferedReader(
                new InputStreamReader(incoming.getInputStream()));
        serverOutput = new PrintWriter(incoming.getOutputStream(), true);

        System.out.println("CLA server running on port " + Settings.CLA_PORT);

        // setup ssl client
        SSLContext clientContext = SSLContext.getInstance("TLS");
        clientContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        sslClientFact = clientContext.getSocketFactory();

        System.out.println("CLA client setup.");
    }

    private void startClient(InetAddress hostAddr, int port) throws Exception {
        SSLSocket client = (SSLSocket) sslClientFact.createSocket(hostAddr, port);
        client.setEnabledCipherSuites(client.getSupportedCipherSuites());

        clientInput = new BufferedReader(new InputStreamReader(client.getInputStream()));
        clientOutput = new PrintWriter(client.getOutputStream(), true);
    }


    public static void main(String[] args) {
        try {
            CentralLegitimizationAgency cla = new CentralLegitimizationAgency();
            cla.run();
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
    }

    public void run() throws Exception {
        setup();
    }
}

@@ -905,32 +905,83 @@
 ows Exception %7B%0A
+        System.out.print(%22loading keystores... %22);%0A
         // load 
@@ -1282,24 +1282,119 @@
 arArray());%0A
+        System.out.print(%22done.%5Cn%22);%0A%0A        System.out.print(%22Preparing trust managers... %22);
 %0A        // 
@@ -1645,36 +1645,122 @@
 s);%0A
-%0A        // setup ssl server
+        System.out.print(%22done.%5Cn%22);%0A%0A        // setup ssl server%0A        System.out.print(%22Starting server... %22);
 %0A   
@@ -2151,25 +2151,24 @@
 tes());%0A
-%0A
         
 // requi
@@ -2163,348 +2163,431 @@
     
-// require client auth%0A        sss.setNeedClientAuth(true);%0A%0A        // prepare incoming connections%0A        SSLSocket incoming
+System.out.print(%22done.%5Cn%22);%0A%0A        // setup ssl client%0A        System.out.print(%22Setting up SSL Client... %22);%0A        SSLContext clientContext
  = 
-(
 SSL
-Socket) sss.accept();%0A        serverInput = new BufferedReader(%0A                new InputStreamReader(incoming.getInputStream()));%0A        serverOutput = new PrintWriter(incoming.getOutputStream(), 
+Context.getInstance(%22TLS%22);%0A        clientContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);%0A        sslClientFact = clientContext.getSocketFactory();%0A        System.out.print(%22done.%5Cn%22);%0A%0A        // require client auth%0A        sss.setNeedClientAuth(
 true);%0A
-%0A
     
@@ -2677,276 +2677,354 @@
  // 
-setup ssl client%0A        SSLContext clientContext = SSLContext.getInstance(%22TLS%22);%0A        clientContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);%0A        sslClientFact = clientContext.getSocketFactory();%0A%0A        System.out.println(%22CLA client setup.%22
+prepare incoming connections%0A        System.out.println(%22Starting server socket IO, accepting connections. %22);%0A        SSLSocket incoming = (SSLSocket) sss.accept();%0A        serverInput = new BufferedReader(%0A                new InputStreamReader(incoming.getInputStream()));%0A        serverOutput = new PrintWriter(incoming.getOutputStream(), true
 );%0A 
@@ -3750,32 +3750,81 @@
 ows Exception %7B%0A
+        System.out.println(%22Setting up CLA...%22);%0A
         setup();

Move CLA client initialization