[Twisted-Python] question about twisted conch (SSH) and wxPython
Hi Guys, Im trying to make a psudo SSH client GUI, but it seems that I although I can 'ls' to a remote machine using twisted.conch, I cant `ls -al`. Also I cant seem to to ssh commands that have spaces in them. Although Im using a windows environment to SSH, i dont think that is the problem. Here is a snippet of my code. Obviously I've already called reactor.run() and included appropriate modules and variables. I dont understand why ls works and ls -al doesnt. Also I was wondering if there are any existing command line SSH clients written with twisted similar to putty, but written in python. Thanks! class SimpleTransport(transport.SSHClientTransport): def verifyHostKey(self, hostKey, fingerprint): print 'host key fingerprint: %s' % fingerprint return defer.succeed(1) def connectionSecure(self): self.requestService( SimpleUserAuth(USER, SimpleConnection())) class SimpleUserAuth(userauth.SSHUserAuthClient): def getPassword(self): return defer.succeed(PASSWORD) def getGenericAnswers(self, name, instruction, questions): print 'Name %s' % name print 'Instruction %s' % instruction answers = [] for prompt, echo in questions: if echo: answer = raw_input(prompt) else: answer = getpass.getpass(prompt) answers.append(answer) return defer.succeed(answers) def getPublicKey(self): path = os.path.expanduser('~/.ssh/id_dsa') # this works with rsa too # just change the name here and in getPrivateKey if not os.path.exists(path) or self.lastPublicKey: # the file doesn't exist, or we've tried a public key return return keys.getPublicKeyString(path+'.pub') def getPrivateKey(self): path = os.path.expanduser('~/.ssh/id_dsa') return defer.succeed(keys.getPrivateKeyObject(path)) class SimpleConnection(connection.SSHConnection): def serviceStarted(self): self.openChannel(TrueChannel(2**16, 2**15, self)) self.openChannel(FalseChannel(2**16, 2**15, self)) self.openChannel(LsChannel(2**16, 2**15, self)) class TrueChannel(channel.SSHChannel): name = 'session' # needed for commands def openFailed(self, reason): print 'true failed', reason def channelOpen(self, ignoredData): self.conn.sendRequest(self, 'exec', common.NS('true')) def request_exit_status(self, data): status = struct.unpack('>L', data)[0] #print 'true status was: %s' % status self.loseConnection() class FalseChannel(channel.SSHChannel): name = 'session' def openFailed(self, reason): print 'false failed', reason def channelOpen(self, ignoredData): self.conn.sendRequest(self, 'exec', common.NS('false')) def request_exit_status(self, data): status = struct.unpack('>L', data)[0] #print 'false status was: %s' % status self.loseConnection() class LsChannel(channel.SSHChannel): name = 'session' def openFailed(self, reason): print 'false failed', reason def channelOpen(self, ignoredData): self.conn.sendRequest(self, 'exec', common.NS('ls -al')) self.data = '' def dataReceived(self, data): self.data += data def closed(self): print 'got data from ls: %s' % repr(self.data) self.loseConnection() reactor.stop() class CatChannel(channel.SSHChannel): name = 'session' def openFailed(self, reason): print 'echo failed', reason def channelOpen(self, ignoredData): self.data = '' d = self.conn.sendRequest(self, 'exec', common.NS('cat'), wantReply = 1) d.addCallback(self._cbRequest) def _cbRequest(self, ignored): self.write('hello conch\n') self.conn.sendEOF(self) def dataReceived(self, data): self.data += data def closed(self): print 'got data from cat: %s' % repr(self.data) self.loseConnection()
Whoops, I forgot to add the wantReply=1 there... anyway, Another question I have is if the password is incorrect, quit the python script... currently the getPassword function looks like this RETRIES = 0 def getPassword(self): global RETRIES if RETRIES == 0: RETRIES = 1 return defer.succeed(PASSWORD) else: sys.exit(0) But it keeps on giving this error: Traceback (most recent call last): File "c:\Python24\lib\site-packages\twisted\python\context.py", line 31, in ca llWithContext return func(*args,**kw) File "c:\Python24\lib\site-packages\twisted\internet\selectreactor.py", line 1 39, in _doReadOrWrite why = getattr(selectable, method)() File "c:\Python24\lib\site-packages\twisted\internet\tcp.py", line 351, in doR ead return self.protocol.dataReceived(data) File "c:\Python24\Lib\site-packages\twisted\conch\ssh\transport.py", line 189, in dataReceived ord(packet[0]), packet[1:]) --- <exception caught here> --- File "c:\Python24\lib\site-packages\twisted\python\log.py", line 56, in callWi thLogger return callWithContext({"system": lp}, func, *args, **kw) File "c:\Python24\lib\site-packages\twisted\python\log.py", line 41, in callWi thContext return context.call({ILogContext: newCtx}, func, *args, **kw) File "c:\Python24\lib\site-packages\twisted\python\context.py", line 52, in ca llWithContext return self.currentContext().callWithContext(ctx, func, *args, **kw) File "c:\Python24\lib\site-packages\twisted\python\context.py", line 31, in ca llWithContext return func(*args,**kw) File "c:\Python24\Lib\site-packages\twisted\conch\ssh\service.py", line 42, in packetReceived f(packet) File "c:\Python24\Lib\site-packages\twisted\conch\ssh\userauth.py", line 259, in ssh_USERAUTH_FAILURE if method not in self.authenticatedWith and self.tryAuth(method): File "c:\Python24\Lib\site-packages\twisted\conch\ssh\userauth.py", line 231, in tryAuth return f() File "c:\Python24\Lib\site-packages\twisted\conch\ssh\userauth.py", line 344, in auth_password d = self.getPassword() File "D:\stanc_vault\dev\WHIP\whip.py", line 67, in getPassword sys.exit(1) exceptions.SystemExit: 1 Astan Chee wrote:
Hi Guys, Im trying to make a psudo SSH client GUI, but it seems that I although I can 'ls' to a remote machine using twisted.conch, I cant `ls -al`. Also I cant seem to to ssh commands that have spaces in them. Although Im using a windows environment to SSH, i dont think that is the problem. Here is a snippet of my code. Obviously I've already called reactor.run() and included appropriate modules and variables. I dont understand why ls works and ls -al doesnt. Also I was wondering if there are any existing command line SSH clients written with twisted similar to putty, but written in python. Thanks!
class SimpleTransport(transport.SSHClientTransport): def verifyHostKey(self, hostKey, fingerprint): print 'host key fingerprint: %s' % fingerprint return defer.succeed(1)
def connectionSecure(self): self.requestService( SimpleUserAuth(USER, SimpleConnection()))
class SimpleUserAuth(userauth.SSHUserAuthClient): def getPassword(self): return defer.succeed(PASSWORD)
def getGenericAnswers(self, name, instruction, questions): print 'Name %s' % name print 'Instruction %s' % instruction answers = [] for prompt, echo in questions: if echo: answer = raw_input(prompt) else: answer = getpass.getpass(prompt) answers.append(answer) return defer.succeed(answers) def getPublicKey(self): path = os.path.expanduser('~/.ssh/id_dsa') # this works with rsa too # just change the name here and in getPrivateKey if not os.path.exists(path) or self.lastPublicKey: # the file doesn't exist, or we've tried a public key return return keys.getPublicKeyString(path+'.pub')
def getPrivateKey(self): path = os.path.expanduser('~/.ssh/id_dsa') return defer.succeed(keys.getPrivateKeyObject(path))
class SimpleConnection(connection.SSHConnection): def serviceStarted(self): self.openChannel(TrueChannel(2**16, 2**15, self)) self.openChannel(FalseChannel(2**16, 2**15, self)) self.openChannel(LsChannel(2**16, 2**15, self))
class TrueChannel(channel.SSHChannel): name = 'session' # needed for commands
def openFailed(self, reason): print 'true failed', reason def channelOpen(self, ignoredData): self.conn.sendRequest(self, 'exec', common.NS('true'))
def request_exit_status(self, data): status = struct.unpack('>L', data)[0] #print 'true status was: %s' % status self.loseConnection()
class FalseChannel(channel.SSHChannel): name = 'session'
def openFailed(self, reason): print 'false failed', reason
def channelOpen(self, ignoredData): self.conn.sendRequest(self, 'exec', common.NS('false'))
def request_exit_status(self, data): status = struct.unpack('>L', data)[0] #print 'false status was: %s' % status self.loseConnection() class LsChannel(channel.SSHChannel): name = 'session'
def openFailed(self, reason): print 'false failed', reason
def channelOpen(self, ignoredData): self.conn.sendRequest(self, 'exec', common.NS('ls -al')) self.data = ''
def dataReceived(self, data): self.data += data
def closed(self): print 'got data from ls: %s' % repr(self.data) self.loseConnection() reactor.stop() class CatChannel(channel.SSHChannel): name = 'session'
def openFailed(self, reason): print 'echo failed', reason
def channelOpen(self, ignoredData): self.data = '' d = self.conn.sendRequest(self, 'exec', common.NS('cat'), wantReply = 1) d.addCallback(self._cbRequest)
def _cbRequest(self, ignored): self.write('hello conch\n') self.conn.sendEOF(self)
def dataReceived(self, data): self.data += data
def closed(self): print 'got data from cat: %s' % repr(self.data) self.loseConnection()
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
On Mon, Jul 18, 2005 at 05:02:52PM +1000, Astan Chee wrote:
Whoops, I forgot to add the wantReply=1 there... anyway, Another question I have is if the password is incorrect, quit the python script...
currently the getPassword function looks like this RETRIES = 0 def getPassword(self): global RETRIES if RETRIES == 0: RETRIES = 1 return defer.succeed(PASSWORD) else: sys.exit(0)
Use reactor.stop() rather than sys.exit(0). -Andrew.
Astan Chee wrote:
def getPassword(self): global RETRIES if RETRIES == 0: RETRIES = 1 return defer.succeed(PASSWORD) else: sys.exit(0)
But it keeps on giving this error: Yes, that's what sys.exit does, raise a SystemExit exception.
If you actually want a non-zero exit status, you need to reactor.stop and save your exit status somewhere, e.g. exitstatus=0 def thing(): global exitstatus if fail: exitstatus = 1 reactor.stop() reactor.run() # We'll only get here once reactor.stop is called sys.exit(exitstatus) A trivial bit of thought can solve this more elegantly than a global (gak!)
Thanks for the help. Another thing I was wondering about is if any of the twisted components supports rsh? or is just using the` rsh` command easiest? Also where can I find detailed documentation on twisted classes and its method? or is diving into the code my best way? thanks again Cheers Phil Mayers wrote:
Astan Chee wrote:
def getPassword(self): global RETRIES if RETRIES == 0: RETRIES = 1 return defer.succeed(PASSWORD) else: sys.exit(0)
But it keeps on giving this error:
Yes, that's what sys.exit does, raise a SystemExit exception.
If you actually want a non-zero exit status, you need to reactor.stop and save your exit status somewhere, e.g.
exitstatus=0
def thing(): global exitstatus if fail: exitstatus = 1 reactor.stop()
reactor.run() # We'll only get here once reactor.stop is called sys.exit(exitstatus)
A trivial bit of thought can solve this more elegantly than a global (gak!)
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
On Jul 18, 2005, at 7:37 PM, Astan Chee wrote:
Thanks for the help. Another thing I was wondering about is if any of the twisted components supports rsh? or is just using the` rsh` command easiest? Also where can I find detailed documentation on twisted classes and its method? or is diving into the code my best way? thanks again
Why would anybody use, never mind implement, rsh? It's a stupid broken insecure protocol. James
On Tue, 19 Jul 2005 09:37:14 +1000, Astan Chee <stanc@al.com.au> wrote:
Thanks for the help. Another thing I was wondering about is if any of the twisted components supports rsh? or is just using the` rsh` command easiest? Also where can I find detailed documentation on twisted classes and its method? or is diving into the code my best way? thanks again Cheers
rsh uses the rlogin protocol. The rlogin protocol is immensely trivial. A Twisted implementation would probably be less than 10 lines, but one is not included with Twisted. Implementing it would probably be easier than shelling out to an rsh(1) binary. Twisted *does* include an SSH implementation, though. In most cases that is vastly preferable. Twisted uses epydoc markup extensively. The resulting automatically generated documentation is available at <http://twistedmatrix.com/documents/current/api/>. Diving into the source is also a really good way to become familiar with what Twisted can do. This can also give you a sense of the level of completion and polish a particular area of Twisted has, which is not always readily apparent from the API documentation. Jp
Thanks for that, but since I've been using twisted's ssh, it doesnt disconnect me from the server whenever I exit. It seems that for some reason if I call the SimpleTransport class after I've called and destroyed(how do I destroy a protocol.ClientFactory() class anyway?) it once, it becomes stuck. I wonder if this is an unresolved bug, oh well. The logs look something like this: 2005/07/19 10:41 AUS Eastern Standard Time [-] Log opened. 2005/07/19 10:41 AUS Eastern Standard Time [-] Starting factory <twisted.internet.protocol.ClientFactory instance at 0x01C9D580> 2005/07/19 10:41 AUS Eastern Standard Time [-] Enabling Multithreading. 2005/07/19 10:41 AUS Eastern Standard Time [SimpleTransport,client] kex alg, key alg: diffie-hellman-group-exchange-sha1 ssh-rsa 2005/07/19 10:41 AUS Eastern Standard Time [SimpleTransport,client] client->server: aes256-cbc hmac-sha1 none 2005/07/19 10:41 AUS Eastern Standard Time [SimpleTransport,client] server->client: aes256-cbc hmac-sha1 none host key fingerprint: 3f:ae:08:ab:0a:79:c9:65:61:f0:ec:5e:1e:48:ee:69 2005/07/19 10:41 AUS Eastern Standard Time [SimpleTransport,client] starting service ssh-userauth 2005/07/19 10:41 AUS Eastern Standard Time [SSHService ssh-userauth on SimpleTransport,client] can continue with: ['publickey', 'password', 'keyboard-in 2005/07/19 10:41 AUS Eastern Standard Time [SSHService ssh-userauth on SimpleTransport,client] trying to auth with publickey 2005/07/19 10:41 AUS Eastern Standard Time [SSHService ssh-userauth on SimpleTransport,client] trying to auth with password 2005/07/19 10:41 AUS Eastern Standard Time [SSHService ssh-userauth on SimpleTransport,client] starting service ssh-connection 2005/07/19 10:41 AUS Eastern Standard Time [SSHService ssh-userauth on SimpleTransport,client] opening channel 0 with 65536 32768 2005/07/19 10:41 AUS Eastern Standard Time [SSHChannel session (0) on SSHService ssh-connection on SimpleTransport,client] sending request exec 2005/07/19 10:41 AUS Eastern Standard Time [SSHChannel session (0) on SSHService ssh-connection on SimpleTransport,client] sending eof 2005/07/19 10:41 AUS Eastern Standard Time [SSHChannel session (0) on SSHService ssh-connection on SimpleTransport,client] remote eof 2005/07/19 10:41 AUS Eastern Standard Time [SSHChannel session (0) on SSHService ssh-connection on SimpleTransport,client] unhandled request for exit-st 2005/07/19 10:41 AUS Eastern Standard Time [SSHChannel session (0) on SSHService ssh-connection on SimpleTransport,client] remote close 2005/07/19 10:41 AUS Eastern Standard Time [SSHChannel session (0) on SSHService ssh-connection on SimpleTransport,client] sending close 0 2005/07/19 10:41 AUS Eastern Standard Time [SimpleTransport,client] connection lost 2005/07/19 10:41 AUS Eastern Standard Time [SimpleTransport,client] Stopping factory <twisted.internet.protocol.ClientFactory instance at 0x01C9D580> 2005/07/19 10:41 AUS Eastern Standard Time [-] Main loop terminated. 2005/07/19 10:41 AUS Eastern Standard Time [-] Log opened. 2005/07/19 10:41 AUS Eastern Standard Time [-] Log opened. 2005/07/19 10:41 AUS Eastern Standard Time [-] Starting factory <twisted.internet.protocol.ClientFactory instance at 0x01CAB148> 2005/07/19 10:41 AUS Eastern Standard Time [-] Starting factory <twisted.internet.protocol.ClientFactory instance at 0x01CAB148> 2005/07/19 10:41 AUS Eastern Standard Time [-] Stopping factory <twisted.internet.protocol.ClientFactory instance at 0x01CAB148> 2005/07/19 10:41 AUS Eastern Standard Time [-] Stopping factory <twisted.internet.protocol.ClientFactory instance at 0x01CAB148> Jp Calderone wrote:
On Tue, 19 Jul 2005 09:37:14 +1000, Astan Chee <stanc@al.com.au> wrote:
Thanks for the help. Another thing I was wondering about is if any of the twisted components supports rsh? or is just using the` rsh` command easiest? Also where can I find detailed documentation on twisted classes and its method? or is diving into the code my best way? thanks again Cheers
rsh uses the rlogin protocol. The rlogin protocol is immensely trivial. A Twisted implementation would probably be less than 10 lines, but one is not included with Twisted. Implementing it would probably be easier than shelling out to an rsh(1) binary. Twisted *does* include an SSH implementation, though. In most cases that is vastly preferable.
Twisted uses epydoc markup extensively. The resulting automatically generated documentation is available at <http://twistedmatrix.com/documents/current/api/>.
Diving into the source is also a really good way to become familiar with what Twisted can do. This can also give you a sense of the level of completion and polish a particular area of Twisted has, which is not always readily apparent from the API documentation.
Jp
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
On Jul 17, 2005, at 9:02 PM, Astan Chee wrote:
Whoops, I forgot to add the wantReply=1 there... anyway, Another question I have is if the password is incorrect, quit the python script...
currently the getPassword function looks like this RETRIES = 0 def getPassword(self): global RETRIES if RETRIES == 0: RETRIES = 1 return defer.succeed(PASSWORD) else: sys.exit(0)
reactor.stop() is what you want here. -bob
participants (6)
-
Andrew Bennetts -
Astan Chee -
Bob Ippolito -
James Y Knight -
Jp Calderone -
Phil Mayers