package de.tudarmstadt.informatik.hostage; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.List; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.preference.PreferenceManager; import de.tudarmstadt.informatik.hostage.io.ByteArrayReaderWriter; import de.tudarmstadt.informatik.hostage.io.ReaderWriter; import de.tudarmstadt.informatik.hostage.io.StringReaderWriter; import de.tudarmstadt.informatik.hostage.logging.Logger; import de.tudarmstadt.informatik.hostage.logging.MyLocationManager; import de.tudarmstadt.informatik.hostage.logging.Record; import de.tudarmstadt.informatik.hostage.logging.Record.TYPE; import de.tudarmstadt.informatik.hostage.protocol.Protocol; import de.tudarmstadt.informatik.hostage.protocol.Protocol.TALK_FIRST; import de.tudarmstadt.informatik.hostage.ui.MainActivity; import de.tudarmstadt.informatik.hostage.wrapper.Packet; /** * Abstract class for a connection handler using a given protocol. * @author Mihai Plasoianu * @author Wulf Pfeiffer */ public class HoneyHandler implements Runnable { /** Time until the socket throws a time out. The time is in milliseconds. */ private int TIMEOUT; /** Time that a inputstream waits if no content is available to read again from stream. */ private int SLEEPTIME; protected Protocol protocol; private Socket client; protected Thread thread; private int attack_id; private int message_id; private String externalIP; private String BSSID; private String SSID; private HoneyListener listener; protected Logger log; /** * Constructor of the class. * Initializes class variables for communication and logging. * Then starts itself in a new Thread. * @param service The background service. * @param listener The Listener that called the service. * @param protocol The protocol on which the handler is running. * @param client A Socket for the communication with a remote client. */ public HoneyHandler(HoneyService service, HoneyListener listener, Protocol protocol, Socket client) { this.listener = listener; this.log = service.getLog(); this.protocol = protocol; this.client = client; this.thread = new Thread(this); SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(service); SLEEPTIME = pref.getInt("sleeptime", 500); TIMEOUT = pref.getInt("timeout", 30) * 1000; //TODO ThreadSicher? attack_id = getAndIncrementAttackID(pref); message_id = 0; SharedPreferences sessionPref = service.getSharedPreferences(MainActivity.SESSION_DATA, Context.MODE_PRIVATE); BSSID = sessionPref.getString(MainActivity.BSSID, null); SSID = sessionPref.getString(MainActivity.SSID, null); externalIP = sessionPref.getString(MainActivity.EXTERNAL_IP, null); setSoTimeout(client); thread.start(); } /** * Set the timeout of the socket to the hard coded time out variable. * @param client The socket * @see #TIMEOUT */ private void setSoTimeout(Socket client) { try { client.setSoTimeout(TIMEOUT); } catch (Exception e) { e.printStackTrace(); } } /** * Creates InputStream and OutputStream for the socket. * Starts communication with client. * When the client closes the connection or a time out occurs the handler is finished. */ @Override public void run() { InputStream in; OutputStream out; try { in = client.getInputStream(); out = client.getOutputStream(); talkToClient(in, out); } catch (Exception e) { e.printStackTrace(); } kill(); } /** * Sets the interrupt flag of the thread and tries to close the socket. */ public void kill() { thread.interrupt(); try { client.close(); } catch (Exception e) { e.printStackTrace(); } listener.refreshHandlers(); } /** * Determines if the interrupt flag of the thread is set. * @return True when the flag is set, else false. */ public boolean isTerminated() { return thread.isInterrupted(); } /** * Communicates with a client using the corresponding protocol implementation. * @param in InputStream of the socket. * @param out OutputStream of the socket. * @throws IOException */ protected void talkToClient(InputStream in, OutputStream out) throws IOException { ReaderWriter stream; if(protocol.getType().equals(byte[].class)) { stream = new ByteArrayReaderWriter(in, out, SLEEPTIME); } else { stream = new StringReaderWriter(in, out); } Packet inputLine; List outputLine; if (protocol.whoTalksFirst() == TALK_FIRST.SERVER) { outputLine = protocol.processMessage(null); stream.write(outputLine); for (Packet o : outputLine) { log.write(createRecord(TYPE.SEND, o.toString())); } } while (!thread.isInterrupted() && (inputLine = stream.read()) != null) { outputLine = protocol.processMessage(inputLine); log.write(createRecord(TYPE.RECEIVE, inputLine.toString())); if (outputLine != null) { stream.write(outputLine); for (Packet o : outputLine) { log.write(createRecord(TYPE.SEND, o.toString())); } } if (protocol.isClosed()) { break; } } } /** * Creates a Record for a message exchanged with a client. * @param type The type of the message. * @param packet The content of the message. * @return The Record representing the communication message. */ protected Record createRecord(TYPE type, String packet) { Record record = new Record(); record.setId(getAndIncrementMessageCounter()); record.setAttack_id(attack_id); record.setProtocol(protocol.toString()); record.setType(type); record.setTimestamp(System.currentTimeMillis()); record.setExternalIP(externalIP); record.setLocalIP(client.getLocalAddress()); record.setLocalPort(protocol.getPort()); record.setRemoteIP(client.getInetAddress()); record.setRemotePort(client.getPort()); record.setBSSID(BSSID); record.setSSID(SSID); record.setPacket(packet); if(MyLocationManager.getNewestLocation() != null){ record.setLatitude(MyLocationManager.getNewestLocation().getLatitude() ); record.setLongitude(MyLocationManager.getNewestLocation().getLongitude() ); record.setAccuracy(MyLocationManager.getNewestLocation().getAccuracy() ); record.setTimestampLocation(MyLocationManager.getNewestLocation().getTime() ); }else { record.setLatitude(0.0); record.setLongitude(0.0); record.setAccuracy(Float.MAX_VALUE); record.setTimestampLocation(0); } return record; } /** * Gets attack ID for the attack. Also increases the attack ID counter by one. Method is synchronized for thread safety. * @param pref The default SharedPreference of the application * @return Unique integer attack ID */ private synchronized int getAndIncrementAttackID(SharedPreferences pref){ Editor editor = pref.edit(); int attackID = pref.getInt("ATTACK_ID_COUNTER", 0); editor.putInt("ATTACK_ID_COUNTER", attack_id + 1); editor.commit(); return attackID; } /** * Gets current message ID for the record. Also increases the message ID counter by one. Method is synchronized for thread safety. * @return Unique integer message ID */ private synchronized int getAndIncrementMessageCounter(){ int msgID = message_id; message_id++; return msgID; } }