summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/taskmanager/tasks/SSLRelayTask.java
blob: a9c02149deee14b14f5ae1dd28f491b150159fc3 (plain) (tree)



























































                                                          
        

                                     































                                                                                                           
                           





                                                                                      
                             
                                                                     

                                                                
                                            

                                                                
                                            

                         















                                                                                
                          













                                                                                
                          
                 















                                                                                                              


















                                                                                                           
                                 








                                                        
                                     
                 
                            




































                                                                                 
package org.openslx.taskmanager.tasks;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.openslx.taskmanager.api.AbstractTask;

import com.google.gson.annotations.Expose;

public class SSLRelayTask extends AbstractTask {

	@Expose
	private String clientAIp;
	@Expose
	private int clientAPort;
	
	@Expose
	private String clientBIp;
	@Expose
	private int clientBPort;
	
	@Expose
	private boolean auth;

	private SSLSocket sockA;
	private SSLSocket sockB;
	
	private Relay aToB;
	private Relay bToA;
	
	private boolean enabled;
	
	private Output status;
	
	/**
	 * ###ONLY FOR TESTING###
	 * 1. initialize SocketFactory w/wo authentication
	 * ###ONLY FOR TESTING###
	 * 
	 * 1a. set system properties (if auth==true)
	 * 2. initialize sockets to A and B
	 * 3. initialize relays to/from A and B
	 */
	@Override
	protected boolean initTask() {
	
		this.setStatusObject(status);	
		return true;
	}
	
	@Override
	protected boolean execute() {
		SSLSocketFactory ssf = initSSLSocketFactory();
		if (ssf==null) {
			status.error = "Could not initialize SSLSocketFactory";
			return false;
		}
		try {
			initSockets(ssf);	
			initRelays();
		} catch (UnknownHostException uhx) {
			status.error = "One of the hosts to relay to/from is unknown: " + uhx.getMessage();
			return close();
		} catch (IOException iox) {
			status.error = iox.getMessage();
			return close();
		}
		
		Thread aToBThread = initThread('a');
		Thread bToAThread = initThread('b');
		
		if (aToBThread == null || bToAThread == null) {
			status.error = "Could not initialize Threads.";
			return close();
		}

		while(enabled) {
			aToBThread.start();
			bToAThread.start();
		}
		return close();
	}
	
	private SSLSocketFactory initSSLSocketFactory () {
		if (auth) {
			System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
			System.setProperty("javax.net.ssl.trustStore", "cacerts.jks");
			
			return (SSLSocketFactory) SSLSocketFactory.getDefault();
		}
		else {
			try {
				return trustAll().getSocketFactory();
			} catch (NoSuchAlgorithmException nax) {
				status.error = nax.getMessage();
				return null;
			} catch (KeyManagementException kmx) {
				status.error = kmx.getMessage();
				return null;
			}
		}
	}
	
	private Thread initThread (char source) {
		if (source == 'a') {
			return new Thread() {
				public void run() {
					try {
						aToB.relay();
					} catch (IOException iox) {
						status.error = iox.getMessage();
						return;
					} catch (InterruptedException ix) {
						status.error = ix.getMessage();
						return;
					}
				};
			};
		}
		else if (source == 'b') {
			return new Thread() {
				public void run() {
					try {
						bToA.relay();
					} catch (IOException iox) {
						status.error = iox.getMessage();
						return;
					} catch (InterruptedException ix) {
						status.error = ix.getMessage();
						return;
					}
				};
			};
		}
		else
			return null;
	}
	
	private void initSockets (SSLSocketFactory ssf) throws IOException, UnknownHostException {
		sockA = (SSLSocket) ssf.createSocket(clientAIp, clientAPort);
		System.out.println("connected to " + clientAIp + " on port " + Integer.toString(clientAPort));
		sockB = (SSLSocket) ssf.createSocket(clientBIp, clientBPort);
		System.out.println("connected to " + clientBIp + " on port " + Integer.toString(clientBPort));
	}
	
	private void initRelays () throws IOException {
		aToB = new Relay(sockA, sockB);
		System.out.println("relay created from " + clientAIp + " to " + clientBIp);
		bToA = new Relay(sockB, sockA);
		System.out.println("relay created from " + clientBIp + " to " + clientAIp);
	}
	
	/**
	 * Create all-trusting TrustManager for no-auth mode
	 */
	private SSLContext trustAll () throws NoSuchAlgorithmException, KeyManagementException {
		TrustManager[] trustAllMan = new TrustManager[] {new X509TrustManager() {
				public java.security.cert.X509Certificate[] getAcceptedIssuers() {
					return null;
				}
				public void checkClientTrusted(X509Certificate[] certs, String authType) {}
				public void checkServerTrusted(X509Certificate[] certs, String authType) {}
			}
		};
		SSLContext ctx = SSLContext.getInstance("SSL");
		ctx.init(null, trustAllMan, new java.security.SecureRandom());
		return ctx;
	}
	
	private boolean close() {
		try {
			if (aToB != null)
				aToB.close();
			if (bToA != null)
				bToA.close();
			sockA.close();
			sockB.close();
		} catch (IOException iox) {
			status.error = iox.getMessage();
			return false;
		}
		return true;
	}
	
	/**
	 * Do the actual relaying in one direction
	 */
	private class Relay {
		private InputStream in;
		private OutputStream out;
		
		private byte[] buffer = new byte[16384];
		
		public Relay (SSLSocket sIn, SSLSocket sOut) throws IOException {
			in = sIn.getInputStream();
			out = sOut.getOutputStream();
		}
		
		public void relay() throws IOException, InterruptedException {
			int readBytes = in.read(buffer);
			
			out.write(buffer, 0, readBytes);
		}
		
		public void close() throws IOException {
			in.close();
			out.close();
		}
	}
	
	/**
	 * Output - contains additional status data of this task
	 */
	@SuppressWarnings( "unused" )
	private static class Output
	{
		protected String error = null;
	}
}