package de.tudarmstadt.informatik.hostage; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Iterator; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.util.Log; import de.tudarmstadt.informatik.hostage.net.MyServerSocketFactory; import de.tudarmstadt.informatik.hostage.protocol.Protocol; import de.tudarmstadt.informatik.hostage.protocol.SSLProtocol; import de.tudarmstadt.informatik.hostage.ui.MainActivity; /** * Protocol listener class:
* Creates a Socket on the port of a given protocol and listens for incoming * connections.
* For each connection creates a Socket and instantiate an * {@link HoneyHandler}. * * @author Mihai Plasoianu * */ public class HoneyListener implements Runnable { private ArrayList handlers = new ArrayList(); /** * Determines the amount of active handlers. * * @return The number of active handlers. */ public int getHandlerCount() { return handlers.size(); } private Protocol protocol; private ServerSocket server; private Thread thread; private HoneyService service; // Shared Preferences private SharedPreferences pref; private ConnectionRegister conReg; // Editor for Shared preferences private Editor editor; private boolean running = false; /** * Determines if the service is running. * * @return True if the service is running, else false. */ public boolean isRunning() { return running; } /** * Constructor for the class. Instantiate class variables. * * @param service * The Background service that started the listener. * @param protocol * The Protocol on which the listener is running. */ public HoneyListener(HoneyService service, Protocol protocol) { this.service = service; this.protocol = protocol; pref = service.getApplicationContext().getSharedPreferences( MainActivity.SESSION_DATA, Context.MODE_PRIVATE); editor = pref.edit(); conReg = new ConnectionRegister(service); } public void run() { while (!thread.isInterrupted()) { addHandler(); } for (HoneyHandler handler : handlers) { handler.kill(); } } /** * Starts the listener. Creates a server socket runs itself in a new Thread * and notifies the background service. */ public void start() { try { server = new MyServerSocketFactory().createServerSocket(protocol .getPort()); (this.thread = new Thread(this)).start(); Log.i("BugSearch", "Open ServerSocket - ServerSocket is: " + ((server == null) ? "null" : "not null")); editor.putBoolean(protocol + MainActivity.LISTENER, true); editor.commit(); service.notifyUI(protocol.toString(), MainActivity.LISTENER); running = true; } catch (Exception e) { e.printStackTrace(); } } /** * Stops the listener. Closes the server socket, interrupts the Thread its * running in and notifies the background service. */ public void stop() { try { Log.i("BugSearch", "Closing ServerSocket - ServerSocket is: " + ((server == null) ? "null" : "not null")); server.close(); thread.interrupt(); editor.putBoolean(protocol + MainActivity.LISTENER, false); editor.commit(); service.notifyUI(protocol.toString(), MainActivity.LISTENER); running = false; } catch (Exception e) { e.printStackTrace(); } } /** * Determine the name of the protocol the listener is running on. * * @return Name of the protocol */ public String getProtocolName() { return protocol.toString(); } /** * Remove all terminated handlers from its internal ArrayList. */ public void refreshHandlers() { for (Iterator iterator = handlers.iterator(); iterator .hasNext();) { HoneyHandler handler = iterator.next(); if (handler.isTerminated()) { conReg.closeConnection(); iterator.remove(); } } } /** * Waits for an incoming connection, accepts it and starts a * {@link HoneyHandler} */ private void addHandler() { if (conReg.isConnectionFree()) { try { Socket client = server.accept(); conReg.newOpenConnection(); if (protocol.isSecure()) { startSecureHandler(client); } else { startHandler(client); } int handlerCount = pref.getInt(protocol + MainActivity.HANDLER_COUNT, 0); editor.putInt(protocol + MainActivity.HANDLER_COUNT, handlerCount + 1); editor.commit(); service.notifyUI(protocol.toString(), MainActivity.HANDLER_COUNT); } catch (Exception e) { e.printStackTrace(); } } } /** * Creates a SSLSocket out of the given socket and starts a * {@link HoneyHandler}. * * @param client * The socket with the accepted connection. * @throws Exception */ private void startSecureHandler(Socket client) throws Exception { SSLContext sslContext = ((SSLProtocol) protocol).getSSLContext(); SSLSocketFactory factory = sslContext.getSocketFactory(); SSLSocket sslClient = (SSLSocket) factory.createSocket(client, null, client.getPort(), false); sslClient.setUseClientMode(false); handlers.add(newInstance(service, this, protocol.getClass() .newInstance(), sslClient)); } /** * Starts a {@link HoneyHandler} with the given socket. * * @param client * The socket with the accepted connection. * @throws Exception */ private void startHandler(Socket client) throws Exception { handlers.add(newInstance(service, this, protocol.getClass() .newInstance(), client)); } /** * Creates a new instance of an {@link HoneyHandler}. * * @param service * The background service * @param listener * The listener that created the handler * @param protocol * The Protocol the handler will run on * @param client * The Socket the handler uses * @return A Instance of a {@link HoneyHandler} with the specified * parameter. */ private HoneyHandler newInstance(HoneyService service, HoneyListener listener, Protocol protocol, Socket client) { return new HoneyHandler(service, listener, protocol, client); } }