13.7 Performing Remote Logins Using telnetlib
Credit: Jeff Bauer
13.7.1 Problem
You need to send commands to one or
more logins that can be on the local machine or on a remote machine,
and the Telnet protocol is acceptable.
13.7.2 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, string, telnetlib
from getpass import getpass
class AutoTelnet:
def _ _init_ _(self, user_list, cmd_list, **kw):
self.host = kw.get('host', 'localhost')
self.timeout = kw.get('timeout', 600)
self.command_prompt = kw.get('command_prompt', "$ ")
self.passwd = {}
for user in user_list:
self.passwd[user] = getpass("Enter user '%s' password: " % user)
self.telnet = telnetlib.Telnet( )
for user in user_list:
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):
t = self.telnet
t.write("\n")
login_prompt = "login: "
response = t.read_until(login_prompt, 5)
if string.count(response, login_prompt):
print response
else:
return 0
t.write("%s\n" % user)
password_prompt = "Password:"
response = t.read_until(password_prompt, 3)
if string.count(response, password_prompt):
print response
else:
return 0
t.write("%s\n" % self.passwd[user])
response = t.read_until(self.command_prompt, 5)
if not string.count(response, self.command_prompt):
return 0
for cmd in cmd_list:
t.write("%s\n" % cmd)
response = t.read_until(self.command_prompt, self.timeout)
if not string.count(response, self.command_prompt):
return 0
print response
return 1
if _ _name_ _ == '_ _main_ _':
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).readlines( ):
if string.rstrip(r):
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)
13.7.3 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, telnetlib is a handy technique to have
in your system-administration toolbox.
Generally, production code will be 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 that it uses in a loop
over a list of users. For each user, it 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
t.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, 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.
One warning (which applies to
Telnet and other old protocols): except, perhaps, for the
transmission of completely public data not protected by a password
that might be of interest to intruders of ill will, do not run Telnet
(or nonanonymous FTP) on networks on which you are not completely
sure that nobody is packet-sniffing, since these protocols date from
an older, more trusting age. They let passwords, and everything else,
travel in the clear, open to any snooper. This is not
Python-specific. Whether you use Python or not, be advised: if there
is any risk that somebody might be packet-sniffing, use
ssh instead, so no password travels on the
network in the clear, and the connection stream itself is encrypted.
13.7.4 See Also
Documentation on the standard library module
telnetlib in the Library
Reference.
|