<br><tt><font size=2>After much wrangling and a small miracle I have managed
to write an object that fetches the output of three commands in the order
given through an SSH connection. How come I cannot switch users? Some of
the information I need can only be fetched through a root account and security
is such that I cannot log in remotely from a root account but must switch
once logged in from an account with less than root privileges.</font></tt>
<br>
<br><tt><font size=2>Here's the line that instaniates my SSH object (also
repeated at the end of my code):</font></tt>
<br>
<br><tt><font size=2>myssh = SSH(&quot;my.host.com&quot;, &quot;myusername&quot;,
&quot;mypasswd&quot;, [&quot;id; su - root; myrootpasswd; id&quot;, &quot;pwd&quot;,
&quot;ls -l&quot;])</font></tt>
<br>
<br><tt><font size=2>The last argument above is a &nbsp;list of three commands.
Inside one command &quot;;&quot; separates the piece parts.</font></tt>
<br><tt><font size=2>I am not even able to su to accounts that don't require
a password.</font></tt>
<br>
<br><tt><font size=2>###========= CODE STARTS ================###</font></tt>
<br><tt><font size=2>from twisted.conch import error</font></tt>
<br><tt><font size=2>from twisted.conch.ssh import transport, connection,
keys, userauth, channel, common</font></tt>
<br><tt><font size=2>from twisted.internet import defer, protocol, reactor</font></tt>
<br><tt><font size=2>import sys, getpass, os, string</font></tt>
<br>
<br><tt><font size=2>class ClientCommandTransport(transport.SSHClientTransport):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def __init__(self, username, password,
cmds, caller):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.username = username</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.password = password</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.cmds = cmds</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller = caller</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; </font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def verifyHostKey(self, pubKey, fingerprint):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; # in a real app, you should
verify that the fingerprint matches</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; # the one you expected
to get from this server</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; return defer.succeed(True)</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def connectionSecure(self):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.requestService(PasswordAuth(self.username,
self.password, ClientConnection(self.cmds, self.caller)))</font></tt>
<br>
<br><tt><font size=2>class PasswordAuth(userauth.SSHUserAuthClient):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def __init__(self, user, password, connection):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; userauth.SSHUserAuthClient.__init__(self,
user, connection)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.password = password</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; </font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def getPassword(self, prompt=None):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; return defer.succeed(self.password)</font></tt>
<br>
<br><tt><font size=2>class ClientConnection(connection.SSHConnection):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def __init__(self, cmds, caller, *args,
**kwargs):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; connection.SSHConnection.__init__(self)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.cmds = cmds</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller = caller</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; #======================</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def serviceStarted(self):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d = defer.Deferred()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addCallback(self._cbFirst)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addErrback(self._ebFirst)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.openChannel(CommandChannel(self.cmds[0],
lastcmd=0, conn=self))</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def _cbFirst(self, result):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; #print 'CALLBACK Result
1:', result</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller.responses.append(result.rstrip())</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d = defer.Deferred()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addCallback(self._cbSecond)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addErrback(self._ebSecond)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.openChannel(CommandChannel(self.cmds[1],
lastcmd=0, conn=self))</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def _ebFirst(self, f):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller.responses.append(None)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; print &quot;Error 1&quot;</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d = defer.Deferred()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addCallback(self._cbSecond)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addErrback(self._ebSecond)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.openChannel(CommandChannel(self.cmds[1],
lastcmd=0, conn=self))</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; #log.err()</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def _cbSecond(self, result):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; #print 'CALLBACK Result
2:', result</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller.responses.append(result.rstrip())</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d = defer.Deferred()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addCallback(self._cbThird)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addErrback(self._ebThird)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.openChannel(CommandChannel(self.cmds[2],
lastcmd=1, conn=self))</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def _ebSecond(self, f):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller.responses.append(None)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d = defer.Deferred()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addCallback(self._cbThird)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.d.addErrback(self._ebThird)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.openChannel(CommandChannel(self.cmds[2],
lastcmd=1, conn=self))</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; #log.err()</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def _cbThird(self, result):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller.responses.append(result.rstrip())</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; #print 'CALLBACK Result
3:', result</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; reactor.stop()</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def _ebThird(self, f):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller.responses.append(None)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; log.err()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; reactor.stop()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; #======================</font></tt>
<br>
<br><tt><font size=2>class CommandChannel(channel.SSHChannel):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; name = 'session'</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; </font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def __init__(self, command, lastcmd,
*args, **kwargs):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; channel.SSHChannel.__init__(self,
*args, **kwargs)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.command = command</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.lastcmd = lastcmd</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.data = &quot;&quot;</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def channelOpen(self, data):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.conn.sendRequest(self,
'exec', common.NS(self.command), wantReply=True).addCallback(self._gotResponse)</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def _gotResponse(self, _):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; #print &quot;RESPONSE&quot;</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.conn.sendEOF(self)</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def dataReceived(self, data):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; #print &quot;Data Received:&quot;,
data</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.data += data</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def closed(self):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.conn.d.callback(self.data)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.loseConnection()</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; ## &nbsp; &nbsp; &nbsp;
&nbsp;if self.lastcmd:</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; ## &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp;print &quot;closing reactor.&quot;</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; ## &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp;reactor.stop()</font></tt>
<br>
<br><tt><font size=2>class ClientCommandFactory(protocol.ClientFactory):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def __init__(self, username, password,
cmds, caller):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.username = username</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.password = password</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.cmds = cmds</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.caller = caller</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def buildProtocol(self, addr):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; protocol = ClientCommandTransport(self.username,
self.password, self.cmds, self.caller)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; return protocol</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; </font></tt>
<br><tt><font size=2>class SSH():</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &quot;&quot;&quot; Contains a SSH connection,
runs commands, and stores results. &quot;&quot;&quot;</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; def __init__(self, host, username, password,
cmds):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.host = host</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.username = username</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.password = password</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.cmds = cmds</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.responses = []</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; self.run_commands()</font></tt>
<br>
<br><tt><font size=2>&nbsp; &nbsp; def run_commands(self):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; factory = ClientCommandFactory(self.username,
self.password, self.cmds, self)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; reactor.connectTCP(self.host,
22, factory)</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; reactor.run()</font></tt>
<br>
<br><tt><font size=2>myssh = SSH(&quot;my.host.com&quot;, &quot;myacct&quot;,
&quot;mypasswd&quot;, [&quot;id; su - root; myrootpasswd; id&quot;, &quot;pwd&quot;,
&quot;ls -l&quot;])</font></tt>
<br>
<br><tt><font size=2>print &quot;=&quot; * 25</font></tt>
<br><tt><font size=2>for i, response in enumerate(myssh.responses):</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; print i, response</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; print &quot;=&quot; * 25</font></tt>
<br>
<br><tt><font size=2>print &quot;\nDone.&quot;</font></tt>