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