Browse Source

Added documentation for the protocols

qam 10 years ago
parent
commit
758e508742

+ 16 - 0
src/de/tudarmstadt/informatik/hostage/commons/HelperUtils.java

@@ -153,4 +153,20 @@ public final class HelperUtils {
 			return new DefaultHttpClient();
 		}
 	}
+	
+	public static byte[] concat(byte[]... bytes) {
+		int newSize = 0;
+		for (byte[] b : bytes)
+			newSize += b.length;
+		byte[] dst = new byte[newSize];
+
+		int currentPos = 0;
+		int newPos;
+		for (byte[] b : bytes) {
+			newPos = b.length;
+			System.arraycopy(b, 0, dst, currentPos, newPos);
+			currentPos += newPos;
+		}
+		return dst;
+	}
 }

+ 1 - 0
src/de/tudarmstadt/informatik/hostage/protocol/ECHO.java

@@ -20,6 +20,7 @@ public class ECHO implements Protocol<ByteArray>{
 	@Override
 	public List<ByteArray> processMessage(ByteArray message) {
 		List<ByteArray> response = new ArrayList<ByteArray>();
+		//respond with the received message
 		response.add(message);
 		return response;
 	}

+ 9 - 1
src/de/tudarmstadt/informatik/hostage/protocol/FTP.java

@@ -4,12 +4,20 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Pattern;
 
+/**
+ * FTP protocol
+ */
 public final class FTP implements Protocol<String> {
-
+	/**
+	 * Represents the states of the protocol
+	 */
 	private static enum STATE {
 		NONE, OPEN, CLOSED, USER, LOGGED_IN
 	};
 
+	/**
+	 * Denotes in which state the protocol is right now
+	 */
 	private STATE state = STATE.NONE;
 
 	@Override

+ 23 - 7
src/de/tudarmstadt/informatik/hostage/protocol/HTTP.java

@@ -3,12 +3,22 @@ package de.tudarmstadt.informatik.hostage.protocol;
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * HTTP protocol
+ * @author Wulf Pfeiffer
+ */
 public final class HTTP implements Protocol<String> {
 	
+	/**
+	 * Represents the states of the protocol
+	 */
 	private enum STATE {
 		NONE, CLOSED
 	}
 
+	/**
+	 * Denotes in which state the protocol is right now
+	 */
 	private STATE state = STATE.NONE;
 	
 	@Override
@@ -25,7 +35,6 @@ public final class HTTP implements Protocol<String> {
 	public List<String> processMessage(String message) {
 		List<String> response = new ArrayList<String>();
 		request = message + request;
-		System.out.println(request);
 		
 		switch(state) {
 		case NONE:
@@ -76,7 +85,13 @@ public final class HTTP implements Protocol<String> {
 	public String toString() {
 		return "HTTP";
 	}
-	
+
+	/**
+	 * Builds a html response that can be sent
+	 * @param code response code that was determined
+	 * @param type request type that was sent by the client
+	 * @return the html response
+	 */
 	private String buildPacket(String code, String type) {
 		String doc = "";
 		if(type.equals(get)) doc = htmlDoc;
@@ -87,9 +102,10 @@ public final class HTTP implements Protocol<String> {
 		return version + code + headerPrefix + doc.length() + headerSuffix + doc;
 	}
 
+	/** Whole request that was sent by the client */
 	private String request = "";
 	private String version = "HTTP/1.1";
-	
+	//request codes
 	private String options 	= "OPTIONS";
 	private String get 		= "GET";
 	private String head 	= "HEAD";
@@ -98,13 +114,13 @@ public final class HTTP implements Protocol<String> {
 	private String delete	= "DELETE";
 	private String trace	= "TRACE";
 	private String connect	= "CONNECT";
-	
+	//response codes
 	private String ok 					= " 200 OK\r\n";
 	private String badRequest 			= " 400 Bad Request\r\n";
 	private String methodNotAllowed 	= " 405 Method Not Allowed\r\n";
 	private String versionUnsupported 	= " 505 HTTP Version not supported\r\n";
 	
-	
+	//html header pre and suffix
 	private String headerPrefix =				
 			"Date: Mon, 01 Jul 2013 18:27:55 GMT\r\n" +
 			"Server: Apache/2.2.22 (Debian)\r\n" +
@@ -116,7 +132,7 @@ public final class HTTP implements Protocol<String> {
 			"Connection: Keep-Alive\r\n" +
 			"Content-Type: text/html\r\n" +
 			"\r\n";
-
+	//html website
 	private String htmlDoc = 
 			"<!doctype html>\n" +
 			"<html lang=\"en\">\n" +
@@ -129,7 +145,7 @@ public final class HTTP implements Protocol<String> {
 			"<p>Congratulations.</p>\n" +
 			"</body>\n" +
 			"</html>";
-	
+	//html error pre and suffix
 	private String errorHtmlPrefix =
 			"<!doctype html>\n" +
 			"<html lang=\"en\">\n" +

+ 43 - 45
src/de/tudarmstadt/informatik/hostage/protocol/MySQL.java

@@ -4,16 +4,27 @@ import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
 
-
+/**
+ * MySQL protocol
+ * @author Wulf Pfeiffer
+ */
 public class MySQL implements Protocol<ByteArray>{
+	/**
+	 * Represents the states of the protocol
+	 */
 	private enum STATE {
 		NONE, CONNECTED, LOGIN_INFO, CLOSED
 	}
 	
+	/**
+	 * Denotes in which state the protocol is right now
+	 */
 	private STATE state = STATE.NONE;
 	
+	/** last request from client */ 
 	private byte[] request;
 	
 	@Override
@@ -69,17 +80,26 @@ public class MySQL implements Protocol<ByteArray>{
 		return state == STATE.CLOSED;
 	}
 	
-	private byte[] wrapPckt(byte[] pckt) {
-		byte[] buff = ByteBuffer.allocate(4).putInt(pckt.length).array();
-		byte[] pcktLength = {buff[3], buff[2], buff[1]};
-		byte[] pcktNumber = new byte[1];
-		if(request != null) pcktNumber[0] = (byte) (request[3] + 1);
-		else pcktNumber[0] = 0x00;
+	/**
+	 * Wraps the response packet with the packet length and number
+	 * @param packet that is wrapped
+	 * @return wrapped packet
+	 */
+	private byte[] wrapPacket(byte[] packet) {
+		byte[] buffer = ByteBuffer.allocate(4).putInt(packet.length).array();
+		byte[] packetLength = {buffer[3], buffer[2], buffer[1]};
+		byte[] packetNumber = new byte[1];
+		if(request != null) packetNumber[0] = (byte) (request[3] + 1);
+		else packetNumber[0] = 0x00;
 		
-		byte[] response = concat(pcktLength, pcktNumber, pckt);
+		byte[] response = HelperUtils.concat(packetLength, packetNumber, packet);
 		return response;
 	}
 	
+	/**
+	 * Builds the greeting packet that the server sends as first packet
+	 * @return greeting packet
+	 */
 	private byte[] greeting() {
 		byte[] protocol = {0x0a};
 		String version = "5.5.31-0+wheezy1";
@@ -94,34 +114,27 @@ public class MySQL implements Protocol<ByteArray>{
 		String payload = "mysql_native_password";
 		byte[] fin = {0x00};
 		
-		byte[] response = concat(protocol, version.getBytes(),versionFin, thread, salt, capabilities, language, status, unused, salt2, payload.getBytes(), fin);
-		
-		return wrapPckt(response);
+		byte[] response = HelperUtils.concat(protocol, version.getBytes(),versionFin, thread, salt, capabilities, language, status, unused, salt2, payload.getBytes(), fin);
+		return wrapPacket(response);
 	}
 	
+	/**
+	 * Builds the ok-response packet
+	 * @return ok-response packet
+	 */
 	private byte[] responseOK() {
 		byte[] affectedRows = {0x00, 0x00, 0x00};
 		byte[] status = {0x02, 0x00};
 		byte[] warnings = {0x00, 0x00};
 		
-		byte[] response = concat(affectedRows, status, warnings);
-		return wrapPckt(response);
+		byte[] response = HelperUtils.concat(affectedRows, status, warnings);
+		return wrapPacket(response);
 	}
-	
-	private byte[] response() {
-		// 4 packets to respond
-		byte[] pckt0 = {0x01, 0x00, 0x00, 0x01, 0x01};
-		byte[] pckt1 = {0x27, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, 
-				0x00, 0x00, 0x11, 0x40, 0x40, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
-				0x65, 0x6e, 0x74, 0x00, 0x0c, 0x21, 0x00, 0x18, 0x00, 0x00, 0x00, (byte) 0xfd, 0x00, 0x00, 0x1f, 0x00, 0x00};
-		byte[] pckt2 = {0x05, 0x00, 0x00, 0x03, (byte) 0xfe, 0x00, 0x00, 0x02, 0x00};
-		byte[] pckt3 = {0x09, 0x00, 0x00, 0x04, 0x08, 0x28, 0x44, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x29};
-		byte[] pckt4 = {0x05, 0x00, 0x00, 0x05, (byte) 0xfe, 0x00, 0x00, 0x02, 0x00};
-			
-		byte[] response = concat(pckt0, pckt1, pckt2, pckt3, pckt4);
-		return response;	//no wrapPckt() needed, because packets already have length and number
-	}
-	
+		
+	/**
+	 * Builds the error-response packet
+	 * @return error-response packet
+	 */
 	private byte[] responseError() {
 		byte[] fill1 = {(byte) 0xff};
 		byte[] code = {0x17, 0x04};
@@ -129,23 +142,8 @@ public class MySQL implements Protocol<ByteArray>{
 		String state = "08S01";
 		String msg = "Unknown command";
 		
-		byte[] response = concat(fill1, code, fill2, state.getBytes(), msg.getBytes());		
-		return wrapPckt(response);
-	}
-	
-	private byte[] concat(byte[]...bytes) {
-		int newSize = 0;	
-		for(byte[] b: bytes) newSize += b.length;		//get total new size
-		byte[] dst = new byte[newSize];				//create new array with new size
-		
-		int currentPos = 0;				
-		int newPos;	
-		for(byte[] b:bytes) {									//for each elem b out of bytes
-			newPos = b.length;									//get b.length and new position
-			System.arraycopy(b, 0, dst, currentPos, newPos);	//copy b in dst from currentPos to newPos
-			currentPos += newPos;								//increase currentPos to newPos + currentPos
-		}
-		return dst;
+		byte[] response = HelperUtils.concat(fill1, code, fill2, state.getBytes(), msg.getBytes());		
+		return wrapPacket(response);
 	}
 
 	@Override

+ 39 - 0
src/de/tudarmstadt/informatik/hostage/protocol/Protocol.java

@@ -2,22 +2,61 @@ package de.tudarmstadt.informatik.hostage.protocol;
 
 import java.util.List;
 
+/**
+ * Interface for protocols that are used by hostage
+ * @param <T> Denotes if the protocol is using Strings or ByteArrays
+ */
 public interface Protocol<T> {
 
+	/**
+	 * Represents who starts the communication once the connection is established
+	 */
 	public static enum TALK_FIRST {
 		SERVER, CLIENT
 	};
 
+	/**
+	 * Returns the port on which the protocol is running
+	 * @return the port used by the protocol (range: 0-65535)
+	 */
 	int getPort();
 
+	/**
+	 * Returns who starts the communication (server or client)
+	 * @return TALK_FIRST.server if the server starts or TALK_FIRST.client if the client starts
+	 */
 	TALK_FIRST whoTalksFirst();
 
+	/**
+	 * Determines the next message that is sent by the server
+	 * @param message last message that was sent by the client
+	 * @return next message that will be sent
+	 */
 	List<T> processMessage(T message);
 
+	/**
+	 * Returns whether the communication is ended and the connection should be closed or not
+	 * @return true if the connection should be closed, else false
+	 */
 	boolean isClosed();
 
+	/**
+	 * Returns if the protocol uses SSL/TLS connection or not
+	 * @return true if SSL/TLS is used, else false
+	 */
 	boolean isSecure();
 
+	/**
+	 * Returns what type the protocol is using, Strings or ByteArrays
+	 * @return the class that the protocol is using
+	 */
 	Class<T> getType();
+	
+	/**
+	 * Returns the name of the protocol
+	 * @return name of the protocol
+	 */
+	@Override 
+	String toString();
 
 }

+ 180 - 111
src/de/tudarmstadt/informatik/hostage/protocol/SMB.java

@@ -7,14 +7,24 @@ import java.util.List;
 import java.util.Random;
 import java.util.TimeZone;
 
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
 
+/**
+ * SMB protocol
+ * @author Wulf Pfeiffer
+ */
 public final class SMB implements Protocol<ByteArray> {
-
+	/**
+	 * Represents the states of the protocol
+	 */
 	private static enum STATE {
 		NONE, CONNECTED, AUTHENTICATED, LISTING, DISCONNECTED, CLOSED
 	}
-
+	
+	/**
+	 * Denotes in which state the protocol is right now
+	 */
 	private STATE state = STATE.NONE;
 
 	@Override
@@ -27,7 +37,7 @@ public final class SMB implements Protocol<ByteArray> {
 		return TALK_FIRST.CLIENT;
 	}
 	
-	private SmbPacket packet = new SmbPacket();
+	private SMBPacket packet = new SMBPacket();
 
 	@Override
 	public List<ByteArray> processMessage(ByteArray message) {
@@ -122,22 +132,10 @@ public final class SMB implements Protocol<ByteArray> {
 		return "SMB";
 	}
 
-	private byte[] concat(byte[]... bytes) {
-		int newSize = 0;
-		for (byte[] b : bytes)
-			newSize += b.length;
-		byte[] dst = new byte[newSize];
-
-		int currentPos = 0;
-		int newPos;
-		for (byte[] b : bytes) {
-			newPos = b.length;
-			System.arraycopy(b, 0, dst, currentPos, newPos);
-			currentPos += newPos;
-		}
-		return dst;
-	}
-
+	/**
+	 * Converts the current system time into a byte[] with windows specific time
+	 * @return current system time in windows format as byte[]
+	 */
 	private byte[] getTimeInBytes() {
 		long time = System.currentTimeMillis();
 		Calendar calend = Calendar.getInstance();
@@ -155,7 +153,12 @@ public final class SMB implements Protocol<ByteArray> {
 
 		return b;
 	}
-
+	
+	/**
+	 * Generates a random byte[] of a specified size
+	 * @param size of the byte[]
+	 * @return random byte[]
+	 */
 	private byte[] randomBytes(int size) {
 		byte[] bytes = new byte[size];
 		Random rdm = new Random();
@@ -163,44 +166,14 @@ public final class SMB implements Protocol<ByteArray> {
 		return bytes;
 	}
 
-	private String byteToStr(byte[] bytes) {
-		return charToString(byteToChar(bytes));
-	}
-	
-	private String charToString(char[] chars) {
-		char[] newChars = new char[chars.length];
-		for (int i = 0, j = 0; i < chars.length && j < newChars.length; i++) {
-			if (isLetter(chars[i])) {
-				newChars[j] = chars[i];
-				j++;
-			}
-		}
-		return new String(newChars);
-	}
-
-	private byte[] charToByte(char[] chars) {
-		byte[] bytes = new byte[chars.length];
-		for (int i = 0; i < chars.length; i++)
-			bytes[i] = (byte) chars[i];
-		return bytes;
-	}
-
-	private char[] byteToChar(byte[] bytes) {
-		char[] chars = new char[bytes.length];
-		for (int i = 0; i < bytes.length; i++)
-			chars[i] = (char) bytes[i];
-		return chars;
-	}
-
-	private boolean isLetter(char c) {
-		return (c >= 32 && c <= 127);
-	}
-
-	private class SmbPacket {
-		private byte[] msg					= null; 
+	/**
+	 * Denotes a SMB packet
+	 */
+	private class SMBPacket {
+		private byte[] message				= null; 
 		private final byte[] serverGUID		= randomBytes(16);
 		private boolean authenticateNext	= false;
-		
+		//components of a SMB packet
 		private byte[] serverComp 		= new byte[4];
 		private byte[] smbCommand		= new byte[1];
 		private byte[] ntStat 			= new byte[4];
@@ -213,39 +186,57 @@ public final class SMB implements Protocol<ByteArray> {
 		private byte[] processID		= new byte[2];
 		private byte[] userID			= new byte[2];
 		private byte[] multiplexID		= new byte[2];
-					
-		public SmbPacket() {
-		}
+				
+		/** Constructor */
+		public SMBPacket() {}
 		
-		public void newMsg(byte[] msg) {
-			this.msg = msg;
-			serverComp 		= new byte[]{msg[4], msg[5], msg[6], msg[7]};
-			smbCommand		= new byte[]{msg[8]};
-			ntStat 			= new byte[]{msg[9], msg[10], msg[11], msg[12]};
-			smbFlags		= new byte[]{(byte) (msg[13] | 0x80)};		// | 0x80 for mark response bit
-			smbFlags2		= new byte[]{msg[14], msg[15]};
-			processIDHigh	= new byte[]{msg[16], msg[17]};
-			signature	 	= new byte[]{msg[18], msg[19], msg[20], msg[21], msg[22], msg[23], msg[24], msg[25]};
-			reserved		= new byte[]{msg[26], msg[27]};
-			treeID			= new byte[]{msg[28], msg[29]};
-			processID		= new byte[]{msg[30], msg[31]};
-			userID			= new byte[]{msg[32], msg[33]};
-			multiplexID		= new byte[]{msg[34], msg[35]};
+		/**
+		 * Breaks a message from the client down into its components
+		 * @param message that is analyzed
+		 */
+		public void newMsg(byte[] message) {
+			this.message 	= message;
+			serverComp 		= new byte[]{message[4], message[5], message[6], message[7]};
+			smbCommand		= new byte[]{message[8]};
+			ntStat 			= new byte[]{message[9], message[10], message[11], message[12]};
+			smbFlags		= new byte[]{(byte) (message[13] | 0x80)};		// | 0x80 for mark response bit
+			smbFlags2		= new byte[]{message[14], message[15]};
+			processIDHigh	= new byte[]{message[16], message[17]};
+			signature	 	= new byte[]{message[18], message[19], message[20], message[21], message[22], message[23], message[24], message[25]};
+			reserved		= new byte[]{message[26], message[27]};
+			treeID			= new byte[]{message[28], message[29]};
+			processID		= new byte[]{message[30], message[31]};
+			userID			= new byte[]{message[32], message[33]};
+			multiplexID		= new byte[]{message[34], message[35]};
 		}
 		
-		private byte[] getNetbios(byte[] response) {
+		/**
+		 * Wraps the Netbios header around a response
+		 * @param response that is wrapped
+		 * @return wrapped response
+		 */
+		private byte[] wrapNetbios(byte[] response) {
 			byte[] netbios = {0x00};
-			byte[] buf = ByteBuffer.allocate(4).putInt(response.length).array();	// allocate(4) because int is 4 bytes long
-			byte[] netbiosLength = {buf[1], buf[2], buf[3]};			// only bytes 1-3 needed, byte 0 is not needed
-			return concat(netbios, netbiosLength);
+			byte[] buffer = ByteBuffer.allocate(4).putInt(response.length).array();	// allocate(4) because int is 4 bytes long
+			byte[] netbiosLength = {buffer[1], buffer[2], buffer[3]};			// only bytes 1-3 needed, byte 0 is not needed
+			return HelperUtils.concat(netbios, netbiosLength, response);
 		}
 		
-		private byte[] getHeader() {
+		/**
+		 * Wraps the header around a response
+		 * @param response that is wrapped
+		 * @return wrapped response
+		 */
+		private byte[] wrapHeader(byte[] response) {
 			byte[] header = new byte[0];
-			return concat(header, serverComp, smbCommand, ntStat, smbFlags, smbFlags2, processIDHigh, signature,
-									reserved, treeID, processID, userID, multiplexID);
+			return HelperUtils.concat(header, serverComp, smbCommand, ntStat, smbFlags, smbFlags2, processIDHigh, signature,
+									reserved, treeID, processID, userID, multiplexID, response);
 		}
 		
+		/**
+		 * Builds the negotiate packet
+		 * @return negotiate packet
+		 */
 		public byte[] getNego() {
 			byte[] wordCount	= {0x11};
 			byte[] dialect		= evaluateDialect();		
@@ -268,15 +259,19 @@ public final class SMB implements Protocol<ByteArray> {
 			byte[] mechType		= {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, (byte) 0x82, 0x37, 0x02, 0x02, 0x1e};
 			byte[] mechType2	= {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, (byte) 0x82, 0x37, 0x02, 0x02, 0x0a};
 			
-			byte[] response = concat(getHeader(), wordCount, dialect, secMode, maxMpxC, maxVcs, maxBufSize, maxRawBuf,
+			byte[] response = HelperUtils.concat(wordCount, dialect, secMode, maxMpxC, maxVcs, maxBufSize, maxRawBuf,
 							sessionKey, capabilities, sysTime, timeZone, keyLength, byteCount, guid, secBlob, oid,
 							protectNeg, negToken, mechType, mechType2);
-			return concat(getNetbios(response), response);
+			return wrapNetbios(wrapHeader(response));
 		}
 		
+		/**
+		 * Evaluates what Dialects are offered by the client and which position the used NT LM 0.12 dialect is at
+		 * @return position of the NT LM 0.12 dialect
+		 */
 		private byte[] evaluateDialect() {
-			byte[] dialectMsg = new byte[msg.length-39];
-			System.arraycopy(msg, 39, dialectMsg, 0, msg.length - 39);
+			byte[] dialectMsg = new byte[message.length-39];
+			System.arraycopy(message, 39, dialectMsg, 0, message.length - 39);
 			short dialectNumber = 0;
 			for(int i = 0, start = 0; i < dialectMsg.length; i++) {
 				if(dialectMsg[i] == 0x00) {
@@ -292,6 +287,10 @@ public final class SMB implements Protocol<ByteArray> {
 			return new byte[]{0x00, 0x00};
 		}
 		
+		/**
+		 * Builds the session setup packet
+		 * @return session setup packet
+		 */
 		public byte[] getSessSetup() {
 			if(authenticateNext) return getSetupAuth();
 			else {
@@ -300,6 +299,10 @@ public final class SMB implements Protocol<ByteArray> {
 			}
 		}
 		
+		/**
+		 * Builds the setup challange packet
+		 * @return setup challange packet
+		 */
 		private byte[] getSetupChal() {
 			byte[] wordCount		= {0x04};
 			byte[] andXCommand		= {(byte) 0xff};
@@ -339,12 +342,16 @@ public final class SMB implements Protocol<ByteArray> {
 			ntStat 					= new byte[]{0x16, 0x00, 0x00, (byte) 0xc0};
 			userID					= new byte[]{0x00, 0x08};
 			
-			byte[] response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
+			byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
 												byteCount, secBlob, negToken, negResult, negToken2, supportedMech, negToken3, 
 												respToken, challenge, respToken2, timeStamp, respToken3, nativOS, nativLanMngr);
-			return concat(getNetbios(response), response);
+			return wrapNetbios(wrapHeader(response));
 		}
 		
+		/**
+		 * Builds the setup authentication packet
+		 * @return setup authentication packet
+		 */
 		private byte[] getSetupAuth() {
 			byte[] wordCount		= {0x04};
 			byte[] andXCommand		= {(byte) 0xff};
@@ -364,11 +371,15 @@ public final class SMB implements Protocol<ByteArray> {
 										0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x00, 0x00};			//Windows 7 Professional 6.1
 
 			
-			byte[] response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
+			byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
 					byteCount, secBlob, nativOS, nativLanMngr);
-			return concat(getNetbios(response), response);
+			return wrapNetbios(wrapHeader(response));
 		}
-
+		
+		/**
+		 * Builds the tree connect packet
+		 * @return tree connect packet
+		 */
 		public byte[] getTreeCon() {
 			String str 			= toString();
 			byte[] wordCount	= {0x00};
@@ -389,19 +400,23 @@ public final class SMB implements Protocol<ByteArray> {
 			
 				treeID						= new byte[]{0x00, 0x08};
 							
-				response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, optionalSupport, maxShareAccess,
+				response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, optionalSupport, maxShareAccess,
 												guestMaxShareAccess, byteCount, service, extraParameters);
 			} else if(str.contains("C$") || str.contains("ADMIN$")) {
 				ntStat = new byte[] {0x22, 0x00, 0x00, (byte) 0xc0};
-				response = concat(getHeader(), wordCount, andXCommand);
+				response = HelperUtils.concat(wordCount, andXCommand);
 			} else {
 				ntStat = new byte[] {(byte) 0xcc, 0x00, 0x00, (byte) 0xc0};
-				response = concat(getHeader(), wordCount, andXCommand);
+				response = HelperUtils.concat(wordCount, andXCommand);
 			}
 			
-			return concat(getNetbios(response), response);
+			return wrapNetbios(wrapHeader(response));
 		}
 		
+		/**
+		 * Builds the nt create packet
+		 * @return nt create packet
+		 */
 		public byte[] getNTCreate() {
 			byte[] wordCount		= {0x22};
 			byte[] andXCommand		= {(byte) 0xff};
@@ -422,12 +437,16 @@ public final class SMB implements Protocol<ByteArray> {
 			byte[] isDirectory		= {0x00};
 			byte[] byteCount		= {0x00, 0x00};
 			
-			byte[] response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, oplockLevel, fid,
+			byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, oplockLevel, fid,
 												createAction, created, lastAccess, lastWrite, change, fileAttributes, allocationSize,
 												endOfFile, fileType, ipcState, isDirectory, byteCount);
-			return concat(getNetbios(response), response);
+			return wrapNetbios(wrapHeader(response));
 		}
 		
+		/**
+		 * Builds the trans packet
+		 * @return trans packet
+		 */
 		public byte[] getTrans() {
 			byte[] transSub	= getTransSub();
 			byte[] response = null;
@@ -454,7 +473,7 @@ public final class SMB implements Protocol<ByteArray> {
 											(byte) 0x88, (byte) 0x8a, (byte) 0xeb, 0x1c, (byte) 0xc9, 0x11, (byte) 0x9f, (byte) 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 
 											0x00, 0x00}; 
 				
-				response = concat(getHeader(), wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
+				response = HelperUtils.concat(wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
 													paramDisplace, dataCount, dataOffset, dataDisplace, setupCount, reserved2, byteCount, padding, dcerpc);
 				
 			} else if(transSub[0] == 0x00 && transSub[1] == 0x00) {
@@ -500,70 +519,120 @@ public final class SMB implements Protocol<ByteArray> {
 				byte[] resumeHandle		= {0x00, 0x00, 0x00, 0x00};
 				byte[] windowsError		= {0x00, 0x00, 0x00, 0x00};
 
-				response = concat(getHeader(), wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
+				response = HelperUtils.concat(wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
 													paramDisplace, dataCount, dataOffset, dataDisplace, setupCount, reserved2, byteCount, padding, dcerpc,
 													serverService, totalEntries, referentID, resumeHandle, windowsError);
 				
 				
 			}
 			
-			return concat(getNetbios(response), response);		
+			return wrapNetbios(wrapHeader(response));		
 		}
 		
+		/**
+		 * Builds the close packet
+		 * @return close packet
+		 */
 		public byte[] getClose() {
 			byte[] wordCount	= {0x00};
 			byte[] byteCount	= {0x00, 0x00};
 			
 			smbCommand			= new byte[]{0x04};
 			
-			byte[] response = concat(getHeader(), wordCount, byteCount);
+			byte[] response = HelperUtils.concat(wordCount, byteCount);
 			
-			return concat(getNetbios(response), response);
+			return wrapNetbios(wrapHeader(response));
 		}
 		
+		/**
+		 * Builds the tree disconnect packet
+		 * @return tree disconnect packet
+		 */
 		public byte[] getTreeDisc() {
 			byte[] wordCount	= {0x00};
 			byte[] byteCount	= {0x00, 0x00};
 			
 			smbCommand[0] = 0x71;
 			
-			byte[] response = concat(getHeader(), wordCount, byteCount);
+			byte[] response = HelperUtils.concat(wordCount, byteCount);
 			
-			return concat(getNetbios(response), response);
+			return wrapNetbios(wrapHeader(response));
 		}
 		
+		/**
+		 * Builds the echo packet
+		 * @return echo packet
+		 */
 		public byte[] getEcho() {
 			byte[] wordCount	= {0x01};
 			byte[] echoSeq		= {0x01, 0x00};
 			byte[] byteCount	= {0x10, 0x00};
 			byte[] echoData		= {(byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0,
 									(byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0}; 
-			byte[] response = concat(getHeader(),  wordCount, echoSeq, byteCount, echoData);
-			return concat(getNetbios(response), response);
+			byte[] response = HelperUtils.concat(wordCount, echoSeq, byteCount, echoData);
+			return wrapNetbios(wrapHeader(response));
 
 		}
 		
+		/**
+		 * Builds the trans2 packet
+		 * @return trans2 packet
+		 */
 		public byte[] getTrans2() {
 			byte[] response = null;		
 			byte[] wordCount	= {0x00};
 			byte[] andXCommand	= {0x00, 0x00};
 			ntStat = new byte[] {0x22, 0x00, 0x00, (byte) 0xc0};
-			response = concat(getHeader(), wordCount, andXCommand);
-			return concat(getNetbios(response), response);
+			response = HelperUtils.concat(wordCount, andXCommand);
+			return wrapNetbios(wrapHeader(response));
 		}
-				
+		
+		/**
+		 * Builds the trans sub packet
+		 * @return trans sub packet
+		 */		
 		private byte[] getTransSub() {
 			byte[] transSub = new byte[2];
-			if(smbCommand[0] == 0x32) transSub = new byte[]{msg[66], msg[65]};
-			else if(smbCommand[0] == 0x25) transSub = new byte[]{0x00, msg[90]};
+			if(smbCommand[0] == 0x32) transSub = new byte[]{message[66], message[65]};
+			else if(smbCommand[0] == 0x25) transSub = new byte[]{0x00, message[90]};
 			else transSub = new byte[]{0x00, 0x00};
 			return transSub;
 		}
-		
+
+		@Override
 		public String toString() {
-			return byteToStr(msg);
+			return byteToStr(message);
+		}
+		
+		/**
+		 * Converts a byte[] to a String, but only characters in ASCII between 32 and 127
+		 * @param bytes that are converted
+		 * @return converted String
+		 */
+		private String byteToStr(byte[] bytes) {
+			char[] chars = new char[bytes.length];
+			for (int i = 0, j = 0; i < bytes.length && j < chars.length; i++) {
+				if (isLetter((char) bytes[i])) {
+					chars[j] = (char) bytes[i];
+					j++;
+				}
+			}
+			return new String(chars);
+		}
+
+		/**
+		 * Determines if a character is in ASCII between 32 and 127
+		 * @param character that is checked 
+		 * @return true if the character is between 32 and 127, else false
+		 */
+		private boolean isLetter(char character) {
+			return (character >= 32 && character <= 127);
 		}
 		
+		/**
+		 * Returns the command number from the current message
+		 * @return command number
+		 */
 		public byte getSmbCommand() {
 			return smbCommand[0];
 		}

+ 125 - 83
src/de/tudarmstadt/informatik/hostage/protocol/SSH.java

@@ -18,10 +18,17 @@ import javax.crypto.interfaces.DHPublicKey;
 import javax.crypto.spec.DHParameterSpec;
 import javax.crypto.spec.DHPublicKeySpec;
 
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
 
+/**
+ * SSH protocol
+ * @author Wulf Pfeiffer
+ */
 public final class SSH implements Protocol<ByteArray> {
-	
+	/**
+	 * Represents the states of the protocol
+	 */
 	private enum STATE {
 		NONE,
 		SRVR_VERSION,
@@ -31,12 +38,16 @@ public final class SSH implements Protocol<ByteArray> {
 		CLOSED
 	}
 	
+	/**
+	 * Denotes in which state the protocol is right now
+	 */
 	private STATE connectionState = STATE.NONE;
 	
 	private String serverVersion = "SSH-2.0-";
 	private String serverType = "OpenSSH_6.0p1 Debian-4";
 		
-	private final byte[] pDH = {
+	//Diffie-Hellman-Group-1 p and g
+	private final byte[] p = {
             (byte)0x00,
             (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
             (byte)0xC9,(byte)0x0F,(byte)0xDA,(byte)0xA2,(byte)0x21,(byte)0x68,(byte)0xC2,(byte)0x34,
@@ -55,17 +66,18 @@ public final class SSH implements Protocol<ByteArray> {
             (byte)0x49,(byte)0x28,(byte)0x66,(byte)0x51,(byte)0xEC,(byte)0xE6,(byte)0x53,(byte)0x81,
             (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF
       };
-	private final byte[] gDH = {0x02};
+	private final byte[] g = {0x02};
+	
     private byte[] V_S = serverType.getBytes();
     private byte[] V_C;
     private byte[] I_S;
     private byte[] I_C;
-    private byte[] eDH;
-    private byte[] fDH;
-    private byte[] kDH;
-    private byte[] hDH;
+    private byte[] e;
+    private byte[] f;
+    private byte[] k;
+    private byte[] h;
     private byte[] K_S;
-    private byte[] sigH;
+    private byte[] sig;
 
     private KeyPair dsa;
 			
@@ -156,25 +168,32 @@ public final class SSH implements Protocol<ByteArray> {
 		return "SSH";
 	}
 	
-	
-	private byte[] wrapPckt(byte[] payload) {
-		int pcktLen = 5 + payload.length; 	//4 byte packet length, 1 byte padding length, payload length
-		int paddLenCBS = cipherBlockSize - (pcktLen % cipherBlockSize);
-		int paddLen8 = 8 - (pcktLen % 8);
-		int paddingLen = paddLenCBS > paddLen8 ? paddLenCBS : paddLen8;
-		if(paddingLen < 4) paddingLen += cipherBlockSize;
-		pcktLen = pcktLen + paddingLen - 4;					//add padding string length to packet length
+	/**
+	 * Wraps the packets with packet length and padding
+	 * @param packet content that is wrapped
+	 * @return wrapped packet
+	 */
+	private byte[] wrapPacket(byte[] packet) {
+		int packetLength = 5 + packet.length; 	//4 byte packet length, 1 byte padding length, payload length
+		int paddingLengthCBS = cipherBlockSize - (packetLength % cipherBlockSize);
+		int paddingLength8 = 8 - (packetLength % 8);
+		int paddingLength = paddingLengthCBS > paddingLength8 ? paddingLengthCBS : paddingLength8;
+		if(paddingLength < 4) paddingLength += cipherBlockSize;
+		packetLength = packetLength + paddingLength - 4;					//add padding string length to packet length
 		
-		byte[] pcktLength = ByteBuffer.allocate(4).putInt(pcktLen).array();
-		byte[] paddingLength = {(byte) paddingLen};
-		byte[] paddingString = new byte[paddingLen];
-		for(int i = 0; i < paddingLen; i++) {
+		byte[] packetLen = ByteBuffer.allocate(4).putInt(packetLength).array();
+		byte[] paddingLen = {(byte) paddingLength};
+		byte[] paddingString = new byte[paddingLength];
+		for(int i = 0; i < paddingLength; i++) {
 			paddingString[i] = 0x00;
 		}
-		
-		return concat(pcktLength, paddingLength, payload, paddingString);
+		return HelperUtils.concat(packetLen, paddingLen, packet, paddingString);
 	}
 	
+	/**
+	 * Builds the Kex Init packet that contains all the allowed algorithms by the server
+	 * @return Kex Init packet
+	 */
 	private byte[] kexInit() {
 		byte[] msgCode = {0x14};
 		I_S = randomBytes(16);
@@ -191,13 +210,17 @@ public final class SSH implements Protocol<ByteArray> {
 		byte[] kexFirsPckt = {0x00};
 		byte[] reserved = {0x00, 0x00, 0x00, 0x00};	
 		
-		byte[] response = concat(msgCode, I_S, kexLength, kex_alg.getBytes(), serverLength, server_alg.getBytes(),
+		byte[] response = HelperUtils.concat(msgCode, I_S, kexLength, kex_alg.getBytes(), serverLength, server_alg.getBytes(),
 							encrypt_c_Length, encrypt_alg_c.getBytes(), encrypt_s_Length, encrypt_alg_s.getBytes(), mac_c_Length, mac_alg_c.getBytes(),
 							mac_s_Length, mac_alg_s.getBytes(), comp_c_Length, comp_alg_c.getBytes(), comp_s_Length, comp_alg_s.getBytes(),
 							language_c_s, language_s_c, kexFirsPckt, reserved);
-		return wrapPckt(response);
+		return wrapPacket(response);
 	}
 	
+	/**
+	 * Builds the Diffie-Hellman Kex Reply, containing the host key,f and the signature
+	 * @return Diffie-Hellman Kex Reply packet
+	 */
 	private byte[] dhKexReply() {
 		generateDHKeys();
 		generateHostKey();
@@ -205,46 +228,52 @@ public final class SSH implements Protocol<ByteArray> {
 		generateSignature();
 		byte[] msgCode = {0x1f};
 		byte[] hostKeyLength = ByteBuffer.allocate(4).putInt(K_S.length).array();
-				byte[] fDHLength = ByteBuffer.allocate(4).putInt(fDH.length).array();
-		byte[] signatureLength = ByteBuffer.allocate(4).putInt(sigH.length).array();
+				byte[] fDHLength = ByteBuffer.allocate(4).putInt(f.length).array();
+		byte[] signatureLength = ByteBuffer.allocate(4).putInt(sig.length).array();
 		byte[] server_algLength = ByteBuffer.allocate(4).putInt(server_alg.getBytes().length).array();
-		byte[] payloadLength = ByteBuffer.allocate(4).putInt(server_algLength.length + signatureLength.length + sigH.length + server_alg.getBytes().length).array();
-		byte[] response = concat(msgCode, hostKeyLength,  K_S,
-									fDHLength, fDH, payloadLength, server_algLength, server_alg.getBytes(), signatureLength, sigH);
-		return wrapPckt(response);
+		byte[] payloadLength = ByteBuffer.allocate(4).putInt(server_algLength.length + signatureLength.length + sig.length + server_alg.getBytes().length).array();
+		byte[] response = HelperUtils.concat(msgCode, hostKeyLength,  K_S,
+									fDHLength, f, payloadLength, server_algLength, server_alg.getBytes(), signatureLength, sig);
+		return wrapPacket(response);
 	}
 	
-	private byte[] newKeys() {
-		byte[] msgCode = {0x15};
-		return wrapPckt(msgCode);
-	}
+//	private byte[] newKeys() {
+//		byte[] msgCode = {0x15};
+//		return wrapPckt(msgCode);
+//	}
 	
+	/**
+	 * Generates the required Diffie-Hellman keys with p and g from Oakley Group 1
+	 */
 	private void generateDHKeys() {	
 		try {
 			KeyPairGenerator myKpairGen = KeyPairGenerator.getInstance("DH");
 			KeyAgreement myKeyAgree = KeyAgreement.getInstance("DH");
-			BigInteger p = new BigInteger(pDH);
-			BigInteger g = new BigInteger(gDH);
-			BigInteger e = new BigInteger(eDH);
+			BigInteger p = new BigInteger(this.p);
+			BigInteger g = new BigInteger(this.g);
+			BigInteger e = new BigInteger(this.e);
 			
             DHParameterSpec dhParamSpec = new DHParameterSpec(p, g);
             myKpairGen.initialize(dhParamSpec);
             KeyPair myKpair = myKpairGen.generateKeyPair();
             myKeyAgree.init(myKpair.getPrivate());
             BigInteger f = ((DHPublicKey) (myKpair.getPublic())).getY();
-            fDH = f.toByteArray();
+            this.f = f.toByteArray();
             
             KeyFactory myKeyFac = KeyFactory.getInstance("DH");
             DHPublicKeySpec keySpec = new DHPublicKeySpec(e, p, g);
             PublicKey yourPubKey = myKeyFac.generatePublic(keySpec);
             myKeyAgree.doPhase(yourPubKey, true);
             byte[] mySharedSecret = myKeyAgree.generateSecret();
-            kDH = mySharedSecret;
+            k = mySharedSecret;
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
 	}
 	
+	/**
+	 * Generates the Host Key based on the DSA algorithm
+	 */
 	private void generateHostKey() {
         try {
             KeyPairGenerator generator = KeyPairGenerator.getInstance("DSA");
@@ -254,27 +283,30 @@ public final class SSH implements Protocol<ByteArray> {
             byte[] stringLength = ByteBuffer.allocate(4).putInt(string.length).array();
             
             byte[] p = ((DSAPublicKey) dsa.getPublic()).getParams().getP().toByteArray();
-            if(p[0] != 0x00) p = concat(new byte[]{0x00}, p);
+            if(p[0] != 0x00) p = HelperUtils.concat(new byte[]{0x00}, p);
             byte[] pLength = ByteBuffer.allocate(4).putInt(p.length).array();
             
             byte[] q = ((DSAPublicKey) dsa.getPublic()).getParams().getQ().toByteArray();
-            if(q[0] != 0x00) q = concat(new byte[]{0x00}, q);
+            if(q[0] != 0x00) q = HelperUtils.concat(new byte[]{0x00}, q);
             byte[] qLength = ByteBuffer.allocate(4).putInt(q.length).array();
             
             byte[] g = ((DSAPublicKey) dsa.getPublic()).getParams().getG().toByteArray();
-            if(g[0] != 0x00) g = concat(new byte[]{0x00}, g);
+            if(g[0] != 0x00) g = HelperUtils.concat(new byte[]{0x00}, g);
             byte[] gLength = ByteBuffer.allocate(4).putInt(g.length).array();
             
             byte[] y = ((DSAPublicKey) dsa.getPublic()).getY().toByteArray();
-            if(y[0] != 0x00) y = concat(new byte[]{0x00}, y);
+            if(y[0] != 0x00) y = HelperUtils.concat(new byte[]{0x00}, y);
             byte[] yLength = ByteBuffer.allocate(4).putInt(y.length).array();
             
-            K_S = concat(stringLength, string, pLength, p, qLength, q, gLength, g, yLength, y);       		
+            K_S = HelperUtils.concat(stringLength, string, pLength, p, qLength, q, gLength, g, yLength, y);       		
         } catch (Exception e) {
         	e.printStackTrace();
         }
 	}
 	
+	/**
+	 * Generates the SHA-1 Hash from several values
+	 */
 	private void generateSha1Hash() {
 		try {
 			MessageDigest sha = MessageDigest.getInstance("SHA-1");
@@ -283,27 +315,34 @@ public final class SSH implements Protocol<ByteArray> {
 			sha.update(I_C);
 			sha.update(I_S);
 			sha.update(K_S);
-			sha.update(eDH);
-			sha.update(fDH);
-			sha.update(kDH);
-			hDH = sha.digest();
+			sha.update(e);
+			sha.update(f);
+			sha.update(k);
+			h = sha.digest();
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
 	}
 	
+	/**
+	 * Generates the signature of the hash using DSA algorithm with SHA-1
+	 */
 	private void generateSignature() {		
 		try {
 			Signature sig = Signature.getInstance("SHA1withDSA");
             sig.initVerify(dsa.getPublic());
             sig.initSign(dsa.getPrivate());
-            sig.update(hDH);
-            sigH = doStuff(sig.sign());
+            sig.update(h);
+            this.sig = extractSignature(sig.sign());
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
 	}
 	
+	/**
+	 * Extracts the type of the client
+	 * @param request containing the clients type
+	 */
 	private void extractType(byte[] request) {
 		V_C = new byte[request.length - 10];
 		for(int i = 0; i < V_C.length; i++) {
@@ -312,6 +351,10 @@ public final class SSH implements Protocol<ByteArray> {
 		}
 	}
 	
+	/**
+	 * Extracts the cookie from the Kex Init client request 
+	 * @param request containing the clients cookie
+	 */
 	private void extractCookie(byte[] request) {
 		I_C = new byte[16];
 		for(int i = 0; i < I_C.length; i++) {
@@ -319,13 +362,22 @@ public final class SSH implements Protocol<ByteArray> {
 		}
 	}
 	
+	/**
+	 * Extracts the public key from the DH Kex Request
+	 * @param request containing the clients public key
+	 */
 	private void extractPubKey(byte[] request) {
-		eDH = new byte[byteToInt(new byte[] {request[6], request[7], request[8], request[9]})];
-		for(int i = 0; i < eDH.length; i++) {
-			eDH[i] = request[i+10];
+		e = new byte[byteToInt(new byte[] {request[6], request[7], request[8], request[9]})];
+		for(int i = 0; i < e.length; i++) {
+			e[i] = request[i+10];
 		}
 	}
 	
+	/**
+	 * Converts a byte[] to int
+	 * @param bytes that are converted
+	 * @return converted byte[] as int
+	 */
 	private static int byteToInt(byte[] bytes) {
 		  int ret = 0;
 		  for (int i=0; i < bytes.length; i++) {
@@ -335,45 +387,36 @@ public final class SSH implements Protocol<ByteArray> {
 		  return ret;
 	}
 	
+	/**
+	 * Generates a random byte[] of a specified size
+	 * @param size of the byte[]
+	 * @return random byte[]
+	 */
 	private byte[] randomBytes(int size) {
 		byte[] bytes = new byte[size];
 		Random rdm = new Random();
 		rdm.nextBytes(bytes);
 		return bytes;		
 	}
-	
-	private byte[] concat(byte[]...bytes) {
-		int newSize = 0;	
-		for(byte[] b: bytes) newSize += b.length;		//get total new size
-		byte[] dst = new byte[newSize];				//create new array with new size
-		
-		int currentPos = 0;				
-		int newPos;	
-		for(byte[] b:bytes) {									//for each elem b out of bytes
-			newPos = b.length;									//get b.length and new position
-			System.arraycopy(b, 0, dst, currentPos, newPos);	//copy b in dst from currentPos to newPos
-			currentPos += newPos;								//increase currentPos to newPos + currentPos
-		}
-		return dst;
-	}
 
-	private byte[] doStuff(byte[] sig) {
-        // sig is in ASN.1
-        // SEQUENCE::={ r INTEGER, s INTEGER }
-        int len = 0;
+	/**
+	 * Extracts r and s from a DSA-signature
+	 * @param signature 
+	 * @return r and s as byte[]
+	 */
+	private byte[] extractSignature(byte[] signature) {
+        //{ r INTEGER, s INTEGER }
+        int length = 0;
         int index = 3;
-        len = sig[index++] & 0xff;
-        byte[] r = new byte[len];
-        System.arraycopy(sig, index, r, 0, r.length);
-        index = index + len + 1;
-        len = sig[index++] & 0xff;
-        byte[] s = new byte[len];
-        System.arraycopy(sig, index, s, 0, s.length);
-
+        length = signature[index++] & 0xff;
+        byte[] r = new byte[length];
+        System.arraycopy(signature, index, r, 0, r.length);
+        index = index + length + 1;
+        length = signature[index++] & 0xff;
+        byte[] s = new byte[length];
+        System.arraycopy(signature, index, s, 0, s.length);
         byte[] result = new byte[40];
-
         // result must be 40 bytes, but length of r and s may not be 20 bytes
-
         System.arraycopy(r,
                          (r.length > 20) ? 1 : 0,
                          result,
@@ -384,7 +427,6 @@ public final class SSH implements Protocol<ByteArray> {
                          result,
                          (s.length > 20) ? 20 : 40 - s.length,
                          (s.length > 20) ? 20 : s.length);
-
         return result;
     }
 

+ 54 - 50
src/de/tudarmstadt/informatik/hostage/protocol/TELNET.java

@@ -3,20 +3,34 @@ package de.tudarmstadt.informatik.hostage.protocol;
 import java.util.ArrayList;
 import java.util.List;
 
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
 
+/**
+ * TELNET protocol
+ * @author Wulf Pfeiffer
+ */
 public final class TELNET implements Protocol<ByteArray> {
-
+	/**
+	 * Represents the states of the protocol
+	 */
 	private static enum STATE {
 		NONE, OPEN, CLOSED, LOGIN, AUTHENTICATE, LOGGED_IN
 	};
-
+	
+	/**
+	 * Denotes in which state the protocol is right now
+	 */
 	private STATE state = STATE.NONE;
 
-	private byte[] usr;
-	private byte[] cmd;
-	private String machine = "raspberrypi";
-	private byte[] session = null;
+	/** user entered by the client */
+	private byte[] user;
+	/** last command sent by the client */
+	private byte[] command;
+	/** name of the server */
+	private String server = "raspberrypi";
+	/** command line prefix */
+	private byte[] sessionToken = null;
 
 	@Override
 	public int getPort() {
@@ -35,14 +49,14 @@ public final class TELNET implements Protocol<ByteArray> {
 		List<ByteArray> response = new ArrayList<ByteArray>();
 		switch (state) {
 		case NONE:
-			response.add(new ByteArray(cmdRequests));
+			response.add(new ByteArray(optionRequest));
 			state = STATE.OPEN;
 			break;
 		case OPEN:
 			if(request != null) {
-				response.add(new ByteArray(getCmdResponses(request)));
+				response.add(new ByteArray(getOptionResponse(request)));
 				response.add(new ByteArray("Debian GNU/Linux 7.0\r\n"));
-				response.add(new ByteArray(machine + "login: "));
+				response.add(new ByteArray(server + "login: "));
 				state = STATE.LOGIN;
 			}
 			break;
@@ -52,26 +66,26 @@ public final class TELNET implements Protocol<ByteArray> {
 				response.add(new ByteArray("\r\n"));
 				response.add(new ByteArray("Password: "));
 				state = STATE.AUTHENTICATE;
-				session = concat(sessionPrefix, "@".getBytes(), machine.getBytes(), sessionMiddle, "@".getBytes(), machine.getBytes(), sessionSuffix);
+				sessionToken = HelperUtils.concat(sessionPrefix, "@".getBytes(), server.getBytes(), sessionMiddle, "@".getBytes(), server.getBytes(), sessionSuffix);
 				break;
 			} else if (request[0] == 0x7f) {
-				byte[] tmp = new byte[usr.length - 1];
-				System.arraycopy(usr, 0, tmp, 0, usr.length - 1);
-				usr = tmp;
+				byte[] tmp = new byte[user.length - 1];
+				System.arraycopy(user, 0, tmp, 0, user.length - 1);
+				user = tmp;
 				response.add(new ByteArray("\b \b"));
 			} else if (request[0] != (byte) 0xff){
-				if(usr == null)
-					usr = request;
+				if(user == null)
+					user = request;
 				else
-					usr = concat(usr, request);
+					user = HelperUtils.concat(user, request);
 				response.add(message);
 			}
 			break;
 		case AUTHENTICATE:
 			if(request == null) break;
 			else if(request[0] == 0x0d) {
-				response.add(new ByteArray("Last Login: \r\nLinux" + machine + " 3.6.11+\r\n"));
-				response.add(new ByteArray(session));
+				response.add(new ByteArray("Last Login: \r\nLinux" + server + " 3.6.11+\r\n"));
+				response.add(new ByteArray(sessionToken));
 				state = STATE.LOGGED_IN;
 			} else if (request[0] == 0x7f) {
 				response.add(new ByteArray("\b \b"));
@@ -80,29 +94,29 @@ public final class TELNET implements Protocol<ByteArray> {
 		case LOGGED_IN:
 			if(request == null) break;
 			else if(request[0] == 0x0d) {
-				if(cmd == null) {
+				if(command == null) {
 					response.add(new ByteArray("\r\n"));
-					response.add(new ByteArray(session));
-				} else if (new String(cmd).contains("exit")) {
+					response.add(new ByteArray(sessionToken));
+				} else if (new String(command).contains("exit")) {
 					response.add(new ByteArray("\r\nlogout\r\n"));
 					state = STATE.CLOSED;
 				} else {
-					String bash = "\r\n-bash: " + new String(cmd)+ ": command not found";
+					String bash = "\r\n-bash: " + new String(command)+ ": command not found";
 					response.add(new ByteArray(bash));
 					response.add(new ByteArray("\r\n"));
-					response.add(new ByteArray(session));
-					cmd = null;
+					response.add(new ByteArray(sessionToken));
+					command = null;
 				}
 			} else if (request[0] == 0x7f) {
-				byte[] tmp = new byte[cmd.length - 1];
-				System.arraycopy(cmd, 0, tmp, 0, cmd.length - 1);
-				cmd = tmp;
+				byte[] tmp = new byte[command.length - 1];
+				System.arraycopy(command, 0, tmp, 0, command.length - 1);
+				command = tmp;
 				response.add(new ByteArray("\b \b"));
 			} else if (request[0] != (byte) 0xff){
-				if(cmd == null)
-					cmd = request;
+				if(command == null)
+					command = request;
 				else
-					cmd = concat(cmd, request);
+					command = HelperUtils.concat(command, request);
 				response.add(message);
 			}
 			break;
@@ -133,7 +147,12 @@ public final class TELNET implements Protocol<ByteArray> {
 		return ByteArray.class;
 	}
 
-	private byte[] getCmdResponses(byte[] request) {
+	/**
+	 * Determines which options that are requested by the client will be done and which not
+	 * @param request requested options
+	 * @return accepted and unaccepted options
+	 */
+	private byte[] getOptionResponse(byte[] request) {
 		List<byte[]> respList = new ArrayList<byte[]>();
 		byte[] cmdResp;
 		for(int i = 0; i < request.length - 2; i += 3) {
@@ -147,14 +166,15 @@ public final class TELNET implements Protocol<ByteArray> {
 		}
 		byte[] response = new byte[0];
 		for(byte[] resp : respList) {
-			response = concat(response, resp);
+			response = HelperUtils.concat(response, resp);
 		}
 		return response;
 	}
 
-	private final byte[] cmdRequests = {(byte) 0xff, (byte) 0xfb, 0x03,
+	/** options requested by the server */
+	private final byte[] optionRequest = {(byte) 0xff, (byte) 0xfb, 0x03,
 										(byte) 0xff, (byte) 0xfb, 0x01};
-
+	//session token prefix, mid and suffix
 	private final byte[] sessionPrefix = {0x1b, 0x5d, 0x30, 0x3b};
 	private final byte[] sessionMiddle = {0x40, 0x72, 0x61, 0x73, 
 			0x70, 0x62, 0x65, 0x72, 0x72, 0x79, 0x70, 0x69, 0x3a, 0x20, 0x7e, 0x07, 0x1b, 0x5b, 0x30, 0x31, 
@@ -162,20 +182,4 @@ public final class TELNET implements Protocol<ByteArray> {
 	private final byte[] sessionSuffix = {0x1b, 0x5b, 0x30, 0x30, 0x6d, 0x20, 0x1b, 0x5b, 0x30, 0x31, 
 			0x3b, 0x33, 0x34, 0x6d, 0x7e, 0x20, 0x24, 0x1b, 0x5b, 0x30, 0x30, 0x6d, 0x20};
 
-	private byte[] concat(byte[]... bytes) {
-		int newSize = 0;
-		for (byte[] b : bytes)
-			newSize += b.length;
-		byte[] dst = new byte[newSize];
-
-		int currentPos = 0;
-		int newPos;
-		for (byte[] b : bytes) {
-			newPos = b.length;
-			System.arraycopy(b, 0, dst, currentPos, newPos);
-			currentPos += newPos;
-		}
-		return dst;
-	}
-
 }