TELNET.java 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package de.tudarmstadt.informatik.hostage.protocol;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
  5. import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
  6. /**
  7. * TELNET protocol
  8. * @author Wulf Pfeiffer
  9. */
  10. public class TELNET implements Protocol<ByteArray> {
  11. /**
  12. * Represents the states of the protocol
  13. */
  14. private static enum STATE {
  15. NONE, OPEN, CLOSED, LOGIN, AUTHENTICATE, LOGGED_IN
  16. };
  17. /**
  18. * Denotes in which state the protocol is right now
  19. */
  20. private STATE state = STATE.NONE;
  21. private byte[] lastMessage;
  22. /** user entered by the client */
  23. private byte[] user;
  24. /** last command sent by the client */
  25. private byte[] command;
  26. /** name of the server */
  27. private String server = "raspberrypi"; //TODO
  28. /** command line prefix */
  29. private byte[] sessionToken = null;
  30. public int getPort() {
  31. return 23;
  32. }
  33. public TALK_FIRST whoTalksFirst() {
  34. return TALK_FIRST.SERVER;
  35. }
  36. public List<ByteArray> processMessage(ByteArray message) {
  37. byte[] request = null;
  38. if(message != null) {
  39. lastMessage = message.get();
  40. request = message.get();
  41. System.out.println(HelperUtils.byteToStr(lastMessage));
  42. }
  43. List<ByteArray> response = new ArrayList<ByteArray>();
  44. switch (state) {
  45. case NONE:
  46. response.add(new ByteArray(optionRequest));
  47. state = STATE.OPEN;
  48. break;
  49. case OPEN:
  50. if(request != null) {
  51. response.add(new ByteArray(getOptionResponse(request)));
  52. response.add(new ByteArray("Debian GNU/Linux 7.0\r\n")); //TODO
  53. response.add(new ByteArray(server + " login: "));
  54. state = STATE.LOGIN;
  55. }
  56. break;
  57. case LOGIN:
  58. if(request == null) break;
  59. else if(checkForByte(request, (byte) 0x0d)) {
  60. if(request.length > 2) {
  61. byte[] buffer = new byte[request.length - 2];
  62. System.arraycopy(request, 0, buffer, 0, request.length - 2);
  63. user = HelperUtils.concat(user, buffer);
  64. response.add(new ByteArray(buffer));
  65. }
  66. response.add(new ByteArray("\r\n"));
  67. response.add(new ByteArray("Password: "));
  68. state = STATE.AUTHENTICATE;
  69. sessionToken = HelperUtils.concat(sessionPrefix, user, "@".getBytes(), server.getBytes(), sessionMiddle, user, "@".getBytes(), server.getBytes(), sessionSuffix);
  70. break;
  71. } else if (checkForByte(request, (byte) 0x7f) && user != null && user.length != 0) {
  72. byte[] tmp = new byte[user.length - 1];
  73. System.arraycopy(user, 0, tmp, 0, user.length - 1);
  74. user = tmp;
  75. response.add(new ByteArray("\b \b"));
  76. break;
  77. } else if (!checkForByte(request, (byte) 0xff)){
  78. if(user == null)
  79. user = request;
  80. else
  81. user = HelperUtils.concat(user, request);
  82. response.add(message);
  83. }
  84. break;
  85. case AUTHENTICATE:
  86. if(request == null) break;
  87. else if(checkForByte(request, (byte) 0x0d)) {
  88. response.add(new ByteArray("\r\nLinux" + server + " 3.6.11+\r\n")); //TODO
  89. response.add(new ByteArray(sessionToken));
  90. state = STATE.LOGGED_IN;
  91. } else if (checkForByte(request, (byte) 0x7f)) {
  92. response.add(new ByteArray("\b \b"));
  93. }
  94. break;
  95. case LOGGED_IN:
  96. if(request == null) break;
  97. else if(checkForByte(request, (byte) 0x0d)) {
  98. if(request.length > 2) {
  99. byte[] buffer = new byte[request.length - 2];
  100. System.arraycopy(request, 0, buffer, 0, request.length - 2);
  101. command = HelperUtils.concat(command, buffer);
  102. response.add(new ByteArray(buffer));
  103. }
  104. if(command == null) {
  105. response.add(new ByteArray("\r\n"));
  106. response.add(new ByteArray(sessionToken));
  107. } else if (new String(command).contains("exit")) {
  108. response.add(new ByteArray("\r\nlogout\r\n"));
  109. state = STATE.CLOSED;
  110. } else {
  111. String bash = "\r\n-bash: " + new String(command)+ ": command not found";
  112. response.add(new ByteArray(bash));
  113. response.add(new ByteArray("\r\n"));
  114. response.add(new ByteArray(sessionToken));
  115. command = null;
  116. }
  117. } else if (checkForByte(request, (byte) 0x7f) && command != null && command.length != 0) {
  118. byte[] tmp = new byte[command.length - 1];
  119. System.arraycopy(command, 0, tmp, 0, command.length - 1);
  120. command = tmp;
  121. response.add(new ByteArray("\b \b"));
  122. break;
  123. } else if (!checkForByte(request, (byte) 0xff)){
  124. if(command == null)
  125. command = request;
  126. else
  127. command = HelperUtils.concat(command, request);
  128. response.add(message);
  129. }
  130. break;
  131. default:
  132. response.add(new ByteArray("\r\nlogout\r\n"));
  133. state = STATE.CLOSED;
  134. break;
  135. }
  136. return response;
  137. }
  138. public boolean isClosed() {
  139. return (state == STATE.CLOSED);
  140. }
  141. public boolean isSecure() {
  142. return false;
  143. }
  144. public String toString() {
  145. return "TELNET";
  146. }
  147. public Class<ByteArray> getType() {
  148. return ByteArray.class;
  149. }
  150. /**
  151. * Checks a byte array for occurence of one byte.
  152. * @param bytes byte array that is checked.
  153. * @param b searched byte.
  154. * @return true if the byte was found, else false.
  155. */
  156. private boolean checkForByte(byte[] bytes, byte b) {
  157. for(byte oneByte : bytes) {
  158. if(oneByte == b) return true;
  159. }
  160. return false;
  161. }
  162. /**
  163. * Determines which options that are requested by the client will be done and which not
  164. * @param request requested options
  165. * @return accepted and unaccepted options
  166. */
  167. private byte[] getOptionResponse(byte[] request) {
  168. List<byte[]> respList = new ArrayList<byte[]>();
  169. byte[] cmdResp;
  170. for(int i = 0; i < request.length - 2; i += 3) {
  171. if(request[i] == (byte) 0xff && request[i+2] != 0x03 && request[i+2] != 0x01) {
  172. cmdResp = new byte[3];
  173. cmdResp[0] = request[i];
  174. cmdResp[1] = request[i + 1] == (byte) 0xfd ? (byte) 0xfc : (byte) 0xfe;
  175. cmdResp[2] = request[i+2];
  176. respList.add(cmdResp);
  177. }
  178. }
  179. byte[] response = new byte[0];
  180. for(byte[] resp : respList) {
  181. response = HelperUtils.concat(response, resp);
  182. }
  183. return response;
  184. }
  185. /** options requested by the server */
  186. private final byte[] optionRequest = {(byte) 0xff, (byte) 0xfb, 0x03, //will suppress go ahead
  187. (byte) 0xff, (byte) 0xfb, 0x01}; //will echo
  188. //session token prefix, mid and suffix //TODO
  189. private final byte[] sessionPrefix = {0x1b, 0x5d, 0x30, 0x3b};
  190. private final byte[] sessionMiddle = {0x40, 0x72, 0x61, 0x73,
  191. 0x70, 0x62, 0x65, 0x72, 0x72, 0x79, 0x70, 0x69, 0x3a, 0x20, 0x7e, 0x07, 0x1b, 0x5b, 0x30, 0x31,
  192. 0x3b, 0x33, 0x32, 0x6d};
  193. private final byte[] sessionSuffix = {0x1b, 0x5b, 0x30, 0x30, 0x6d, 0x20, 0x1b, 0x5b, 0x30, 0x31,
  194. 0x3b, 0x33, 0x34, 0x6d, 0x7e, 0x20, 0x24, 0x1b, 0x5b, 0x30, 0x30, 0x6d, 0x20};
  195. }