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