TELNET.java 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. package de.tudarmstadt.informatik.hostage.protocol;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import android.content.Context;
  5. import de.tudarmstadt.informatik.hostage.Hostage;
  6. import de.tudarmstadt.informatik.hostage.R;
  7. import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
  8. import de.tudarmstadt.informatik.hostage.wrapper.Packet;
  9. /**
  10. * TELNET protocol. Implementation of RFC document 854.
  11. *
  12. * @author Wulf Pfeiffer
  13. */
  14. public class TELNET implements Protocol {
  15. /**
  16. * Represents the states of the protocol
  17. */
  18. private static enum STATE {
  19. NONE, OPEN, CLOSED, LOGIN, AUTHENTICATE, LOGGED_IN
  20. };
  21. /**
  22. * Denotes in which state the protocol is right now
  23. */
  24. private STATE state = STATE.NONE;
  25. /** user entered by the client */
  26. private byte[] user;
  27. /** last command sent by the client */
  28. private byte[] command;
  29. /** name of the server */
  30. private String serverName = HelperUtils.getRandomString(16, false);
  31. private String serverVersion = initServerVersion();
  32. private String login = initLogin();
  33. private String serverBanner = initServerBanner();
  34. /** command line prefix */
  35. private static byte[] sessionToken = null;
  36. /** options requested by the server */
  37. private static final byte[] optionRequest = {
  38. (byte) 0xff, (byte) 0xfb,
  39. 0x03, // will suppress go ahead
  40. (byte) 0xff, (byte) 0xfb, 0x01 // will echo
  41. };
  42. // session token prefix, mid and suffix
  43. private static final byte[] sessionPrefix = { 0x1b, 0x5d, 0x30, 0x3b };
  44. private static final byte[] sessionMiddle = { 0x3a, 0x20, 0x7e, 0x07, 0x1b,
  45. 0x5b, 0x30, 0x31, 0x3b, 0x33, 0x32, 0x6d };
  46. private static final byte[] sessionSuffix = { 0x1b, 0x5b, 0x30, 0x30, 0x6d,
  47. 0x20, 0x1b, 0x5b, 0x30, 0x31, 0x3b, 0x33, 0x34, 0x6d, 0x7e, 0x20,
  48. 0x24, 0x1b, 0x5b, 0x30, 0x30, 0x6d, 0x20 };
  49. @Override
  50. public int getPort() {
  51. return 23;
  52. }
  53. @Override
  54. public boolean isClosed() {
  55. return (state == STATE.CLOSED);
  56. }
  57. @Override
  58. public boolean isSecure() {
  59. return false;
  60. }
  61. @Override
  62. public List<Packet> processMessage(Packet requestPacket) {
  63. byte[] request = null;
  64. if (requestPacket != null && requestPacket.getBytes().length > 0) { // ignore empty packets
  65. request = requestPacket.getBytes();
  66. }
  67. List<Packet> responsePackets = new ArrayList<Packet>();
  68. switch (state) {
  69. case NONE:
  70. responsePackets.add(new Packet(optionRequest, toString()));
  71. state = STATE.OPEN;
  72. break;
  73. case OPEN:
  74. if (request != null) {
  75. responsePackets.add(new Packet(getOptionResponse(request), toString()));
  76. responsePackets.add(new Packet(login + "login: ", toString()));
  77. state = STATE.LOGIN;
  78. }
  79. break;
  80. case LOGIN:
  81. if (request == null)
  82. break;
  83. else if (checkForByte(request, (byte) 0x0d)) {
  84. if (request.length > 2) {
  85. byte[] buffer = new byte[request.length - 2];
  86. System.arraycopy(request, 0, buffer, 0, request.length - 2);
  87. user = HelperUtils.concat(user, buffer);
  88. responsePackets.add(new Packet(buffer, toString()));
  89. }
  90. responsePackets.add(new Packet("\r\n", toString()));
  91. responsePackets.add(new Packet("password: ", toString()));
  92. state = STATE.AUTHENTICATE;
  93. if (serverVersion.contains("Windows")) {
  94. sessionToken = HelperUtils.concat("C:\\Users\\".getBytes(), user, ">".getBytes());
  95. } else {
  96. sessionToken = HelperUtils.concat(sessionPrefix, user,
  97. "@".getBytes(), serverName.getBytes(), sessionMiddle,
  98. user, "@".getBytes(), serverName.getBytes(),
  99. sessionSuffix);
  100. }
  101. break;
  102. } else if (checkForByte(request, (byte) 0x7f) && user != null
  103. && user.length != 0) {
  104. byte[] tmp = new byte[user.length - 1];
  105. System.arraycopy(user, 0, tmp, 0, user.length - 1);
  106. user = tmp;
  107. responsePackets.add(new Packet("\b \b", toString()));
  108. break;
  109. } else if (!checkForByte(request, (byte) 0xff)) {
  110. if (user == null)
  111. user = request;
  112. else
  113. user = HelperUtils.concat(user, request);
  114. responsePackets.add(requestPacket);
  115. }
  116. break;
  117. case AUTHENTICATE:
  118. if (request == null)
  119. break;
  120. else if (checkForByte(request, (byte) 0x0d)) {
  121. responsePackets.add(new Packet("\r\n"+serverBanner, toString()));
  122. responsePackets.add(new Packet(sessionToken, toString()));
  123. state = STATE.LOGGED_IN;
  124. } else if (checkForByte(request, (byte) 0x7f)) {
  125. responsePackets.add(new Packet("\b \b", toString()));
  126. }
  127. break;
  128. case LOGGED_IN:
  129. if (request == null)
  130. break;
  131. else if (checkForByte(request, (byte) 0x0d)) {
  132. if (request.length > 2) {
  133. byte[] buffer = new byte[request.length - 2];
  134. System.arraycopy(request, 0, buffer, 0, request.length - 2);
  135. command = HelperUtils.concat(command, buffer);
  136. responsePackets.add(new Packet(buffer, toString()));
  137. }
  138. if (command == null) {
  139. responsePackets.add(new Packet("\r\n", toString()));
  140. responsePackets.add(new Packet(sessionToken, toString()));
  141. } else if (new String(command).contains("exit")) {
  142. responsePackets.add(new Packet("\r\nlogout\r\n", toString()));
  143. state = STATE.CLOSED;
  144. } else {
  145. String bash = "\r\n-bash: " + new String(command)
  146. + ": command not found";
  147. responsePackets.add(new Packet(bash, toString()));
  148. responsePackets.add(new Packet("\r\n", toString()));
  149. responsePackets.add(new Packet(sessionToken, toString()));
  150. command = null;
  151. }
  152. } else if (checkForByte(request, (byte) 0x7f) && command != null
  153. && command.length != 0) {
  154. byte[] tmp = new byte[command.length - 1];
  155. System.arraycopy(command, 0, tmp, 0, command.length - 1);
  156. command = tmp;
  157. responsePackets.add(new Packet("\b \b", toString()));
  158. break;
  159. } else if (!checkForByte(request, (byte) 0xff)) {
  160. if (command == null)
  161. command = request;
  162. else
  163. command = HelperUtils.concat(command, request);
  164. responsePackets.add(requestPacket);
  165. }
  166. break;
  167. default:
  168. responsePackets.add(new Packet("\r\nlogout\r\n", toString()));
  169. state = STATE.CLOSED;
  170. break;
  171. }
  172. return responsePackets;
  173. }
  174. @Override
  175. public String toString() {
  176. return "TELNET";
  177. }
  178. @Override
  179. public TALK_FIRST whoTalksFirst() {
  180. return TALK_FIRST.SERVER;
  181. }
  182. private static String initServerVersion() {
  183. String sharedPreferencePath = Hostage.getContext().getString(
  184. R.string.shared_preference_path);
  185. String profile = Hostage
  186. .getContext()
  187. .getSharedPreferences(sharedPreferencePath,
  188. Context.MODE_PRIVATE).getString("os", "");
  189. return profile;
  190. }
  191. private String initServerBanner() {
  192. if (serverVersion.contains("Windows")) {
  193. return "\r\n*===============================================================\r\n"
  194. + "Microsoft Telnet Server.\r\n"
  195. + "*===============================================================\r\n";
  196. }
  197. return "";
  198. }
  199. private String initLogin() {
  200. if (serverVersion.contains("Windows")) {
  201. return "Welcome to Microsoft Telnet Service \r\n\r\n";
  202. }
  203. return "Debian GNU/Linux 7.0\r\n";
  204. }
  205. /**
  206. * Checks a byte array for occurence of one byte.
  207. *
  208. * @param bytes
  209. * byte array that is checked.
  210. * @param b
  211. * searched byte.
  212. * @return true if the byte was found, else false.
  213. */
  214. private boolean checkForByte(byte[] bytes, byte b) {
  215. for (byte oneByte : bytes) {
  216. if (oneByte == b)
  217. return true;
  218. }
  219. return false;
  220. }
  221. /**
  222. * Determines which options that are requested by the client will be done
  223. * and which not
  224. *
  225. * @param request
  226. * requested options
  227. * @return accepted and unaccepted options
  228. */
  229. private byte[] getOptionResponse(byte[] request) {
  230. List<byte[]> responseList = new ArrayList<byte[]>();
  231. byte[] requestInverse;
  232. for (int i = 0; i < request.length - 2; i += 3) {
  233. if (request[i] == (byte) 0xff && request[i + 2] != 0x03
  234. && request[i + 2] != 0x01) {
  235. requestInverse = new byte[3];
  236. requestInverse[0] = request[i];
  237. requestInverse[1] = request[i + 1] == (byte) 0xfd ? (byte) 0xfc
  238. : (byte) 0xfe;
  239. requestInverse[2] = request[i + 2];
  240. responseList.add(requestInverse);
  241. }
  242. }
  243. byte[] optionResponse = new byte[0];
  244. for (byte[] response : responseList) {
  245. optionResponse = HelperUtils.concat(optionResponse, response);
  246. }
  247. return optionResponse;
  248. }
  249. }