Python
  Home arrow Python arrow Page 5 - SSH with Twisted
Dev Shed Forums 
Administration  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Forums Sitemap 
IBM® developerWorks 
Dedicated Servers 
E-Commerce Hosting 
Linux Web Hosting 
Managed Hosting 
Small Business Hosting 
Download TestComplete 
VPS Hosting 
Weekly Newsletter

 
Developer Updates  
Free Website Content 
eWeek
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PYTHON

SSH with Twisted
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 2
    2008-03-06

    Table of Contents:
  • SSH with Twisted
  • Setting Up a Custom SSH Server continued
  • Using Public Keys for Authentication
  • Providing an Administrative Python Shell
  • Running Commands on a Remote Server

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
     
    ADVERTISEMENT

    Route your faxes to your email inbox. Private, secure fax numbers available from CallWave. Choose your fax number.

    SSH with Twisted - Running Commands on a Remote Server
    (Page 5 of 5 )

    This lab demonstrates how to write an SSH client. You can use twisted.conch to communicate with a server using SSH: logging in, executing commands, and
    capturing the output.

    How Do I Do That?

    There are several classes that work together to make up a twisted.conch.ssh SSH client. The transport.SSHClientTransportclass sets up the connection and verifies the identity of the server. Theuserauth.SSHUserAuthClientlogs in using your authentication credentials. Theconnection.SSHConnectionclass takes over once you’ve logged in, and creates one or morechannel.SSHChannelobjects, which you then use to communicate with the server over a secure channel. Example 10-4 shows how you can use these classes to make an SSH client that logs into a server, runs a command, and prints the output.

    Example 10-4. sshclient.py

    from twisted.conch import error
    from twisted.conch.ssh import transport, connection, keys, userauth, channel, common from twisted.internet import defer, protocol, reactor

    class ClientCommandTransport(transport.SSHClientTransport):
       
    def __init__(self, username, password, command):
            self.username = username
            self.password = password  
            self.command = command

        def verifyHostKey(self, pubKey, fingerprint):
            # in a real app, you should verify that the fingerprint matches
            # the one you expected to get from this server
            return defer.succeed(True)

        def connectionSecure(self):
            self.requestService(
                PasswordAuth(self.username, self.password,
                             ClientConnection(self.command)))

    class PasswordAuth(userauth.SSHUserAuthClient):
       
    def __init__(self, user, password, connection):
            userauth.SSHUserAuthClient.__init__(self, user, connection)
            self.password = password

        def getPassword(self, prompt=None):
            return defer.succeed(self.password)

    class ClientConnection(connection.SSHConnection):
       
    def __init__(self, cmd, *args, **kwargs):
            connection.SSHConnection.__init__(self)
            self.command = cmd

        def serviceStarted(self):
            self.openChannel(CommandChannel(self.command, conn=self))

    class CommandChannel(channel.SSHChannel):
        name = 'session'

        def __init__(self, command, *args, **kwargs):
            channel.SSHChannel.__init__(self, *args, **kwargs)
            self.command = command

        def channelOpen(self, data):
           
    self.conn.sendRequest(
                self, 'exec', common.NS(self.command), wantReply=True).addCallback(
                self._gotResponse)

        def _gotResponse(self, _):
            self.conn.sendEOF(self)

        def dataReceived(self, data):
            print data

        def closed(self):
            reactor.stop()

    class ClientCommandFactory(protocol.ClientFactory):
       
    def __init__(self, username, password, command):
            self.username = username
            self.password = password
            self.command = command

        def buildProtocol(self, addr):
            protocol = ClientCommandTransport(
                self.username, self.password, self.command)
            return protocol

    if __name__ == "__main__":
        import sys, getpass
        server = sys.argv[1]
        command = sys.argv[2]
        username = raw_input("Username: ")
        password = getpass.getpass("Password: ")
        factory = ClientCommandFactory(username, password, command)
        reactor.connectTCP(server, 22, factory)
        reactor.run()

    Run sshclient.py with two arguments: a hostname and a command. It will ask for your username and password, log into the server, execute the command, and print the output. For example, you could run the who command to get a list of who’s currently logged in to the server:

      $ python sshclient.py myserver.example.com who
     
    Username: abe
     
    Password: password

      root     pts/0       Jun 11 21:35 (192.168.0.13)
      phil     pts/2       Jun 22 13:58 (192.168.0.1)
      phil     pts/3       Jun 22 13:58 (192.168.0.1)

    How Does That Work?

    The ClientCommandTransport in Example 10-4 handles the initial connection to the SSH server. Its verifyHostKey method checks to make sure the server’s public key matches your expectations. Typically, you’d remember each server the first time you connected, and then check on subsequent connections to make sure that another server wasn’t maliciously trying to pass itself off as the server you expected. Here, it just returns a True value without bothering to check the key. The connectionSecure method is called as soon as the initial encrypted connection has been established. This is the appropriate time to send your login credentials, by passing a
    userauth.SSHUserAuthClient to self.requestService, along with a connection.SSHConnection object that should manage the connection after authentication succeeds.

    ThePasswordAuthinherits fromuserauth.SSHUserAuthClient. It has to implement only a single method,getPassword, which returns the password it will use to log in. If you wanted to use public key authentication, you’d implement the methodsgetPublicKeyandgetPrivateKeyinstead, returning the appropriate key as a string in each case.

    TheClientConnectionclass in Example 10-4 will have itsserviceStartedmethod called as soon as the client has successfully logged in. It callsself.openChannelwith aCommandChannel object, which is a subclass ofchannel.SSHChannel. This object is used to work with an authenticated channel to the SSH server. ItschannelOpenmethod is called when the channel is ready. At this point, you can callself.conn.sendRequestto send a command to the server. You have to encode data sent over SSH as a specially formatted network string; to get a string in this format, pass it to thetwisted.conch.common.NSfunction. Set the keyword argumentwantReplytoTrueif you’re interested in getting a response from the command; this setting will causesendRequestto return aDeferredthat will be called back when the command is completed. (If you don’t setwantReplytoTrue,sendRequestwill returnNone.) As data is received from the server, it will be passed todataReceived. Once you’re done using the channel, close it by callingself.conn.sendEOF. Theclosed method will be called to let you know when the channel has been successfully closed.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · This article is an excerpt from the book "Twisted Network Programming Essentials,"...
     

    Buy this book now. This article is excerpted from chapter 10 of the book Twisted Network Programming Essentials, written by Abe Fettig (O'Reilly, 2007; ISBN: 0596100329). Check it out today at your favorite bookstore. Buy this book now.

       

    PYTHON ARTICLES

    - SSH with Twisted
    - Mobile Programming in Python using PyS60: UI...
    - Python: Count on It
    - Python Strings: Spinning Yarns
    - Python: More Fun with Strings
    - Python: Stringing You Along
    - Python Operators
    - Bluetooth Programming in Python: Network Pro...
    - Python Sets
    - Python Conditionals, Lists, Dictionaries, an...
    - Python: Input and Variables
    - Introduction to Python Programming
    - Mobile Programming in Python using PyS60: Ge...
    - Bluetooth Programming using Python
    - Finishing the PyMailGUI Client: User Help To...




    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 2 hosted by Hostway