Recipe15.9.Performing Remote Logins Using telnetlib


Recipe 15.9. Performing Remote Logins Using telnetlib

Credit: Jeff Bauer

Problem

You need to send commands to one or more logins that can be on a local machine, or a remote machine, and the Telnet protocol is acceptable.

Solution

Telnet is one of the oldest protocols in the TCP/IP stack, but it may still be serviceable (at least within an intranet that is well protected against sniffing and spoofing attacks). In any case, Python's standard module telnetlib supports Telnet quite well:

# auto_telnet.py - remote control via telnet import os, sys, telnetlib from getpass import getpass class AutoTelnet(object):     def _ _init_ _(self, user_list, cmd_list, **kw):         # optional parameters are host, timeout in seconds, command         # prompt to expect from the host on successful logins:         self.host = kw.get('host', 'localhost')         self.timeout = kw.get('timeout', 600)         self.command_prompt = kw.get('command_prompt', "$ ")         # collect passwords for each user, interactively         self.passwd = {  }         for user in user_list:             self.passwd[user] = getpass("Enter user '%s' password: " % user)         # instantiate Telnet proxy         self.telnet = telnetlib.Telnet( )         for user in user_list:             # login with given host and user, and act appropriately             self.telnet.open(self.host)             ok = self.action(user, cmd_list)             if not ok:                 print "Unable to process:", user             self.telnet.close( )     def action(self, user, cmd_list):         # wait for a login prompt         t = self.telnet         t.write("\n")         login_prompt = "login: "         response = t.read_until(login_prompt, 5)         if login_prompt in response:             print response         else:             return 0         # supply user and password for login         t.write("%s\n" % user)         password_prompt = "Password:"         response = t.read_until(password_prompt, 3)         if password_prompt in response:             print response         else:             return 0         t.write("%s\n" % self.passwd[user])         # wait for command prompt to indicate successful login         response = t.read_until(self.command_prompt, 5)         if self.command_prompt not in response:             return 0         # send each command and wait for command prompt after each         for cmd in cmd_list:             t.write("%s\n" % cmd)             response = t.read_until(self.command_prompt, self.timeout)             if self.command_prompt not in response:                 return 0             print response         return 1 if _ _name_ _ == '_ _main_ _':     # code which runs as a main script, only     basename = os.path.splitext(os.path.basename(sys.argv[0]))[0]     logname = os.environ.get("LOGNAME", os.environ.get("USERNAME"))     host = 'localhost'     import getopt     optlist, user_list = getopt.getopt(sys.argv[1:], 'c:f:h:')     usage = """ usage: %s [-h host] [-f cmdfile] [-c "command"] user1 user2 ...     -c  command     -f  command file     -h  host  (default: '%s') Example:  %s -c "echo $HOME" %s """ % (basename, host, basename, logname)     if len(sys.argv) < 2:         print usage         sys.exit(1)     cmd_list = [  ]     for opt, optarg in optlist:         if opt == '-f':             for r in open(optarg):                 if r.rstrip( ):                     cmd_list.append(r)         elif opt == '-c':             command = optarg             if command[0] == '"' and command[-1] == '"':                 command = command[1:-1]             cmd_list.append(command)         elif opt == '-h':             host = optarg     autoTelnet = AutoTelnet(user_list, cmd_list, host=host)

Discussion

Python's telnetlib lets you easily automate access to Telnet servers, even from non-Unix machines. As a flexible alternative to the popen functions, which only run commands locally as the user that's running the script, telnetlib, which can work across an intranet and can login and run commands as different users, is a handy technique to have in your system administration toolbox.

Production code generally has to be made more robust, but this recipe should be enough to get you started in the right direction. The recipe's AutoTelnet class instantiates a single telnetlib.Telnet object and uses that single object in a loop over a list of users. For each user, the recipe calls the open method of the Telnet instance to open the connection to the specified host, runs a series of commands in AutoTelnet's action method, and finally calls the close method of the Telnet instance to terminate the connection.

AutoTelnet's action method is where the action is. All operations depend on two methods of the Telnet instance. The write method takes a single string argument and writes it to the connection. The read_until method takes two arguments, a string to wait for and a timeout in seconds, and returns a string with all the characters received from the connection until the timeout elapsed or the waited-for string occurred. action's code uses these two methods to wait for a login prompt and send the username; wait for a password prompt and send the password; and then, repeatedly, wait for a command prompt (typically from a Unix shell at the other end of the connection) and send the commands in the list sequentially (waiting for a command prompt again after sending each one).

One warning (which applies to any use of Telnet and some other old protocols): except when transmitting completely public data, not protected by passwords that might be of interest to intruders of ill will, do not run Telnet (or non-anonymous FTP, for that matter) on networks on which you are not completely sure that nobody is packet-sniffing, since these protocols date from an older, more trusting age. These protocols let passwords and everything else travel in the clear, open to any snooper. This issue is not Python specific; it applies to any implementation of these protocols, since it depends on the definition of the protocols themselves. Whether or not you use Python, be advised: if there is any risk that someone might be packet-sniffing, use SSH instead, as shown next in Recipe 15.10 so that no password ever travels on the network in the clear, and so that the connection stream itself gets encrypted.

See Also

Documentation on the standard library module telnetlib in the Library Reference; Recipe 15.10.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net