9

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.

  • Good question. From looking at the source code, it doesn't look like it. You'd have to trick it into failing to open /dev/tty (LD_PRELOAD?). – Celada Mar 27 '16 at 20:42
  • @Celada would that cause problems when starting the shell? – muru Mar 27 '16 at 20:46
  • Probably not... – Celada Mar 27 '16 at 20:49
7

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.
  • ControlMaster is already setup, precisely because it's such a pain to enter passwords in such cases. It shouldn't be difficult to write a function which tests for an existing master and uses the askpass if it couldn't find one. Thanks! – muru Mar 27 '16 at 22:20
3

A per SSH manual (man ssh):

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.

Therefore you need to disassociate the terminal (e.g. by adding a pipe) and make sure DISPLAY isn't set (if you want to use terminal for your passphrase instead).

Simple example:

echo foo | SSH_ASKPASS=/my/cmd DISPLAY= ssh ...

The same with ssh-add:

$ echo foo | SSH_ASKPASS=/my/cmd DISPLAY= ssh-add id_rsa
ssh_askpass: exec(/my/cmd): No such file or directory
  • Unfortunately this does not work for me. It does say Pseudo-terminal will not be allocated because stdin is not a terminal, so it seems that the pipe is doing something. ssh </dev/null had the same effect. However in both cases it still asks for a password, and I can still type one in. I tried on Linux and Mac. I tried ssh -vvv but it doesn't say anything useful. – Timmmm Dec 18 '19 at 16:45
  • 1
    SSH_ASKPASS=/foo DISPLAY= setsid ssh host works though. – Timmmm Dec 18 '19 at 16:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.