The SSL tunneling Client

Description: Deliverable 3 is a simple application that is written on top of JSSE (Java Secure Socket Extension) API. The goal of Deliverable 3 is to experiment with the functionalities that are provided by the JSSE and get ready to build a SSL applet and server in the final project. Deliverable 3 is designed to simulate the working model of the final project, so it includes three programs: a regular client, a SSL client and a SSL server. The regular client acts as a local media player; the SSL client plays the role of the media/tunneling applet and the SSL server works as the SSL/RTSP streaming server. In this application, the regular client can only request a connection to the SSL server through the SSL client. The SSL client opens an SSL connection based on the host name and the port number provided by the regular client. The communication between the SSL client and server is in a secure way: traveling data in both directions is encrypted. Once the SSL connection is established, the SSL client encrypted data it received from the regular client and send it to the server and decrypted data it received from the SSL server and send it to the regular client.

Usage: Run SSLServer first, then SSLClient, finally LocalClient.

/**
 The regular Client.
*/

import java.io.*;
import java.net.*;

public class LocalClient
{
    public static final String ENDL = "\r\n";

    public static void main(String[] args)
    {
        try
        {
            int agentPort = 5323;
            Socket socket = new Socket("localhost", agentPort);

            //The name and the port number of the SSL host
            String remoteHost = "localhost";
            int remotePort = 5123;

            BufferedWriter writer = new BufferedWriter(
               new OutputStreamWriter(socket.getOutputStream()) );

            String tunnelInfo = remoteHost + ENDL + Integer.toString(remotePort) + ENDL;
            writer.write(tunnelInfo);
            writer.flush();

            BufferedReader reader = new BufferedReader(
               new InputStreamReader(socket.getInputStream()) );

            //Wait for the server's response
            String response = reader.readLine();
            System.out.println(response);
            if(response.equalsIgnoreCase("SSL connection ok") )
            {
                String message = "Hello, SSL Server." + ENDL;
                writer.write(message);
                writer.flush();
                response = reader.readLine();
                System.out.println(response);
            }

            String sessionOver = "sessionover" + ENDL;
            writer.write(sessionOver);
            writer.flush();
            System.out.println("One Session Over");

            reader.close();
            writer.close();
            socket.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

------------------------------------------------------------------

/**
 The SSL tunneling client.
*/

import java.io.*;
import javax.net.ssl.*;
import java.net.*;

public class SSLClient
{

    private static int agentPort = 5323;

    public static void main(String[] args)
    {
        new SSLClient();
    }

    public SSLClient()
    {
        try
        {
            ServerSocket server = new ServerSocket(agentPort);

            while (true)
            {
                Socket incoming = server.accept();
                AgentSlave slave = new AgentSlave(incoming);
                slave.start();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    // SSL agent slave
    class AgentSlave extends Thread
    {
        public final String ENDL = "\r\n";

        //for regular client
        private Socket clientSocket;
        private SSLSocket sslSocket;
        private BufferedReader clientReader;
        private BufferedWriter clientWriter;

        //for SSLServer
        private BufferedReader sslReader;
        private BufferedWriter sslWriter;

        private boolean sessionOver;

        public AgentSlave(Socket st)
        {
            sessionOver = false;
            clientSocket = st;
            try
            {
                clientReader = new BufferedReader(
                  new InputStreamReader(clientSocket.getInputStream()));

                String remoteHost = clientReader.readLine();

                String s = clientReader.readLine();
                int remotePort = Integer.parseInt(s);

                //Constructs a TCP connection to the SSL server
                SSLSocketFactory sslFactory =
                  (SSLSocketFactory) SSLSocketFactory.getDefault();
                sslSocket =
                  (SSLSocket) sslFactory.createSocket(remoteHost, remotePort);

                //Initialize the security attributes
                sslSocket.startHandshake();

                sslReader = new BufferedReader(
                  new InputStreamReader(sslSocket.getInputStream()));

                String mesg = "SSL client reqires connection for local client." + ENDL;
                sendToServer(mesg);

                mesg = sslReader.readLine();
                System.out.println(mesg);

                if (mesg.indexOf("SSL connection ok") != -1)
                {
                    mesg = mesg + ENDL;
                    sendToClient(mesg);
                } else
                {
                    System.out.println("sendToClient . fail");
                    sendToClient("SSL connection failed.");
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        public void run()
        {
            String mesg;
            while (!sessionOver)
            {
                mesg = receiveFromClient() + ENDL;
                if(sessionOver)
                    break;
                sendToServer(mesg);
                mesg = receiveFromServer()+ ENDL;
                sendToClient(mesg);
            }

            try
            {
                clientReader.close();
                clientWriter.close();
                clientSocket.close();

                sslReader.close();
                sslWriter.close();
                sslSocket.close();

                System.out.println("One Session Over." + ENDL);

            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        public String receiveFromClient()
        {
            String message = "";
            try
            {
                message = clientReader.readLine();
                if (message.equalsIgnoreCase("sessionover"))
                {
                    sendToServer("sessionover" + ENDL);
                    sessionOver = true;
                } else
                {
                    sessionOver = false;
                    System.out.println(message);
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return message;
        }

        public String receiveFromServer()
        {
            String mesg = "";
            try
            {
                mesg = sslReader.readLine();
                System.out.println(mesg);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return mesg;
        }

        public void sendToClient(String message)
        {
            try
            {
                clientWriter = new BufferedWriter(
                  new OutputStreamWriter(clientSocket.getOutputStream()));
                clientWriter.write(message);
                clientWriter.flush();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        public void sendToServer(String message)
        {
            try
            {
                sslWriter = new BufferedWriter(
                  new OutputStreamWriter(sslSocket.getOutputStream()));
                sslWriter.write(message);
                sslWriter.flush();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

------------------------------------------------------------------

/**
 The SSL server
*/

import javax.net.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import javax.net.ssl.*;


public class SSLServer
{
    private static int port = 5123;

    public static void main(String args[])
    {
        new SSLServer();
    }

    public SSLServer()
    {
        try
        {
            //the following code (above the while)is from JSSE sample code provided by Sum.
            SSLServerSocketFactory ssf = null;
            // set up key manager to do server authentication
            SSLContext ctx;
            KeyManagerFactory kmf;
            KeyStore ks;
            char[] passphrase = "passphrase".toCharArray();

            ctx = SSLContext.getInstance("TLS");
            kmf = KeyManagerFactory.getInstance("SunX509");
            ks = KeyStore.getInstance("JKS");

            ks.load(new FileInputStream("testkeys"), passphrase);
            kmf.init(ks, passphrase);
            ctx.init(kmf.getKeyManagers(), null, null);

            ssf = ctx.getServerSocketFactory();

            ServerSocket sslServer = ssf.createServerSocket(port);

            while (true)
            {
                Socket incoming = sslServer.accept();
                ServerSlave slave = new ServerSlave(incoming);
                slave.start();
            }
        }
        catch (Exception e)
        {
            System.out.println("Exception caught: " + e);
        }
    }

    // SSL Server Slave
    class ServerSlave extends Thread
    {
        public static final String ENDL = "\r\n";

        private Socket socket;
        private BufferedReader reader;
        private BufferedWriter writer;
        private boolean isStartMesg;

        public ServerSlave(Socket st)
        {
            socket = st;
            isStartMesg = false;
        }

        public void run()
        {
            boolean sessionOver = false;
            while (!sessionOver)
            {
                System.out.flush();
                sessionOver = receive();
                sendResponse();
            }

            try
            {
                reader.close();
                writer.close();
                socket.close();
                System.out.println("One Session Over." + ENDL);
            }
            catch (Exception e)
            {
                System.out.println("Exception caught: " + e);
            }
        }

        public boolean receive()
        {
            boolean sessionOver = false;

            try
            {
                reader = new BufferedReader(
                  new InputStreamReader(socket.getInputStream()));
                String message = reader.readLine();
                if (message.equalsIgnoreCase("sessionover"))
                    sessionOver = true;
                else if (
                  message.equalsIgnoreCase(
                     "SSL client reqires connection for local client."))
                {
                    isStartMesg = true;
                } else
                {
                    sessionOver = false;
                    System.out.println(message);
                }
            }
            catch (Exception e)
            {
                System.out.println("Exception caught: " + e);
            }
            return sessionOver;

        }

        public void sendResponse()
        {
            try
            {
                writer = new BufferedWriter(
                  new OutputStreamWriter(socket.getOutputStream()));

                if (isStartMesg)
                {
                    writer.write("SSL connection ok" + ENDL);
                    isStartMesg = false;
                }
                else
                {
                    String message = "Hello, SSL client." + ENDL;
                    writer.write(message);
                }
                writer.flush();
            }
            catch (Exception e)
            {
                System.out.println("Exception caught: " + e);
            }
        }
    }
}