telnet.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """Telnet."""
  2. from pypacker import pypacker, triggerlist
  3. import struct
  4. IAC = 255 # interpret as command:
  5. DONT = 254 # you are not to use option
  6. DO = 253 # please, you use option
  7. WONT = 252 # I won"t use option
  8. WILL = 251 # I will use option
  9. SB = 250 # interpret as subnegotiation
  10. GA = 249 # you may reverse the line
  11. EL = 248 # erase the current line
  12. EC = 247 # erase the current character
  13. AYT = 246 # are you there
  14. AO = 245 # abort output--but let prog finish
  15. IP = 244 # interrupt process--permanently
  16. BREAK = 243 # break
  17. DM = 242 # data mark--for connect. cleaning
  18. NOP = 241 # nop
  19. SE = 240 # end sub negotiation
  20. EOR = 239 # end of record (transparent mode)
  21. ABORT = 238 # Abort process
  22. SUSP = 237 # Suspend process
  23. xEOF = 236 # End of file: EOF is already used...
  24. SYNCH = 242 # for telfunc calls
  25. class TelnetTriggerList(triggerlist.TriggerList):
  26. def _pack(self):
  27. return b"".join(self)
  28. TELNET_OPTION_START = b"\xff\xaa"
  29. TELNET_OPTION_END = b"\xff\x00"
  30. class Telnet(pypacker.Packet):
  31. __hdr__ = (
  32. ("telnet_data", None, TelnetTriggerList),
  33. )
  34. def _dissect(self, buf):
  35. self._init_triggerlist("telnet_data", buf, self._parse_data)
  36. return len(buf)
  37. @staticmethod
  38. def _parse_data(buf):
  39. off = 0
  40. t_data = []
  41. t_len = len(buf)
  42. # parse telnet data:
  43. # fffaXX = start of options
  44. # fff0 = end of options
  45. while off < t_len:
  46. if buf[off: off + 2] == TELNET_OPTION_START:
  47. # add start marker
  48. t_data.append(buf[off: off + 3])
  49. off += 3
  50. # find end of option
  51. idx_end = buf.find(TELNET_OPTION_END, off)
  52. # add option data
  53. t_data.append(buf[off: idx_end + 1])
  54. # add end marker
  55. t_data.append(TELNET_OPTION_END)
  56. off = idx_end + 2
  57. else:
  58. # add command
  59. t_data.append(buf[off: off + 3])
  60. off += 3
  61. return t_data
  62. def strip_options(buf):
  63. """Return a list of lines and dict of options from telnet data."""
  64. l = buf.split(struct.pack("B", IAC))
  65. b = []
  66. d = {}
  67. subopt = False
  68. for w in l:
  69. if not w:
  70. continue
  71. o = w[0]
  72. if o > SB:
  73. # print("WILL/WONT/DO/DONT/IAC", "w")
  74. w = w[2:]
  75. elif o == SE:
  76. # print("SE", "w")
  77. w = w[1:]
  78. subopt = False
  79. elif o == SB:
  80. # print("SB", "w")
  81. subopt = True
  82. for opt in (b"USER", b"DISPLAY", b"TERM"):
  83. p = w.find(opt + b"\x01")
  84. if p != -1:
  85. d[opt] = w[p + len(opt) + 1:].split(b"\x00", 1)[0]
  86. w = None
  87. elif subopt:
  88. w = None
  89. if w:
  90. w = w.replace(b"\x00", b"\n").splitlines()
  91. if not w[-1]:
  92. w.pop()
  93. b.extend(w)
  94. return b, d