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 { /** * 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[] lastMessage; /** 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() { return 23; } @Override public TALK_FIRST whoTalksFirst() { return TALK_FIRST.SERVER; } @Override public List processMessage(ByteArray message) { if(message != null) lastMessage = message.get(); byte[] request = null; if(message != null) request = message.get(); List response = new ArrayList(); switch (state) { case NONE: response.add(new ByteArray(optionRequest)); state = STATE.OPEN; break; case OPEN: if(request != null) { response.add(new ByteArray(getOptionResponse(request))); response.add(new ByteArray("Debian GNU/Linux 7.0\r\n")); response.add(new ByteArray(server + " login: ")); state = STATE.LOGIN; } break; case LOGIN: if(request == null) break; else if(request[0] == 0x0d) { response.add(new ByteArray("\r\n")); response.add(new ByteArray("Password: ")); state = STATE.AUTHENTICATE; sessionToken = HelperUtils.concat(sessionPrefix, user, "@".getBytes(), server.getBytes(), sessionMiddle, user, "@".getBytes(), server.getBytes(), sessionSuffix); break; } else if (request[0] == 0x7f) { 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(user == null) user = request; else user = HelperUtils.concat(user, request); response.add(message); } break; case AUTHENTICATE: if(request == null) break; else if(request[0] == 0x0d) { response.add(new ByteArray("\r\nLast 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")); } break; case LOGGED_IN: if(request == null) break; else if(request[0] == 0x0d) { if(command == null) { response.add(new ByteArray("\r\n")); 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(command)+ ": command not found"; response.add(new ByteArray(bash)); response.add(new ByteArray("\r\n")); response.add(new ByteArray(sessionToken)); command = null; } } else if (request[0] == 0x7f) { 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(command == null) command = request; else command = HelperUtils.concat(command, request); response.add(message); } break; default: response.add(new ByteArray("\r\nlogout\r\n")); state = STATE.CLOSED; break; } return response; } @Override public boolean isClosed() { return (state == STATE.CLOSED); } @Override public boolean isSecure() { return false; } @Override public String toString() { return "TELNET"; } @Override public Class getType() { return ByteArray.class; } /** * 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 respList = new ArrayList(); byte[] cmdResp; for(int i = 0; i < request.length - 2; i += 3) { if(request[i] == (byte) 0xff && request[i+2] != 0x03 && request[i+2] != 0x01) { cmdResp = new byte[3]; cmdResp[0] = request[i]; cmdResp[1] = request[i + 1] == (byte) 0xfd ? (byte) 0xfc : (byte) 0xfe; cmdResp[2] = request[i+2]; respList.add(cmdResp); } } byte[] response = new byte[0]; for(byte[] resp : respList) { response = HelperUtils.concat(response, resp); } return response; } /** options requested by the server */ private final byte[] optionRequest = {(byte) 0xff, (byte) 0xfb, 0x03, //will suppress go ahead (byte) 0xff, (byte) 0xfb, 0x01}; //will echo //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, 0x3b, 0x33, 0x32, 0x6d}; 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}; }