Nested SSH session with Paramiko
Question: I'm rewriting a Bash script I wrote into Python. The crux of that script was

    
    
    ssh -t first.com "ssh second.com very_remote_command"
    

I'm having a problem with the nested authentication with paramiko. I wasn't
able to find any examples dealing with my precise situation, but I was able to
find examples with _sudo_ on a remote host.

[The first method](http://jessenoller.com/2009/02/05/ssh-programming-with-
paramiko-completely-different/) writes to stdin

    
    
    ssh.connect('127.0.0.1', username='jesse', password='lol')
    stdin, stdout, stderr = ssh.exec_command("sudo dmesg")
    stdin.write('lol\n')
    stdin.flush()
    

[The second](http://www.gossamer-threads.com/lists/python/bugs/765465) creates
a channel and uses the socket-like _send_ and _recv_.

I was able to get _stdin.write_ to work with _sudo_ , but it doesn't work with
_ssh_ on the remote host.

    
    
    import paramiko
    
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect('first.com', username='luser', password='secret')
    stdin, stdout, stderr = ssh.exec_command('ssh luser@second.com')
    stdin.write('secret')
    stdin.flush()
    print '---- out ----'
    print stdout.readlines()
    print '---- error ----'
    print stderr.readlines()
    
    ssh.close()
    

...prints...

    
    
    ---- out ----
    []
    ---- error ----
    ['Pseudo-terminal will not be allocated because stdin is not a terminal.\r\n', 'Permission denied, please try again.\r\n', 'Permission denied, please try again.\r\n', 'Permission denied (publickey,password,keyboard-interactive).\r\n']
    

The pseudo-terminal error reminded me of the -t flag in my original command,
so I switched to the second method, using a Channel. Instead of
ssh.exec_command and later, I have:

    
    
    t = ssh.get_transport()
    chan = t.open_session()
    chan.get_pty()
    print '---- send ssh cmd ----'
    print chan.send('ssh luser@second.com')
    print '---- recv ----'
    print chan.recv(9999)
    chan = t.open_session()
    print '---- send password ----'
    print chan.send('secret')
    print '---- recv ----'
    print chan.recv(9999)
    

...but it prints '---- send ssh cmd ----' and just hangs until I kill the
process.

I'm new to Python and none too knowledgeable about networks. In the first
case, why does sending the password work with _sudo_ but not with _ssh_? Are
the prompts different? Is paramiko even the right library for this?


Answer: I managed to find a solution, but it requires a little manual work. If anyone
have a better solution, please tell me.

    
    
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect('first.com', username='luser', password='secret')
    
    chan = ssh.invoke_shell()
    
    # Ssh and wait for the password prompt.
    chan.send('ssh second.com\n')
    buff = ''
    while not buff.endswith('\'s password: '):
        resp = chan.recv(9999)
        buff += resp
    
    # Send the password and wait for a prompt.
    chan.send('secret\n')
    buff = ''
    while not buff.endswith('some-prompt$ '):
        resp = chan.recv(9999)
        buff += resp
    
    # Execute whatever command and wait for a prompt again.
    chan.send('ls\n')
    buff = ''
    while not buff.endswith('some-prompt$ '):
        resp = chan.recv(9999)
        buff += resp
    
    # Now buff has the data I need.
    print 'buff', buff
    
    ssh.close()
    

The thing to note is that instead of this

    
    
    t = ssh.get_transport()
    chan = t.open_session()
    chan.get_pty()
    

...you want this

    
    
    chan = ssh.invoke_shell()
    

It reminds me of when I tried to write a TradeWars script when I was a kid and
gave up coding for ten years. :)

