# $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 == {}