1 r"""TELNET client class. 2 3 Based on RFC 854: TELNET Protocol Specification, by J. Postel and 4 J. Reynolds 5 6 Example: 7 8 >>> from telnetlib import Telnet 9 >>> tn = Telnet('www.python.org', 79) # connect to finger port 10 >>> tn.write(b'guido\r\n') 11 >>> print(tn.read_all()) 12 Login Name TTY Idle When Where 13 guido Guido van Rossum pts/2 <Dec 2 11:10> snag.cnri.reston.. 14 15 >>> 16 17 Note that read_all() won't read until eof -- it just reads some data 18 -- but it guarantees to read at least one byte unless EOF is hit. 19 20 It is possible to pass a Telnet object to a selector in order to wait until 21 more data is available. Note that in this case, read_eager() may return b'' 22 even if there was data on the socket, because the protocol negotiation may have 23 eaten the data. This is why EOFError is needed in some cases to distinguish 24 between "no data" and "connection closed" (since the socket also appears ready 25 for reading when it is closed). 26 27 To do: 28 - option negotiation 29 - timeout should be intrinsic to the connection object instead of an 30 option on one of the read calls only 31 32 """ 33 34 35 # Imported modules 36 import sys 37 import socket 38 import selectors 39 from time import monotonic as _time 40 41 __all__ = ["Telnet"] 42 43 # Tunable parameters 44 DEBUGLEVEL = 0 45 46 # Telnet protocol defaults 47 TELNET_PORT = 23 48 49 # Telnet protocol characters (don't change) 50 IAC = bytes([255]) # "Interpret As Command" 51 DONT = bytes([254]) 52 DO = bytes([253]) 53 WONT = bytes([252]) 54 WILL = bytes([251]) 55 theNULL = bytes([0]) 56 57 SE = bytes([240]) # Subnegotiation End 58 NOP = bytes([241]) # No Operation 59 DM = bytes([242]) # Data Mark 60 BRK = bytes([243]) # Break 61 IP = bytes([244]) # Interrupt process 62 AO = bytes([245]) # Abort output 63 AYT = bytes([246]) # Are You There 64 EC = bytes([247]) # Erase Character 65 EL = bytes([248]) # Erase Line 66 GA = bytes([249]) # Go Ahead 67 SB = bytes([250]) # Subnegotiation Begin 68 69 70 # Telnet protocol options code (don't change) 71 # These ones all come from arpa/telnet.h 72 BINARY = bytes([0]) # 8-bit data path 73 ECHO = bytes([1]) # echo 74 RCP = bytes([2]) # prepare to reconnect 75 SGA = bytes([3]) # suppress go ahead 76 NAMS = bytes([4]) # approximate message size 77 STATUS = bytes([5]) # give status 78 TM = bytes([6]) # timing mark 79 RCTE = bytes([7]) # remote controlled transmission and echo 80 NAOL = bytes([8]) # negotiate about output line width 81 NAOP = bytes([9]) # negotiate about output page size 82 NAOCRD = bytes([10]) # negotiate about CR disposition 83 NAOHTS = bytes([11]) # negotiate about horizontal tabstops 84 NAOHTD = bytes([12]) # negotiate about horizontal tab disposition 85 NAOFFD = bytes([13]) # negotiate about formfeed disposition 86 NAOVTS = bytes([14]) # negotiate about vertical tab stops 87 NAOVTD = bytes([15]) # negotiate about vertical tab disposition 88 NAOLFD = bytes([16]) # negotiate about output LF disposition 89 XASCII = bytes([17]) # extended ascii character set 90 LOGOUT = bytes([18]) # force logout 91 BM = bytes([19]) # byte macro 92 DET = bytes([20]) # data entry terminal 93 SUPDUP = bytes([21]) # supdup protocol 94 SUPDUPOUTPUT = bytes([22]) # supdup output 95 SNDLOC = bytes([23]) # send location 96 TTYPE = bytes([24]) # terminal type 97 EOR = bytes([25]) # end or record 98 TUID = bytes([26]) # TACACS user identification 99 OUTMRK = bytes([27]) # output marking 100 TTYLOC = bytes([28]) # terminal location number 101 VT3270REGIME = bytes([29]) # 3270 regime 102 X3PAD = bytes([30]) # X.3 PAD 103 NAWS = bytes([31]) # window size 104 TSPEED = bytes([32]) # terminal speed 105 LFLOW = bytes([33]) # remote flow control 106 LINEMODE = bytes([34]) # Linemode option 107 XDISPLOC = bytes([35]) # X Display Location 108 OLD_ENVIRON = bytes([36]) # Old - Environment variables 109 AUTHENTICATION = bytes([37]) # Authenticate 110 ENCRYPT = bytes([38]) # Encryption option 111 NEW_ENVIRON = bytes([39]) # New - Environment variables 112 # the following ones come from 113 # http://www.iana.org/assignments/telnet-options 114 # Unfortunately, that document does not assign identifiers 115 # to all of them, so we are making them up 116 TN3270E = bytes([40]) # TN3270E 117 XAUTH = bytes([41]) # XAUTH 118 CHARSET = bytes([42]) # CHARSET 119 RSP = bytes([43]) # Telnet Remote Serial Port 120 COM_PORT_OPTION = bytes([44]) # Com Port Control Option 121 SUPPRESS_LOCAL_ECHO = bytes([45]) # Telnet Suppress Local Echo 122 TLS = bytes([46]) # Telnet Start TLS 123 KERMIT = bytes([47]) # KERMIT 124 SEND_URL = bytes([48]) # SEND-URL 125 FORWARD_X = bytes([49]) # FORWARD_X 126 PRAGMA_LOGON = bytes([138]) # TELOPT PRAGMA LOGON 127 SSPI_LOGON = bytes([139]) # TELOPT SSPI LOGON 128 PRAGMA_HEARTBEAT = bytes([140]) # TELOPT PRAGMA HEARTBEAT 129 EXOPL = bytes([255]) # Extended-Options-List 130 NOOPT = bytes([0]) 131 132 133 # poll/select have the advantage of not requiring any extra file descriptor, 134 # contrarily to epoll/kqueue (also, they require a single syscall). 135 if hasattr(selectors, 'PollSelector'): 136 _TelnetSelector = selectors.PollSelector 137 else: 138 _TelnetSelector = selectors.SelectSelector 139 140 141 class Telnet: 142 143 """Telnet interface class. 144 145 An instance of this class represents a connection to a telnet 146 server. The instance is initially not connected; the open() 147 method must be used to establish a connection. Alternatively, the 148 host name and optional port number can be passed to the 149 constructor, too. 150 151 Don't try to reopen an already connected instance. 152 153 This class has many read_*() methods. Note that some of them 154 raise EOFError when the end of the connection is read, because 155 they can return an empty string for other reasons. See the 156 individual doc strings. 157 158 read_until(expected, [timeout]) 159 Read until the expected string has been seen, or a timeout is 160 hit (default is no timeout); may block. 161 162 read_all() 163 Read all data until EOF; may block. 164 165 read_some() 166 Read at least one byte or EOF; may block. 167 168 read_very_eager() 169 Read all data available already queued or on the socket, 170 without blocking. 171 172 read_eager() 173 Read either data already queued or some data available on the 174 socket, without blocking. 175 176 read_lazy() 177 Read all data in the raw queue (processing it first), without 178 doing any socket I/O. 179 180 read_very_lazy() 181 Reads all data in the cooked queue, without doing any socket 182 I/O. 183 184 read_sb_data() 185 Reads available data between SB ... SE sequence. Don't block. 186 187 set_option_negotiation_callback(callback) 188 Each time a telnet option is read on the input flow, this callback 189 (if set) is called with the following parameters : 190 callback(telnet socket, command, option) 191 option will be chr(0) when there is no option. 192 No other action is done afterwards by telnetlib. 193 194 """ 195 196 def __init__(self, host=None, port=0, 197 timeout=socket._GLOBAL_DEFAULT_TIMEOUT): 198 """Constructor. 199 200 When called without arguments, create an unconnected instance. 201 With a hostname argument, it connects the instance; port number 202 and timeout are optional. 203 """ 204 self.debuglevel = DEBUGLEVEL 205 self.host = host 206 self.port = port 207 self.timeout = timeout 208 self.sock = None 209 self.rawq = b'' 210 self.irawq = 0 211 self.cookedq = b'' 212 self.eof = 0 213 self.iacseq = b'' # Buffer for IAC sequence. 214 self.sb = 0 # flag for SB and SE sequence. 215 self.sbdataq = b'' 216 self.option_callback = None 217 if host is not None: 218 self.open(host, port, timeout) 219 220 def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): 221 """Connect to a host. 222 223 The optional second argument is the port number, which 224 defaults to the standard telnet port (23). 225 226 Don't try to reopen an already connected instance. 227 """ 228 self.eof = 0 229 if not port: 230 port = TELNET_PORT 231 self.host = host 232 self.port = port 233 self.timeout = timeout 234 self.sock = socket.create_connection((host, port), timeout) 235 236 def __del__(self): 237 """Destructor -- close the connection.""" 238 self.close() 239 240 def msg(self, msg, *args): 241 """Print a debug message, when the debug level is > 0. 242 243 If extra arguments are present, they are substituted in the 244 message using the standard string formatting operator. 245 246 """ 247 if self.debuglevel > 0: 248 print('Telnet(%s,%s):' % (self.host, self.port), end=' ') 249 if args: 250 print(msg % args) 251 else: 252 print(msg) 253 254 def set_debuglevel(self, debuglevel): 255 """Set the debug level. 256 257 The higher it is, the more debug output you get (on sys.stdout). 258 259 """ 260 self.debuglevel = debuglevel 261 262 def close(self): 263 """Close the connection.""" 264 sock = self.sock 265 self.sock = None 266 self.eof = True 267 self.iacseq = b'' 268 self.sb = 0 269 if sock: 270 sock.close() 271 272 def get_socket(self): 273 """Return the socket object used internally.""" 274 return self.sock 275 276 def fileno(self): 277 """Return the fileno() of the socket object used internally.""" 278 return self.sock.fileno() 279 280 def write(self, buffer): 281 """Write a string to the socket, doubling any IAC characters. 282 283 Can block if the connection is blocked. May raise 284 OSError if the connection is closed. 285 286 """ 287 if IAC in buffer: 288 buffer = buffer.replace(IAC, IAC+IAC) 289 self.msg("send %r", buffer) 290 self.sock.sendall(buffer) 291 292 def read_until(self, match, timeout=None): 293 """Read until a given string is encountered or until timeout. 294 295 When no match is found, return whatever is available instead, 296 possibly the empty string. Raise EOFError if the connection 297 is closed and no cooked data is available. 298 299 """ 300 n = len(match) 301 self.process_rawq() 302 i = self.cookedq.find(match) 303 if i >= 0: 304 i = i+n 305 buf = self.cookedq[:i] 306 self.cookedq = self.cookedq[i:] 307 return buf 308 if timeout is not None: 309 deadline = _time() + timeout 310 with _TelnetSelector() as selector: 311 selector.register(self, selectors.EVENT_READ) 312 while not self.eof: 313 if selector.select(timeout): 314 i = max(0, len(self.cookedq)-n) 315 self.fill_rawq() 316 self.process_rawq() 317 i = self.cookedq.find(match, i) 318 if i >= 0: 319 i = i+n 320 buf = self.cookedq[:i] 321 self.cookedq = self.cookedq[i:] 322 return buf 323 if timeout is not None: 324 timeout = deadline - _time() 325 if timeout < 0: 326 break 327 return self.read_very_lazy() 328 329 def read_all(self): 330 """Read all data until EOF; block until connection closed.""" 331 self.process_rawq() 332 while not self.eof: 333 self.fill_rawq() 334 self.process_rawq() 335 buf = self.cookedq 336 self.cookedq = b'' 337 return buf 338 339 def read_some(self): 340 """Read at least one byte of cooked data unless EOF is hit. 341 342 Return b'' if EOF is hit. Block if no data is immediately 343 available. 344 345 """ 346 self.process_rawq() 347 while not self.cookedq and not self.eof: 348 self.fill_rawq() 349 self.process_rawq() 350 buf = self.cookedq 351 self.cookedq = b'' 352 return buf 353 354 def read_very_eager(self): 355 """Read everything that's possible without blocking in I/O (eager). 356 357 Raise EOFError if connection closed and no cooked data 358 available. Return b'' if no cooked data available otherwise. 359 Don't block unless in the midst of an IAC sequence. 360 361 """ 362 self.process_rawq() 363 while not self.eof and self.sock_avail(): 364 self.fill_rawq() 365 self.process_rawq() 366 return self.read_very_lazy() 367 368 def read_eager(self): 369 """Read readily available data. 370 371 Raise EOFError if connection closed and no cooked data 372 available. Return b'' if no cooked data available otherwise. 373 Don't block unless in the midst of an IAC sequence. 374 375 """ 376 self.process_rawq() 377 while not self.cookedq and not self.eof and self.sock_avail(): 378 self.fill_rawq() 379 self.process_rawq() 380 return self.read_very_lazy() 381 382 def read_lazy(self): 383 """Process and return data that's already in the queues (lazy). 384 385 Raise EOFError if connection closed and no data available. 386 Return b'' if no cooked data available otherwise. Don't block 387 unless in the midst of an IAC sequence. 388 389 """ 390 self.process_rawq() 391 return self.read_very_lazy() 392 393 def read_very_lazy(self): 394 """Return any data available in the cooked queue (very lazy). 395 396 Raise EOFError if connection closed and no data available. 397 Return b'' if no cooked data available otherwise. Don't block. 398 399 """ 400 buf = self.cookedq 401 self.cookedq = b'' 402 if not buf and self.eof and not self.rawq: 403 raise EOFError('telnet connection closed') 404 return buf 405 406 def read_sb_data(self): 407 """Return any data available in the SB ... SE queue. 408 409 Return b'' if no SB ... SE available. Should only be called 410 after seeing a SB or SE command. When a new SB command is 411 found, old unread SB data will be discarded. Don't block. 412 413 """ 414 buf = self.sbdataq 415 self.sbdataq = b'' 416 return buf 417 418 def set_option_negotiation_callback(self, callback): 419 """Provide a callback function called after each receipt of a telnet option.""" 420 self.option_callback = callback 421 422 def process_rawq(self): 423 """Transfer from raw queue to cooked queue. 424 425 Set self.eof when connection is closed. Don't block unless in 426 the midst of an IAC sequence. 427 428 """ 429 buf = [b'', b''] 430 try: 431 while self.rawq: 432 c = self.rawq_getchar() 433 if not self.iacseq: 434 if c == theNULL: 435 continue 436 if c == b"\021": 437 continue 438 if c != IAC: 439 buf[self.sb] = buf[self.sb] + c 440 continue 441 else: 442 self.iacseq += c 443 elif len(self.iacseq) == 1: 444 # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]' 445 if c in (DO, DONT, WILL, WONT): 446 self.iacseq += c 447 continue 448 449 self.iacseq = b'' 450 if c == IAC: 451 buf[self.sb] = buf[self.sb] + c 452 else: 453 if c == SB: # SB ... SE start. 454 self.sb = 1 455 self.sbdataq = b'' 456 elif c == SE: 457 self.sb = 0 458 self.sbdataq = self.sbdataq + buf[1] 459 buf[1] = b'' 460 if self.option_callback: 461 # Callback is supposed to look into 462 # the sbdataq 463 self.option_callback(self.sock, c, NOOPT) 464 else: 465 # We can't offer automatic processing of 466 # suboptions. Alas, we should not get any 467 # unless we did a WILL/DO before. 468 self.msg('IAC %d not recognized' % ord(c)) 469 elif len(self.iacseq) == 2: 470 cmd = self.iacseq[1:2] 471 self.iacseq = b'' 472 opt = c 473 if cmd in (DO, DONT): 474 self.msg('IAC %s %d', 475 cmd == DO and 'DO' or 'DONT', ord(opt)) 476 if self.option_callback: 477 self.option_callback(self.sock, cmd, opt) 478 else: 479 self.sock.sendall(IAC + WONT + opt) 480 elif cmd in (WILL, WONT): 481 self.msg('IAC %s %d', 482 cmd == WILL and 'WILL' or 'WONT', ord(opt)) 483 if self.option_callback: 484 self.option_callback(self.sock, cmd, opt) 485 else: 486 self.sock.sendall(IAC + DONT + opt) 487 except EOFError: # raised by self.rawq_getchar() 488 self.iacseq = b'' # Reset on EOF 489 self.sb = 0 490 pass 491 self.cookedq = self.cookedq + buf[0] 492 self.sbdataq = self.sbdataq + buf[1] 493 494 def rawq_getchar(self): 495 """Get next char from raw queue. 496 497 Block if no data is immediately available. Raise EOFError 498 when connection is closed. 499 500 """ 501 if not self.rawq: 502 self.fill_rawq() 503 if self.eof: 504 raise EOFError 505 c = self.rawq[self.irawq:self.irawq+1] 506 self.irawq = self.irawq + 1 507 if self.irawq >= len(self.rawq): 508 self.rawq = b'' 509 self.irawq = 0 510 return c 511 512 def fill_rawq(self): 513 """Fill raw queue from exactly one recv() system call. 514 515 Block if no data is immediately available. Set self.eof when 516 connection is closed. 517 518 """ 519 if self.irawq >= len(self.rawq): 520 self.rawq = b'' 521 self.irawq = 0 522 # The buffer size should be fairly small so as to avoid quadratic 523 # behavior in process_rawq() above 524 buf = self.sock.recv(50) 525 self.msg("recv %r", buf) 526 self.eof = (not buf) 527 self.rawq = self.rawq + buf 528 529 def sock_avail(self): 530 """Test whether data is available on the socket.""" 531 with _TelnetSelector() as selector: 532 selector.register(self, selectors.EVENT_READ) 533 return bool(selector.select(0)) 534 535 def interact(self): 536 """Interaction function, emulates a very dumb telnet client.""" 537 if sys.platform == "win32": 538 self.mt_interact() 539 return 540 with _TelnetSelector() as selector: 541 selector.register(self, selectors.EVENT_READ) 542 selector.register(sys.stdin, selectors.EVENT_READ) 543 544 while True: 545 for key, events in selector.select(): 546 if key.fileobj is self: 547 try: 548 text = self.read_eager() 549 except EOFError: 550 print('*** Connection closed by remote host ***') 551 return 552 if text: 553 sys.stdout.write(text.decode('ascii')) 554 sys.stdout.flush() 555 elif key.fileobj is sys.stdin: 556 line = sys.stdin.readline().encode('ascii') 557 if not line: 558 return 559 self.write(line) 560 561 def mt_interact(self): 562 """Multithreaded version of interact().""" 563 import _thread 564 _thread.start_new_thread(self.listener, ()) 565 while 1: 566 line = sys.stdin.readline() 567 if not line: 568 break 569 self.write(line.encode('ascii')) 570 571 def listener(self): 572 """Helper for mt_interact() -- this executes in the other thread.""" 573 while 1: 574 try: 575 data = self.read_eager() 576 except EOFError: 577 print('*** Connection closed by remote host ***') 578 return 579 if data: 580 sys.stdout.write(data.decode('ascii')) 581 else: 582 sys.stdout.flush() 583 584 def expect(self, list, timeout=None): 585 """Read until one from a list of a regular expressions matches. 586 587 The first argument is a list of regular expressions, either 588 compiled (re.Pattern instances) or uncompiled (strings). 589 The optional second argument is a timeout, in seconds; default 590 is no timeout. 591 592 Return a tuple of three items: the index in the list of the 593 first regular expression that matches; the re.Match object 594 returned; and the text read up till and including the match. 595 596 If EOF is read and no text was read, raise EOFError. 597 Otherwise, when nothing matches, return (-1, None, text) where 598 text is the text received so far (may be the empty string if a 599 timeout happened). 600 601 If a regular expression ends with a greedy match (e.g. '.*') 602 or if more than one expression can match the same input, the 603 results are undeterministic, and may depend on the I/O timing. 604 605 """ 606 re = None 607 list = list[:] 608 indices = range(len(list)) 609 for i in indices: 610 if not hasattr(list[i], "search"): 611 if not re: import re 612 list[i] = re.compile(list[i]) 613 if timeout is not None: 614 deadline = _time() + timeout 615 with _TelnetSelector() as selector: 616 selector.register(self, selectors.EVENT_READ) 617 while not self.eof: 618 self.process_rawq() 619 for i in indices: 620 m = list[i].search(self.cookedq) 621 if m: 622 e = m.end() 623 text = self.cookedq[:e] 624 self.cookedq = self.cookedq[e:] 625 return (i, m, text) 626 if timeout is not None: 627 ready = selector.select(timeout) 628 timeout = deadline - _time() 629 if not ready: 630 if timeout < 0: 631 break 632 else: 633 continue 634 self.fill_rawq() 635 text = self.read_very_lazy() 636 if not text and self.eof: 637 raise EOFError 638 return (-1, None, text) 639 640 def __enter__(self): 641 return self 642 643 def __exit__(self, type, value, traceback): 644 self.close() 645 646 647 def test(): 648 """Test program for telnetlib. 649 650 Usage: python telnetlib.py [-d] ... [host [port]] 651 652 Default host is localhost; default port is 23. 653 654 """ 655 debuglevel = 0 656 while sys.argv[1:] and sys.argv[1] == '-d': 657 debuglevel = debuglevel+1 658 del sys.argv[1] 659 host = 'localhost' 660 if sys.argv[1:]: 661 host = sys.argv[1] 662 port = 0 663 if sys.argv[2:]: 664 portstr = sys.argv[2] 665 try: 666 port = int(portstr) 667 except ValueError: 668 port = socket.getservbyname(portstr, 'tcp') 669 with Telnet() as tn: 670 tn.set_debuglevel(debuglevel) 671 tn.open(host, port, timeout=0.5) 672 tn.interact() 673 674 if __name__ == '__main__': 675 test() 676