| # $Id: telnet.py 23 2006-11-08 15:45:33Z dugsong $ |
| # -*- coding: utf-8 -*- |
| """Telnet.""" |
| from __future__ import print_function |
| from __future__ import absolute_import |
| |
| import struct |
| |
| from .compat import compat_ord |
| |
| IAC = 255 # interpret as command: |
| DONT = 254 # you are not to use option |
| DO = 253 # please, you use option |
| WONT = 252 # I won't use option |
| WILL = 251 # I will use option |
| SB = 250 # interpret as subnegotiation |
| GA = 249 # you may reverse the line |
| EL = 248 # erase the current line |
| EC = 247 # erase the current character |
| AYT = 246 # are you there |
| AO = 245 # abort output--but let prog finish |
| IP = 244 # interrupt process--permanently |
| BREAK = 243 # break |
| DM = 242 # data mark--for connect. cleaning |
| NOP = 241 # nop |
| SE = 240 # end sub negotiation |
| EOR = 239 # end of record (transparent mode) |
| ABORT = 238 # Abort process |
| SUSP = 237 # Suspend process |
| xEOF = 236 # End of file: EOF is already used... |
| |
| SYNCH = 242 # for telfunc calls |
| |
| |
| def strip_options(buf): |
| """Return a list of lines and dict of options from telnet data.""" |
| l_ = buf.split(struct.pack("B", IAC)) |
| # print l_ |
| b = [] |
| d = {} |
| subopt = False |
| for w in l_: |
| if not w: |
| continue |
| o = compat_ord(w[0]) |
| if o > SB: |
| # print 'WILL/WONT/DO/DONT/IAC', `w` |
| w = w[2:] |
| elif o == SE: |
| # print 'SE', `w` |
| w = w[1:] |
| subopt = False |
| elif o == SB: |
| # print 'SB', `w` |
| subopt = True |
| for opt in (b'USER', b'DISPLAY', b'TERM'): |
| p = w.find(opt + b'\x01') |
| if p != -1: |
| d[opt] = w[p + len(opt) + 1:].split(b'\x00', 1)[0] |
| w = None |
| elif subopt: |
| w = None |
| if w: |
| w = w.replace(b'\x00', b'\n').splitlines() |
| if not w[-1]: |
| w.pop() |
| b.extend(w) |
| return b, d |
| |
| |
| def test_telnet(): |
| l_ = [] |
| s = (b'\xff\xfb\x25\xff\xfa\x25\x00\x00\x00\xff\xf0\xff\xfd\x26\xff\xfa\x26\x05\xff\xf0\xff\xfa' |
| b'\x26\x01\x01\x02\xff\xf0\xff\xfb\x18\xff\xfb\x20\xff\xfb\x23\xff\xfb\x27\xff\xfc\x24\xff' |
| b'\xfa\x20\x00\x33\x38\x34\x30\x30\x2c\x33\x38\x34\x30\x30\xff\xf0\xff\xfa\x23\x00\x64\x6f' |
| b'\x75\x67\x68\x62\x6f\x79\x2e\x63\x69\x74\x69\x2e\x75\x6d\x69\x63\x68\x2e\x65\x64\x75\x3a' |
| b'\x30\x2e\x30\xff\xf0\xff\xfa\x27\x00\x00\x44\x49\x53\x50\x4c\x41\x59\x01\x64\x6f\x75\x67' |
| b'\x68\x62\x6f\x79\x2e\x63\x69\x74\x69\x2e\x75\x6d\x69\x63\x68\x2e\x65\x64\x75\x3a\x30\x2e' |
| b'\x30\x00\x55\x53\x45\x52\x01\x64\x75\x67\x73\x6f\x6e\x67\xff\xf0\xff\xfa\x18\x00\x58\x54' |
| b'\x45\x52\x4d\xff\xf0\xff\xfd\x03\xff\xfc\x01\xff\xfb\x1f\xff\xfa\x1f\x00\x50\x00\x28\xff' |
| b'\xf0\xff\xfd\x05\xff\xfb\x21\xff\xfd\x01\x66\x75\x67\x6c\x79\x0d\x00\x79\x6f\x64\x61\x0d' |
| b'\x00\x62\x61\x73\x68\x74\x61\x72\x64\x0d\x00') |
| l_.append(s) |
| s = (b'\xff\xfd\x01\xff\xfd\x03\xff\xfb\x18\xff\xfb\x1f\xff\xfa\x1f\x00\x58\x00\x32\xff\xf0\x61' |
| b'\x64\x6d\x69\x6e\x0d\x00\xff\xfa\x18\x00\x4c\x49\x4e\x55\x58\xff\xf0\x66\x6f\x6f\x62\x61' |
| b'\x72\x0d\x00\x65\x6e\x61\x62\x6c\x65\x0d\x00\x66\x6f\x6f\x62\x61\x72\x0d\x00\x0d\x00\x73' |
| b'\x68\x6f\x77\x20\x69\x70\x20\x69\x6e\x74\x20\x56\x6c\x61\x6e\x20\x36\x36\x36\x0d\x00') |
| l_.append(s) |
| s = (b'\xff\xfb\x25\xff\xfa\x25\x00\x00\x00\xff\xf0\xff\xfd\x26\xff\xfa\x26\x05\xff\xf0\xff\xfa' |
| b'\x26\x01\x01\x02\xff\xf0\xff\xfb\x26\xff\xfb\x18\xff\xfb\x20\xff\xfb\x23\xff\xfb\x27\xff' |
| b'\xfc\x24\xff\xfa\x20\x00\x33\x38\x34\x30\x30\x2c\x33\x38\x34\x30\x30\xff\xf0\xff\xfa\x23' |
| b'\x00\x64\x6f\x75\x67\x68\x62\x6f\x79\x2e\x63\x69\x74\x69\x2e\x75\x6d\x69\x63\x68\x2e\x65' |
| b'\x64\x75\x3a\x30\x2e\x30\xff\xf0\xff\xfa\x27\x00\x00\x44\x49\x53\x50\x4c\x41\x59\x01\x64' |
| b'\x6f\x75\x67\x68\x62\x6f\x79\x2e\x63\x69\x74\x69\x2e\x75\x6d\x69\x63\x68\x2e\x65\x64\x75' |
| b'\x3a\x30\x2e\x30\x00\x55\x53\x45\x52\x01\x64\x75\x67\x73\x6f\x6e\x67\xff\xf0\xff\xfa\x18' |
| b'\x00\x58\x54\x45\x52\x4d\xff\xf0\xff\xfd\x03\xff\xfc\x01\xff\xfb\x22\xff\xfa\x22\x03\x01' |
| b'\x03\x00\x03\x62\x03\x04\x02\x0f\x05\x00\xff\xff\x07\x62\x1c\x08\x02\x04\x09\x42\x1a\x0a' |
| b'\x02\x7f\x0b\x02\x15\x0c\x02\x17\x0d\x02\x12\x0e\x02\x16\x0f\x02\x11\x10\x02\x13\x11\x00' |
| b'\xff\xff\x12\x00\xff\xff\xff\xf0\xff\xfb\x1f\xff\xfa\x1f\x00\x50\x00\x28\xff\xf0\xff\xfd' |
| b'\x05\xff\xfb\x21\xff\xfa\x22\x01\x0f\xff\xf0\xff\xfd\x01\xff\xfe\x01\xff\xfa\x22\x03\x01' |
| b'\x80\x00\xff\xf0\xff\xfd\x01\x77\x65\x72\x64\x0d\x0a\xff\xfe\x01\x79\x6f\x64\x61\x0d\x0a' |
| b'\xff\xfd\x01\x64\x61\x72\x74\x68\x76\x61\x64\x65\x72\x0d\x0a\xff\xfe\x01') |
| l_.append(s) |
| exp = [([b'fugly', b'yoda', b'bashtard'], {b'USER': b'dugsong', b'DISPLAY': b'doughboy.citi.umich.edu:0.0'}), |
| ([b'admin', b'foobar', b'enable', b'foobar', b'', b'show ip int Vlan 666'], {}), |
| ([b'werd', b'yoda', b'darthvader'], {b'USER': b'dugsong', b'DISPLAY': b'doughboy.citi.umich.edu:0.0'})] |
| assert (list(map(strip_options, l_)) == exp) |
| |
| |
| def test_trailing_null(): |
| from binascii import unhexlify |
| buf = unhexlify( |
| '0100020000' |
| ) |
| b, d = strip_options(buf) |
| assert b == [b'\x01', b'\x02'] |
| assert d == {} |