Linux SSH – How to Get SSH to Use Askpass Program from Terminal

linuxopensshssh

man ssh says:

SSH_ASKPASS
   If  ssh needs a passphrase, it will read the passphrase from the
   current terminal if it was run from a terminal.  If ssh does not
   have  a  terminal associated with it but DISPLAY and SSH_ASKPASS
   are set, it will execute the program  specified  by  SSH_ASKPASS
   and open an X11 window to read the passphrase.

I'd like SSH to use an askpass program even if it was run from a terminal.

On occasion, I have to connect to servers, where there's some delay in showing a password prompt (maybe due to network issues, maybe due to attempted reverse DNS lookups, …). I get annoyed and switch to something else, and forget about the attempted connection. (Insert joke about attention span of a goldfish.) When I finally get back to it, the prompt's timed out and even a correct password would just result in a closed connection.

Keys would be one solution, but not every system I use has my usual SSH keys. However, I usually use Ubuntu systems, and Ubuntu has an SSH askpass program installed by default.

If an askpass window popped up, however, I'd be immediately aware of it. That's a good enough compromise for me, if only I can get it to work.

Best Answer

This will be a bit more complicated, but combination of several pieces will make it working:

Explanation

  1. To force ssh to use $SSH_ASKPASS program, you can't allow ssh to see the real tty. It is just condition. This can be done by using setsid and using -n switch to ssh.

    This case would initiate connection, but you would not be able to interact with the shell, which is probably also your requirement ;) (and also breaks your local TTY).

    But you can give up the "first session". You should also add -N switch, which will suppress the remote command and will do just the authentication.

    Also the possible output "junk" can be redirected to &> /dev/null if you are not interested in it.

  2. Set up ControlMaster in ssh_config. It is cool feature and once the connection is established, you can "fire up" sessions pretty fast. This snippet in ~/.ssh/config should do that:

    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 5m
    

    You can add that into some host block listing your "slow candidates", or just everywhere. It is almost no overhead.

Final line

Then you should be able to connect in this way to the host you expect it will take a while:

setsid ssh -nN host
# wait, insert password in the X11 prompt
ssh host
# will bring you directly to your session

Whole process might be simplified by alias or bash function doing both in one step, but it is left on readers imagination.

Only command-line arguments

You can join both things together on command-line without ssh_config part:

setsid ssh -nNMS ~/.ssh/masters/%C host
# wait, insert password in the X11 prompt
ssh -S ~/.ssh/masters/%C host
# will bring you directly to your session

The following function should work when SSH options aren't specified:

ssh() {
    if ! command ssh -o PasswordAuthentication=no "$1" true
    then
        setsid -w ssh -fnN "$1"
    fi
    command ssh "$@"
}
  • -f instructs SSH to go to the background just before program execution, which is after it has got the password.
  • -w tells setsid to wait for the program to end. In this case, that happens when SSH goes to the background. Combined with ssh -f, the manual wait between the two SSH commands can be eliminated.
  • The function assumes the first argument is the hostname.
  • The test is just to prevent unnecessary SSH connections.
Related Question