ccontavalli / ssh-ident

Different agents and different keys for different projects, with ssh.
Other
963 stars 71 forks source link

ssh-askpass required by ssh-ident #32

Closed mhoff closed 7 years ago

mhoff commented 8 years ago

When syncing some local stuff with my remote host rsync asks for the passphrase with ssh-askpass, even though this program is not installed on my system (I want to stick with this). As the program is not installed, adding the identity fails and the generic fallback identity is tried.

I set up ssh-ident as an executable in my $PATH. This is the output (VERBOSITY = LOG_DEBUG) I receive when running the rsync command:

rsync -e "ssh -p 22" -P -rvzc --delete $LOCAL_PATH $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH [...]
Will run '/usr/bin/ssh' as ssh binary - deteced from argv[0] and $PATH
Agent for identity v8 ready
Loading keys:
    /home/mhoff/.ssh/identities/v8/id_rsa
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
+ . /home/mhoff/.ssh/agents/agent-v8-$HOSTNAME
+ exec /usr/bin/ssh -oUseRoaming=no -p 22 -l $REMOTE_USER $REMOTE_HOST rsync --server -vrcCze.iLsfx --delete --partial . $REMOTE_PATH
Enter passphrase for key '/home/mhoff/.ssh/id_rsa':

Plainly, adding the identity to the agent triggers ssh-askpass. I tracked down the following method being responsible in ssh-ident:

  @staticmethod
  def RunShellCommandInAgent(agentfile, command):
    """Runs a shell command with an agent configured in the environment."""
    command = ["/bin/sh", "-c",
               ". {0} >/dev/null 2>/dev/null; {1}".format(agentfile, command)]
    # command = ['/bin/sh', '-c', '. /home/mhoff/.ssh/agents/agent-v8-$HOST >/dev/null 2>/dev/null; ssh-add -t 14400 /home/mhoff/.ssh/identities/v8/id_rsa']
    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    stdout, stderr = process.communicate()
    return process.wait(), stdout

The weird thing is that when I execute the above code in a standalone script everything works fine.

Script

#!/usr/bin/python
import subprocess
if __name__ == '__main__':
    command = ["/bin/sh", "-c", "/home/mhoff/.ssh/agents/agent-v8-$HOST >/dev/null 2>/dev/null; ssh-add -t 14400 /home/mhoff/.ssh/identities/v8/id_rsa"]
    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    stdout, stderr = process.communicate()

Output

Enter passphrase for /home/mhoff/.ssh/identities/v8/id_rsa: 

In the rsync command, I can add -i $IDENTITY_PATH to the ssh call. Then, the error still occurs, but the "fallback" identitiy is the given identity and the right prompt is used:

rsync -e "ssh -p 22 -i ~/.ssh/identities/v8/id_rsa" -P -rvzc --delete $LOCAL_PATH $REMOTE_HOST:$REMOTE_PATH [...]
Will run '/usr/bin/ssh' as ssh binary - deteced from argv[0] and $PATH
Agent for identity v8 ready
Loading keys:
    /home/mhoff/.ssh/identities/v8/id_rsa
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
+ . /home/mhoff/.ssh/agents/agent-v8-T420
+ exec /usr/bin/ssh -oUseRoaming=no -p 22 -i ~/.ssh/identities/v8/id_rsa -l $REMOTE_USER $REMOTE_HOST rsync --server -vrcCze.iLsfx --delete --partial . $REMOTE_PATH
Enter passphrase for key '/home/mhoff/.ssh/identities/v8/id_rsa': 
mhoff commented 8 years ago

I have further tracked down the issue. rsync $REMOTE_HOST:/ . fails to prompt for the passphrase with MATCH_ARGV = [... (r"$REMOTE_HOST", "v8") ...] being configured.

I modified ssh-ident to print argv supplied to main when being called. Directly executed, /home/mhoff/.bin/ssh $REMOTE_HOST rsync --server --sender -e.Lsfx . / is able to prompt for the passphrase correctly. Consequently, something in between rsync and the call to ssh leads to the above problem.

I checked the environment being called in (os.environ), but the only difference between both calls is that the executed binary differs (/usr/bin/rsync versus the path to my test script).

I really don't know how to proceed from here. I even checked whether SSH_ASKPASS is set before calling the evil subprocess.Popen but found nothing.