telnetlib.py 22.5 KB
Newer Older
1
r"""TELNET client class.
2 3 4 5 6 7 8 9

Based on RFC 854: TELNET Protocol Specification, by J. Postel and
J. Reynolds

Example:

>>> from telnetlib import Telnet
>>> tn = Telnet('www.python.org', 79)   # connect to finger port
10
>>> tn.write(b'guido\r\n')
11
>>> print(tn.read_all())
12 13
Login       Name               TTY         Idle    When    Where
guido    Guido van Rossum      pts/2        <Dec  2 11:10> snag.cnri.reston..
Tim Peters's avatar
Tim Peters committed
14

15 16 17 18 19
>>>

Note that read_all() won't read until eof -- it just reads some data
-- but it guarantees to read at least one byte unless EOF is hit.

20 21 22 23 24 25
It is possible to pass a Telnet object to a selector in order to wait until
more data is available.  Note that in this case, read_eager() may return b''
even if there was data on the socket, because the protocol negotiation may have
eaten the data.  This is why EOFError is needed in some cases to distinguish
between "no data" and "connection closed" (since the socket also appears ready
for reading when it is closed).
26 27 28

To do:
- option negotiation
29 30
- timeout should be intrinsic to the connection object instead of an
  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 42
__all__ = ["Telnet"]

43 44 45 46 47 48 49
# Tunable parameters
DEBUGLEVEL = 0

# Telnet protocol defaults
TELNET_PORT = 23

# Telnet protocol characters (don't change)
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
IAC  = bytes([255]) # "Interpret As Command"
DONT = bytes([254])
DO   = bytes([253])
WONT = bytes([252])
WILL = bytes([251])
theNULL = bytes([0])

SE  = bytes([240])  # Subnegotiation End
NOP = bytes([241])  # No Operation
DM  = bytes([242])  # Data Mark
BRK = bytes([243])  # Break
IP  = bytes([244])  # Interrupt process
AO  = bytes([245])  # Abort output
AYT = bytes([246])  # Are You There
EC  = bytes([247])  # Erase Character
EL  = bytes([248])  # Erase Line
GA  = bytes([249])  # Go Ahead
SB =  bytes([250])  # Subnegotiation Begin
68

69

70 71
# Telnet protocol options code (don't change)
# These ones all come from arpa/telnet.h
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
BINARY = bytes([0]) # 8-bit data path
ECHO = bytes([1]) # echo
RCP = bytes([2]) # prepare to reconnect
SGA = bytes([3]) # suppress go ahead
NAMS = bytes([4]) # approximate message size
STATUS = bytes([5]) # give status
TM = bytes([6]) # timing mark
RCTE = bytes([7]) # remote controlled transmission and echo
NAOL = bytes([8]) # negotiate about output line width
NAOP = bytes([9]) # negotiate about output page size
NAOCRD = bytes([10]) # negotiate about CR disposition
NAOHTS = bytes([11]) # negotiate about horizontal tabstops
NAOHTD = bytes([12]) # negotiate about horizontal tab disposition
NAOFFD = bytes([13]) # negotiate about formfeed disposition
NAOVTS = bytes([14]) # negotiate about vertical tab stops
NAOVTD = bytes([15]) # negotiate about vertical tab disposition
NAOLFD = bytes([16]) # negotiate about output LF disposition
XASCII = bytes([17]) # extended ascii character set
LOGOUT = bytes([18]) # force logout
BM = bytes([19]) # byte macro
DET = bytes([20]) # data entry terminal
SUPDUP = bytes([21]) # supdup protocol
SUPDUPOUTPUT = bytes([22]) # supdup output
SNDLOC = bytes([23]) # send location
TTYPE = bytes([24]) # terminal type
EOR = bytes([25]) # end or record
TUID = bytes([26]) # TACACS user identification
OUTMRK = bytes([27]) # output marking
TTYLOC = bytes([28]) # terminal location number
VT3270REGIME = bytes([29]) # 3270 regime
X3PAD = bytes([30]) # X.3 PAD
NAWS = bytes([31]) # window size
TSPEED = bytes([32]) # terminal speed
LFLOW = bytes([33]) # remote flow control
LINEMODE = bytes([34]) # Linemode option
XDISPLOC = bytes([35]) # X Display Location
OLD_ENVIRON = bytes([36]) # Old - Environment variables
AUTHENTICATION = bytes([37]) # Authenticate
ENCRYPT = bytes([38]) # Encryption option
NEW_ENVIRON = bytes([39]) # New - Environment variables
112 113 114 115
# the following ones come from
# http://www.iana.org/assignments/telnet-options
# Unfortunately, that document does not assign identifiers
# to all of them, so we are making them up
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
TN3270E = bytes([40]) # TN3270E
XAUTH = bytes([41]) # XAUTH
CHARSET = bytes([42]) # CHARSET
RSP = bytes([43]) # Telnet Remote Serial Port
COM_PORT_OPTION = bytes([44]) # Com Port Control Option
SUPPRESS_LOCAL_ECHO = bytes([45]) # Telnet Suppress Local Echo
TLS = bytes([46]) # Telnet Start TLS
KERMIT = bytes([47]) # KERMIT
SEND_URL = bytes([48]) # SEND-URL
FORWARD_X = bytes([49]) # FORWARD_X
PRAGMA_LOGON = bytes([138]) # TELOPT PRAGMA LOGON
SSPI_LOGON = bytes([139]) # TELOPT SSPI LOGON
PRAGMA_HEARTBEAT = bytes([140]) # TELOPT PRAGMA HEARTBEAT
EXOPL = bytes([255]) # Extended-Options-List
NOOPT = bytes([0])
131

132 133 134 135 136 137 138 139 140

# poll/select have the advantage of not requiring any extra file descriptor,
# contrarily to epoll/kqueue (also, they require a single syscall).
if hasattr(selectors, 'PollSelector'):
    _TelnetSelector = selectors.PollSelector
else:
    _TelnetSelector = selectors.SelectSelector


141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
class Telnet:

    """Telnet interface class.

    An instance of this class represents a connection to a telnet
    server.  The instance is initially not connected; the open()
    method must be used to establish a connection.  Alternatively, the
    host name and optional port number can be passed to the
    constructor, too.

    Don't try to reopen an already connected instance.

    This class has many read_*() methods.  Note that some of them
    raise EOFError when the end of the connection is read, because
    they can return an empty string for other reasons.  See the
    individual doc strings.

    read_until(expected, [timeout])
        Read until the expected string has been seen, or a timeout is
160
        hit (default is no timeout); may block.
161 162 163 164 165 166 167 168 169

    read_all()
        Read all data until EOF; may block.

    read_some()
        Read at least one byte or EOF; may block.

    read_very_eager()
        Read all data available already queued or on the socket,
170
        without blocking.
171 172 173

    read_eager()
        Read either data already queued or some data available on the
174
        socket, without blocking.
175 176 177

    read_lazy()
        Read all data in the raw queue (processing it first), without
178
        doing any socket I/O.
179 180 181

    read_very_lazy()
        Reads all data in the cooked queue, without doing any socket
182
        I/O.
183

184 185 186
    read_sb_data()
        Reads available data between SB ... SE sequence. Don't block.

187 188 189
    set_option_negotiation_callback(callback)
        Each time a telnet option is read on the input flow, this callback
        (if set) is called with the following parameters :
190 191
        callback(telnet socket, command, option)
            option will be chr(0) when there is no option.
192 193
        No other action is done afterwards by telnetlib.

194 195
    """

Georg Brandl's avatar
Georg Brandl committed
196 197
    def __init__(self, host=None, port=0,
                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
198 199 200
        """Constructor.

        When called without arguments, create an unconnected instance.
Georg Brandl's avatar
Georg Brandl committed
201 202
        With a hostname argument, it connects the instance; port number
        and timeout are optional.
203 204 205 206
        """
        self.debuglevel = DEBUGLEVEL
        self.host = host
        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

Georg Brandl's avatar
Georg Brandl committed
220
    def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
221
        """Connect to a host.
222

223 224
        The optional second argument is the port number, which
        defaults to the standard telnet port (23).
225

226 227 228 229 230 231 232
        Don't try to reopen an already connected instance.
        """
        self.eof = 0
        if not port:
            port = TELNET_PORT
        self.host = host
        self.port = port
Georg Brandl's avatar
Georg Brandl committed
233 234
        self.timeout = timeout
        self.sock = socket.create_connection((host, port), timeout)
235 236

    def __del__(self):
237 238
        """Destructor -- close the connection."""
        self.close()
239 240

    def msg(self, msg, *args):
241
        """Print a debug message, when the debug level is > 0.
242

243 244
        If extra arguments are present, they are substituted in the
        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 266
        self.sock = None
        self.eof = True
267
        self.iacseq = b''
268
        self.sb = 0
269 270
        if sock:
            sock.close()
271 272

    def get_socket(self):
273 274
        """Return the socket object used internally."""
        return self.sock
275 276

    def fileno(self):
277 278
        """Return the fileno() of the socket object used internally."""
        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 294 295 296 297 298 299 300 301
        """Read until a given string is encountered or until timeout.

        When no match is found, return whatever is available instead,
        possibly the empty string.  Raise EOFError if the connection
        is closed and no cooked data is available.

        """
        n = len(match)
        self.process_rawq()
302
        i = self.cookedq.find(match)
303 304 305 306 307 308
        if i >= 0:
            i = i+n
            buf = self.cookedq[:i]
            self.cookedq = self.cookedq[i:]
            return buf
        if timeout is not None:
309
            deadline = _time() + timeout
310 311 312 313 314 315 316 317 318 319 320 321 322 323
        with _TelnetSelector() as selector:
            selector.register(self, selectors.EVENT_READ)
            while not self.eof:
                if selector.select(timeout):
                    i = max(0, len(self.cookedq)-n)
                    self.fill_rawq()
                    self.process_rawq()
                    i = self.cookedq.find(match, i)
                    if i >= 0:
                        i = i+n
                        buf = self.cookedq[:i]
                        self.cookedq = self.cookedq[i:]
                        return buf
                if timeout is not None:
324
                    timeout = deadline - _time()
325 326
                    if timeout < 0:
                        break
327
        return self.read_very_lazy()
328 329

    def read_all(self):
330 331 332 333 334 335
        """Read all data until EOF; block until connection closed."""
        self.process_rawq()
        while not self.eof:
            self.fill_rawq()
            self.process_rawq()
        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 347 348 349 350
        """
        self.process_rawq()
        while not self.cookedq and not self.eof:
            self.fill_rawq()
            self.process_rawq()
        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).
Tim Peters's avatar
Tim Peters committed
356

357
        Raise EOFError if connection closed and no cooked data
358
        available.  Return b'' if no cooked data available otherwise.
359 360 361 362 363 364 365 366
        Don't block unless in the midst of an IAC sequence.

        """
        self.process_rawq()
        while not self.eof and self.sock_avail():
            self.fill_rawq()
            self.process_rawq()
        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 377 378 379 380
        """
        self.process_rawq()
        while not self.cookedq and not self.eof and self.sock_avail():
            self.fill_rawq()
            self.process_rawq()
        return self.read_very_lazy()
381 382

    def read_lazy(self):
383
        """Process and return data that's already in the queues (lazy).
Tim Peters's avatar
Tim Peters committed
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 391
        """
        self.process_rawq()
        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
Tim Peters's avatar
Tim Peters committed
405

406 407 408
    def read_sb_data(self):
        """Return any data available in the SB ... SE queue.

409
        Return b'' if no SB ... SE available. Should only be called
Tim Peters's avatar
Tim Peters committed
410
        after seeing a SB or SE command. When a new SB command is
411 412 413 414
        found, old unread SB data will be discarded. Don't block.

        """
        buf = self.sbdataq
415
        self.sbdataq = b''
416
        return buf
417

418 419 420 421
    def set_option_negotiation_callback(self, callback):
        """Provide a callback function called after each receipt of a telnet option."""
        self.option_callback = callback

422
    def process_rawq(self):
423 424 425 426 427 428
        """Transfer from raw queue to cooked queue.

        Set self.eof when connection is closed.  Don't block unless in
        the midst of an IAC sequence.

        """
429
        buf = [b'', b'']
430 431 432
        try:
            while self.rawq:
                c = self.rawq_getchar()
433 434 435
                if not self.iacseq:
                    if c == theNULL:
                        continue
436
                    if c == b"\021":
437 438 439 440
                        continue
                    if c != IAC:
                        buf[self.sb] = buf[self.sb] + c
                        continue
441
                    else:
442 443
                        self.iacseq += c
                elif len(self.iacseq) == 1:
444
                    # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
445 446 447
                    if c in (DO, DONT, WILL, WONT):
                        self.iacseq += c
                        continue
Tim Peters's avatar
Tim Peters committed
448

449
                    self.iacseq = b''
450 451
                    if c == IAC:
                        buf[self.sb] = buf[self.sb] + c
452
                    else:
453 454
                        if c == SB: # SB ... SE start.
                            self.sb = 1
455
                            self.sbdataq = b''
456 457 458
                        elif c == SE:
                            self.sb = 0
                            self.sbdataq = self.sbdataq + buf[1]
459
                            buf[1] = b''
460 461 462 463 464 465 466 467 468 469
                        if self.option_callback:
                            # Callback is supposed to look into
                            # the sbdataq
                            self.option_callback(self.sock, c, NOOPT)
                        else:
                            # We can't offer automatic processing of
                            # suboptions. Alas, we should not get any
                            # unless we did a WILL/DO before.
                            self.msg('IAC %d not recognized' % ord(c))
                elif len(self.iacseq) == 2:
470
                    cmd = self.iacseq[1:2]
471
                    self.iacseq = b''
472 473
                    opt = c
                    if cmd in (DO, DONT):
Tim Peters's avatar
Tim Peters committed
474
                        self.msg('IAC %s %d',
475 476 477 478 479 480 481 482 483 484 485 486
                            cmd == DO and 'DO' or 'DONT', ord(opt))
                        if self.option_callback:
                            self.option_callback(self.sock, cmd, opt)
                        else:
                            self.sock.sendall(IAC + WONT + opt)
                    elif cmd in (WILL, WONT):
                        self.msg('IAC %s %d',
                            cmd == WILL and 'WILL' or 'WONT', ord(opt))
                        if self.option_callback:
                            self.option_callback(self.sock, cmd, opt)
                        else:
                            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 492
        self.cookedq = self.cookedq + buf[0]
        self.sbdataq = self.sbdataq + buf[1]
493 494

    def rawq_getchar(self):
495 496 497 498 499 500 501 502 503 504
        """Get next char from raw queue.

        Block if no data is immediately available.  Raise EOFError
        when connection is closed.

        """
        if not self.rawq:
            self.fill_rawq()
            if self.eof:
                raise EOFError
505
        c = self.rawq[self.irawq:self.irawq+1]
506 507
        self.irawq = self.irawq + 1
        if self.irawq >= len(self.rawq):
508
            self.rawq = b''
509 510
            self.irawq = 0
        return c
511 512

    def fill_rawq(self):
513 514 515 516 517 518 519
        """Fill raw queue from exactly one recv() system call.

        Block if no data is immediately available.  Set self.eof when
        connection is closed.

        """
        if self.irawq >= len(self.rawq):
520
            self.rawq = b''
521 522 523 524
            self.irawq = 0
        # The buffer size should be fairly small so as to avoid quadratic
        # behavior in process_rawq() above
        buf = self.sock.recv(50)
525
        self.msg("recv %r", buf)
526 527
        self.eof = (not buf)
        self.rawq = self.rawq + buf
528 529

    def sock_avail(self):
530
        """Test whether data is available on the socket."""
531 532 533
        with _TelnetSelector() as selector:
            selector.register(self, selectors.EVENT_READ)
            return bool(selector.select(0))
534 535

    def interact(self):
536
        """Interaction function, emulates a very dumb telnet client."""
537 538 539
        if sys.platform == "win32":
            self.mt_interact()
            return
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
        with _TelnetSelector() as selector:
            selector.register(self, selectors.EVENT_READ)
            selector.register(sys.stdin, selectors.EVENT_READ)

            while True:
                for key, events in selector.select():
                    if key.fileobj is self:
                        try:
                            text = self.read_eager()
                        except EOFError:
                            print('*** Connection closed by remote host ***')
                            return
                        if text:
                            sys.stdout.write(text.decode('ascii'))
                            sys.stdout.flush()
                    elif key.fileobj is sys.stdin:
                        line = sys.stdin.readline().encode('ascii')
                        if not line:
                            return
                        self.write(line)
560

561 562
    def mt_interact(self):
        """Multithreaded version of interact()."""
563 564
        import _thread
        _thread.start_new_thread(self.listener, ())
565 566 567 568
        while 1:
            line = sys.stdin.readline()
            if not line:
                break
569
            self.write(line.encode('ascii'))
570 571 572 573 574 575 576

    def listener(self):
        """Helper for mt_interact() -- this executes in the other thread."""
        while 1:
            try:
                data = self.read_eager()
            except EOFError:
577
                print('*** Connection closed by remote host ***')
578 579
                return
            if data:
580
                sys.stdout.write(data.decode('ascii'))
581 582 583
            else:
                sys.stdout.flush()

584
    def expect(self, list, timeout=None):
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
        """Read until one from a list of a regular expressions matches.

        The first argument is a list of regular expressions, either
        compiled (re.RegexObject instances) or uncompiled (strings).
        The optional second argument is a timeout, in seconds; default
        is no timeout.

        Return a tuple of three items: the index in the list of the
        first regular expression that matches; the match object
        returned; and the text read up till and including the match.

        If EOF is read and no text was read, raise EOFError.
        Otherwise, when nothing matches, return (-1, None, text) where
        text is the text received so far (may be the empty string if a
        timeout happened).

        If a regular expression ends with a greedy match (e.g. '.*')
        or if more than one expression can match the same input, the
        results are undeterministic, and may depend on the I/O timing.

        """
        re = None
        list = list[:]
        indices = range(len(list))
        for i in indices:
            if not hasattr(list[i], "search"):
                if not re: import re
                list[i] = re.compile(list[i])
613
        if timeout is not None:
614
            deadline = _time() + timeout
615 616 617 618 619 620 621 622 623 624 625 626 627
        with _TelnetSelector() as selector:
            selector.register(self, selectors.EVENT_READ)
            while not self.eof:
                self.process_rawq()
                for i in indices:
                    m = list[i].search(self.cookedq)
                    if m:
                        e = m.end()
                        text = self.cookedq[:e]
                        self.cookedq = self.cookedq[e:]
                        return (i, m, text)
                if timeout is not None:
                    ready = selector.select(timeout)
628
                    timeout = deadline - _time()
629 630 631 632 633 634
                    if not ready:
                        if timeout < 0:
                            break
                        else:
                            continue
                self.fill_rawq()
635 636 637 638
        text = self.read_very_lazy()
        if not text and self.eof:
            raise EOFError
        return (-1, None, text)
639 640 641 642 643 644 645 646 647 648 649 650


def test():
    """Test program for telnetlib.

    Usage: python telnetlib.py [-d] ... [host [port]]

    Default host is localhost; default port is 23.

    """
    debuglevel = 0
    while sys.argv[1:] and sys.argv[1] == '-d':
651 652
        debuglevel = debuglevel+1
        del sys.argv[1]
653 654
    host = 'localhost'
    if sys.argv[1:]:
655
        host = sys.argv[1]
656 657
    port = 0
    if sys.argv[2:]:
658 659 660 661 662
        portstr = sys.argv[2]
        try:
            port = int(portstr)
        except ValueError:
            port = socket.getservbyname(portstr, 'tcp')
663 664
    tn = Telnet()
    tn.set_debuglevel(debuglevel)
665
    tn.open(host, port, timeout=0.5)
666 667 668 669 670
    tn.interact()
    tn.close()

if __name__ == '__main__':
    test()