• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         sys.audit("telnetlib.Telnet.open", self, host, port)
235         self.sock = socket.create_connection((host, port), timeout)
236 
237     def __del__(self):
238         """Destructor -- close the connection."""
239         self.close()
240 
241     def msg(self, msg, *args):
242         """Print a debug message, when the debug level is > 0.
243 
244         If extra arguments are present, they are substituted in the
245         message using the standard string formatting operator.
246 
247         """
248         if self.debuglevel > 0:
249             print('Telnet(%s,%s):' % (self.host, self.port), end=' ')
250             if args:
251                 print(msg % args)
252             else:
253                 print(msg)
254 
255     def set_debuglevel(self, debuglevel):
256         """Set the debug level.
257 
258         The higher it is, the more debug output you get (on sys.stdout).
259 
260         """
261         self.debuglevel = debuglevel
262 
263     def close(self):
264         """Close the connection."""
265         sock = self.sock
266         self.sock = None
267         self.eof = True
268         self.iacseq = b''
269         self.sb = 0
270         if sock:
271             sock.close()
272 
273     def get_socket(self):
274         """Return the socket object used internally."""
275         return self.sock
276 
277     def fileno(self):
278         """Return the fileno() of the socket object used internally."""
279         return self.sock.fileno()
280 
281     def write(self, buffer):
282         """Write a string to the socket, doubling any IAC characters.
283 
284         Can block if the connection is blocked.  May raise
285         OSError if the connection is closed.
286 
287         """
288         if IAC in buffer:
289             buffer = buffer.replace(IAC, IAC+IAC)
290         sys.audit("telnetlib.Telnet.write", self, buffer)
291         self.msg("send %r", buffer)
292         self.sock.sendall(buffer)
293 
294     def read_until(self, match, timeout=None):
295         """Read until a given string is encountered or until timeout.
296 
297         When no match is found, return whatever is available instead,
298         possibly the empty string.  Raise EOFError if the connection
299         is closed and no cooked data is available.
300 
301         """
302         n = len(match)
303         self.process_rawq()
304         i = self.cookedq.find(match)
305         if i >= 0:
306             i = i+n
307             buf = self.cookedq[:i]
308             self.cookedq = self.cookedq[i:]
309             return buf
310         if timeout is not None:
311             deadline = _time() + timeout
312         with _TelnetSelector() as selector:
313             selector.register(self, selectors.EVENT_READ)
314             while not self.eof:
315                 if selector.select(timeout):
316                     i = max(0, len(self.cookedq)-n)
317                     self.fill_rawq()
318                     self.process_rawq()
319                     i = self.cookedq.find(match, i)
320                     if i >= 0:
321                         i = i+n
322                         buf = self.cookedq[:i]
323                         self.cookedq = self.cookedq[i:]
324                         return buf
325                 if timeout is not None:
326                     timeout = deadline - _time()
327                     if timeout < 0:
328                         break
329         return self.read_very_lazy()
330 
331     def read_all(self):
332         """Read all data until EOF; block until connection closed."""
333         self.process_rawq()
334         while not self.eof:
335             self.fill_rawq()
336             self.process_rawq()
337         buf = self.cookedq
338         self.cookedq = b''
339         return buf
340 
341     def read_some(self):
342         """Read at least one byte of cooked data unless EOF is hit.
343 
344         Return b'' if EOF is hit.  Block if no data is immediately
345         available.
346 
347         """
348         self.process_rawq()
349         while not self.cookedq and not self.eof:
350             self.fill_rawq()
351             self.process_rawq()
352         buf = self.cookedq
353         self.cookedq = b''
354         return buf
355 
356     def read_very_eager(self):
357         """Read everything that's possible without blocking in I/O (eager).
358 
359         Raise EOFError if connection closed and no cooked data
360         available.  Return b'' if no cooked data available otherwise.
361         Don't block unless in the midst of an IAC sequence.
362 
363         """
364         self.process_rawq()
365         while not self.eof and self.sock_avail():
366             self.fill_rawq()
367             self.process_rawq()
368         return self.read_very_lazy()
369 
370     def read_eager(self):
371         """Read readily available data.
372 
373         Raise EOFError if connection closed and no cooked data
374         available.  Return b'' if no cooked data available otherwise.
375         Don't block unless in the midst of an IAC sequence.
376 
377         """
378         self.process_rawq()
379         while not self.cookedq and not self.eof and self.sock_avail():
380             self.fill_rawq()
381             self.process_rawq()
382         return self.read_very_lazy()
383 
384     def read_lazy(self):
385         """Process and return data that's already in the queues (lazy).
386 
387         Raise EOFError if connection closed and no data available.
388         Return b'' if no cooked data available otherwise.  Don't block
389         unless in the midst of an IAC sequence.
390 
391         """
392         self.process_rawq()
393         return self.read_very_lazy()
394 
395     def read_very_lazy(self):
396         """Return any data available in the cooked queue (very lazy).
397 
398         Raise EOFError if connection closed and no data available.
399         Return b'' if no cooked data available otherwise.  Don't block.
400 
401         """
402         buf = self.cookedq
403         self.cookedq = b''
404         if not buf and self.eof and not self.rawq:
405             raise EOFError('telnet connection closed')
406         return buf
407 
408     def read_sb_data(self):
409         """Return any data available in the SB ... SE queue.
410 
411         Return b'' if no SB ... SE available. Should only be called
412         after seeing a SB or SE command. When a new SB command is
413         found, old unread SB data will be discarded. Don't block.
414 
415         """
416         buf = self.sbdataq
417         self.sbdataq = b''
418         return buf
419 
420     def set_option_negotiation_callback(self, callback):
421         """Provide a callback function called after each receipt of a telnet option."""
422         self.option_callback = callback
423 
424     def process_rawq(self):
425         """Transfer from raw queue to cooked queue.
426 
427         Set self.eof when connection is closed.  Don't block unless in
428         the midst of an IAC sequence.
429 
430         """
431         buf = [b'', b'']
432         try:
433             while self.rawq:
434                 c = self.rawq_getchar()
435                 if not self.iacseq:
436                     if c == theNULL:
437                         continue
438                     if c == b"\021":
439                         continue
440                     if c != IAC:
441                         buf[self.sb] = buf[self.sb] + c
442                         continue
443                     else:
444                         self.iacseq += c
445                 elif len(self.iacseq) == 1:
446                     # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
447                     if c in (DO, DONT, WILL, WONT):
448                         self.iacseq += c
449                         continue
450 
451                     self.iacseq = b''
452                     if c == IAC:
453                         buf[self.sb] = buf[self.sb] + c
454                     else:
455                         if c == SB: # SB ... SE start.
456                             self.sb = 1
457                             self.sbdataq = b''
458                         elif c == SE:
459                             self.sb = 0
460                             self.sbdataq = self.sbdataq + buf[1]
461                             buf[1] = b''
462                         if self.option_callback:
463                             # Callback is supposed to look into
464                             # the sbdataq
465                             self.option_callback(self.sock, c, NOOPT)
466                         else:
467                             # We can't offer automatic processing of
468                             # suboptions. Alas, we should not get any
469                             # unless we did a WILL/DO before.
470                             self.msg('IAC %d not recognized' % ord(c))
471                 elif len(self.iacseq) == 2:
472                     cmd = self.iacseq[1:2]
473                     self.iacseq = b''
474                     opt = c
475                     if cmd in (DO, DONT):
476                         self.msg('IAC %s %d',
477                             cmd == DO and 'DO' or 'DONT', ord(opt))
478                         if self.option_callback:
479                             self.option_callback(self.sock, cmd, opt)
480                         else:
481                             self.sock.sendall(IAC + WONT + opt)
482                     elif cmd in (WILL, WONT):
483                         self.msg('IAC %s %d',
484                             cmd == WILL and 'WILL' or 'WONT', ord(opt))
485                         if self.option_callback:
486                             self.option_callback(self.sock, cmd, opt)
487                         else:
488                             self.sock.sendall(IAC + DONT + opt)
489         except EOFError: # raised by self.rawq_getchar()
490             self.iacseq = b'' # Reset on EOF
491             self.sb = 0
492             pass
493         self.cookedq = self.cookedq + buf[0]
494         self.sbdataq = self.sbdataq + buf[1]
495 
496     def rawq_getchar(self):
497         """Get next char from raw queue.
498 
499         Block if no data is immediately available.  Raise EOFError
500         when connection is closed.
501 
502         """
503         if not self.rawq:
504             self.fill_rawq()
505             if self.eof:
506                 raise EOFError
507         c = self.rawq[self.irawq:self.irawq+1]
508         self.irawq = self.irawq + 1
509         if self.irawq >= len(self.rawq):
510             self.rawq = b''
511             self.irawq = 0
512         return c
513 
514     def fill_rawq(self):
515         """Fill raw queue from exactly one recv() system call.
516 
517         Block if no data is immediately available.  Set self.eof when
518         connection is closed.
519 
520         """
521         if self.irawq >= len(self.rawq):
522             self.rawq = b''
523             self.irawq = 0
524         # The buffer size should be fairly small so as to avoid quadratic
525         # behavior in process_rawq() above
526         buf = self.sock.recv(50)
527         self.msg("recv %r", buf)
528         self.eof = (not buf)
529         self.rawq = self.rawq + buf
530 
531     def sock_avail(self):
532         """Test whether data is available on the socket."""
533         with _TelnetSelector() as selector:
534             selector.register(self, selectors.EVENT_READ)
535             return bool(selector.select(0))
536 
537     def interact(self):
538         """Interaction function, emulates a very dumb telnet client."""
539         if sys.platform == "win32":
540             self.mt_interact()
541             return
542         with _TelnetSelector() as selector:
543             selector.register(self, selectors.EVENT_READ)
544             selector.register(sys.stdin, selectors.EVENT_READ)
545 
546             while True:
547                 for key, events in selector.select():
548                     if key.fileobj is self:
549                         try:
550                             text = self.read_eager()
551                         except EOFError:
552                             print('*** Connection closed by remote host ***')
553                             return
554                         if text:
555                             sys.stdout.write(text.decode('ascii'))
556                             sys.stdout.flush()
557                     elif key.fileobj is sys.stdin:
558                         line = sys.stdin.readline().encode('ascii')
559                         if not line:
560                             return
561                         self.write(line)
562 
563     def mt_interact(self):
564         """Multithreaded version of interact()."""
565         import _thread
566         _thread.start_new_thread(self.listener, ())
567         while 1:
568             line = sys.stdin.readline()
569             if not line:
570                 break
571             self.write(line.encode('ascii'))
572 
573     def listener(self):
574         """Helper for mt_interact() -- this executes in the other thread."""
575         while 1:
576             try:
577                 data = self.read_eager()
578             except EOFError:
579                 print('*** Connection closed by remote host ***')
580                 return
581             if data:
582                 sys.stdout.write(data.decode('ascii'))
583             else:
584                 sys.stdout.flush()
585 
586     def expect(self, list, timeout=None):
587         """Read until one from a list of a regular expressions matches.
588 
589         The first argument is a list of regular expressions, either
590         compiled (re.Pattern instances) or uncompiled (strings).
591         The optional second argument is a timeout, in seconds; default
592         is no timeout.
593 
594         Return a tuple of three items: the index in the list of the
595         first regular expression that matches; the re.Match object
596         returned; and the text read up till and including the match.
597 
598         If EOF is read and no text was read, raise EOFError.
599         Otherwise, when nothing matches, return (-1, None, text) where
600         text is the text received so far (may be the empty string if a
601         timeout happened).
602 
603         If a regular expression ends with a greedy match (e.g. '.*')
604         or if more than one expression can match the same input, the
605         results are undeterministic, and may depend on the I/O timing.
606 
607         """
608         re = None
609         list = list[:]
610         indices = range(len(list))
611         for i in indices:
612             if not hasattr(list[i], "search"):
613                 if not re: import re
614                 list[i] = re.compile(list[i])
615         if timeout is not None:
616             deadline = _time() + timeout
617         with _TelnetSelector() as selector:
618             selector.register(self, selectors.EVENT_READ)
619             while not self.eof:
620                 self.process_rawq()
621                 for i in indices:
622                     m = list[i].search(self.cookedq)
623                     if m:
624                         e = m.end()
625                         text = self.cookedq[:e]
626                         self.cookedq = self.cookedq[e:]
627                         return (i, m, text)
628                 if timeout is not None:
629                     ready = selector.select(timeout)
630                     timeout = deadline - _time()
631                     if not ready:
632                         if timeout < 0:
633                             break
634                         else:
635                             continue
636                 self.fill_rawq()
637         text = self.read_very_lazy()
638         if not text and self.eof:
639             raise EOFError
640         return (-1, None, text)
641 
642     def __enter__(self):
643         return self
644 
645     def __exit__(self, type, value, traceback):
646         self.close()
647 
648 
649 def test():
650     """Test program for telnetlib.
651 
652     Usage: python telnetlib.py [-d] ... [host [port]]
653 
654     Default host is localhost; default port is 23.
655 
656     """
657     debuglevel = 0
658     while sys.argv[1:] and sys.argv[1] == '-d':
659         debuglevel = debuglevel+1
660         del sys.argv[1]
661     host = 'localhost'
662     if sys.argv[1:]:
663         host = sys.argv[1]
664     port = 0
665     if sys.argv[2:]:
666         portstr = sys.argv[2]
667         try:
668             port = int(portstr)
669         except ValueError:
670             port = socket.getservbyname(portstr, 'tcp')
671     with Telnet() as tn:
672         tn.set_debuglevel(debuglevel)
673         tn.open(host, port, timeout=0.5)
674         tn.interact()
675 
676 if __name__ == '__main__':
677     test()
678