53

How can I force SSH to request passphrases using a graphical prompt (GTK, for example) instead of the standard one that uses the terminal?

I tried setting SSH_ASKPASS=/usr/bin/ssh-askpass but it seems to have no effects.

The problem is the fact the openssh documentation says

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.

An ssh launched from the command line, in my case as the result of a git push, will have a terminal associated with it, so the SSH_ASKPASS logic seems to be ignored.

Please note that I am not referring to ssh-add, but to generic ssh invocations towards an hosts for which a key pair is present but protected by a passphrase.

gioele
  • 2,139

6 Answers6

43

#1 - Missing package?

You're probably missing the package that contains ssh-askpass. Try installing it.

Fedora/CentOS/RHEL:

$ sudo yum install openssh-askpass

Debian/Ubuntu:

$ sudo apt-get install ssh-askpass-gnome ssh-askpass

Finding missing utilities

You can search for missing tools using these commands:

Fedora/CentOS/RHEL:

$ yum search ssh-askpass
Loaded plugins: langpacks, presto, refresh-packagekit
Adding en_US to language list
======================================================= Matched: ssh-askpass =======================================================
x11-ssh-askpass.x86_64 : A passphrase dialog for X and not only for OpenSSH
ksshaskpass.x86_64 : A KDE version of ssh-askpass with KWallet support
connect-proxy.x86_64 : SSH Proxy command helper
openssh-askpass.x86_64 : A passphrase dialog for OpenSSH and X

Debian/Ubuntu:

$ apt-file -l search ssh-askpass
app-install-data
cruft
git-cola
luckybackup-data
pssh
sdm-terminal
seahorse
ssh-askpass
ssh-askpass-fullscreen
ssh-askpass-gnome

#2 - Disconnected terminal?

I missed this initially but after further reading up I noticed this comment in the man page of ssh regarding the SSH_ASKPASS environment variable.

excerpt

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. This is particularly
               useful when calling ssh from a .xsession or related script.  
               (Note that on some machines it may be necessary to redirect the 
               input from /dev/null to make this work.)

If you notice in the comment, it states that ssh "doesn't have a terminal associated" AND DISPLAY & SSH_ASKPASS are set. Noticing this is key. So to get ssh to use SSH_ASKPASS we need to get ssh to not have a terminal (aka. STDIN & STDOUT) attached to it.

One way to do this by making use of the command setsid. Don't feel bad. I never heard of this tool either. From the man page:

setsid - run a program in a new session

So if we run ssh as the "program" to setsid we can detach ssh from our terminal meeting the criteria mentioned in ssh's man page. The other criteria are set as follows:

$ echo $DISPLAY; echo $SSH_ASKPASS
:0.0
/usr/libexec/openssh/ssh-askpass

So if we put this all together:

$ setsid ssh user@remotehost

For example:

$ setsid ssh user@skinner

                                       ss of ask gui

A solution

If you'd like to make it so that the setsid is "built-in" you can create an aliases like so:

$ alias ssh="setsid ssh"

Now when you ssh you'll get the GUI popping up asking for your password:

$ ssh user@skinner

References

slm
  • 369,824
  • ssh-askpass gnome is installed and it works fine if launched manually. – gioele Jul 22 '13 at 23:14
  • @gioele - see updates, I think I've figured it out. – slm Jul 23 '13 at 01:29
  • the problem of this solution is that it requires that I modify each git or rsync command to use setsid ssh instad of plain ssh. – gioele Jul 23 '13 at 08:16
  • @gioele - you asked for a method to "force" the password GUI, this provides that. You can replace commands such as ssh with aliases setsid ssh is one approach. There are other ways. The limiting factor is openssh needs no TTY attached in order to activate the ASK_SSHPASS. – slm Jul 23 '13 at 09:08
  • 1
    I'm not missing the package and I cannot use setsid and then work in ssh from my terminal. That's just not a valid answer at all!? Plus, it was working in older versions of Ubuntu, so I'm not too sure I understand why it suddenly stopped working! – Alexis Wilke Nov 30 '14 at 05:40
  • @AlexisWilke - if you have a new question I encourage you to ask. This method, as demonstrated, does work. So you may have a different set of circumstances or things may have changed with newer versions of things. – slm Nov 30 '14 at 13:52
  • I found it! After all that reading yesterday, I finally got it. I had problems connecting because I had too many keys under ~/.ssh so I decided to move them under ~/.ssh/other_keys. That works in the sense that it does let you connect to servers properly, but that hides the keys from the ssh-agent so they do not get auto-added. Moving a key back to ~/.ssh solves the problem, although a better solution would be to have a tool that auto-adds keys without asking for the passphrase... (like ssh-add keyname but silent.) – Alexis Wilke Nov 30 '14 at 23:16
  • @AlexisWilke - yeah I've written about that issue before on SU: Too many authentication failures for username – slm Nov 30 '14 at 23:52
  • Interesting. I read that question/answers a while back when I ran in that problem. I now have a new question about the ssh-add not being able to add keys without immediately asking you for your passphrase. http://unix.stackexchange.com/questions/170750/is-there-a-way-to-specify-the-list-of-private-keys-to-add-to-ssh-agent Maybe someone has a solution for that one. – Alexis Wilke Dec 01 '14 at 00:03
  • In the past I have come across one caveat which is not mentioned in your answer. I needed to use ssh to connect to an embedded system and I wanted to use SSH_ASKPASS. It turns out the embedded system used keyboard-interactive authentication and SSH_ASKPASS only works for password. Since the prompt displayed using keyboard-interactive looked exactly like the one which password would have used, it took me a long time before I realized why SSH_ASKPASS never worked for me. – kasperd Jun 09 '15 at 22:12
  • The link points to the man page of setsid(2) while it should point to setsid(1) – Weijun Zhou Dec 28 '17 at 19:41
  • @AlexisWilke you can create initial ssh session with ControlMaster ssh_config feature enabled: setsid ssh -Nf ... host, and then to interactively connect to the host, use: ssh ... host which will re-use the already authenticated ssh session. – abbe May 14 '18 at 13:17
12

It cannot be done in OpenSSH before version 8.4: for details read the issue in the OpenSSH Bugzilla asking for this feature since 2002 and finally fixed in 2021-01: Generalize SSH_ASKPASS.

For OpenSSH version 8.4+, see the accepted answer for a quick explanation of how to achieve this using SSH_ASKPASS_REQUIRE.

gioele
  • 2,139
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – cuonglm Oct 13 '15 at 01:30
  • 10
    @cuonglm "this is not possible" is an answer. It might be wrong or misleading (I'm not saying it is), but it's still an answer. – terdon Oct 22 '15 at 14:04
  • Correct, the "it cannot be done" assertion saves us from searching the web for an answer that isn't there. – Coder Guy Nov 11 '21 at 21:14
11

It only took 19 years to solve this issue OpenSSH Bug 69 - generalised-askpass.

OpenSSH 8.4 will include a $SSH_ASKPASS_REQUIRE variable that accepts force|prefer|never options.

When I set SSH_ASKPASS_REQUIRE to prefer then ssh-add from the terminal will launch the ssh-askpass user interface. On my Arch Linux machine I have the following in my .xinitrc

export SSH_ASKPASS=/usr/lib/ssh/x11-ssh-askpass
export SSH_ASKPASS_REQUIRE=prefer
eval `keychain --eval --noask ~/.ssh/id_rsa`

And in my ~/.ssh/config I have

AddKeysToAgent yes

So when I run e.g. git pull in one of my projects the very first time after a reboot, then the askpass dialog will correctly popup and ask for the password only a single time.

Hope that helps.

thg
  • 126
5

There is a way to close the terminal for a single command, and that is using file redirection:

ssh-add > /dev/null < /dev/null 2>&1

This will run the command ssh-add with the terminal closed. Which is fine and dandy, except for the its complexity. But now that you know the correct command, simply make it an alias and append it to ~/.bash_aliases:

alias ssh-add="/usr/bin/ssh-add > /dev/null < /dev/null 2>&1"

And you should be set. Simply typing ssh-add will now invoke the alias which will invoke the real command with all the redirection in place.

The ssh-add now correctly asks you the password with a dialog box... Provided that you have one of these packages installed (in Ubuntu or derivatives, they may have other names elsewhere):

  • ssh-askpass
  • ssh-askpass-fullscreen
  • ssh-askpass-gnome
  • ksshaskpath
  • kwalletcli
  • lxqt-openssh-askpass
  • razorqt-openssh-askpasss

Now, what do all those things mean?

The 2>&1 means redirect file descriptor #2 (standard error) to the same place file descriptor #1 (standard output) is directed to.

The > /dev/null means redirect standard output to /dev/null, which is a special file that discards all data written to it.

The < /dev/null means redirect standard input to /dev/null (idem).

As a side note, and an off topic but related note, if you ever want to program a service in bash, you must remember what a service actually is, a process with standard input, output, and error closed that is in the background:

service > /dev/null < /dev/null 2>&1 &

Notice that the only difference is the & added at the end (plus the fact that I changed the command ssh-add for a theoretical service. Those commands will correctly put a service on the background.

studog
  • 527
Victor
  • 47
  • Thank you for the detailed answer Victor. However, it does not fit my requirements. As I wrote at the end of the question, «Please note that I am not referring to ssh-add, but to generic ssh invocations towards an hosts for which a key pair is present but protected by a passphrase.». – gioele Mar 20 '17 at 06:23
  • I see.

    Well, ssh functions the exact same way, and the same answer I gave previously still applies. Just replace every occurence of ssh-add with ssh and you are set.

    – Victor Mar 22 '17 at 14:38
  • There is just a tiny detail you forgot: if I close stdin/stdout for ssh, how do I give commands through ssh? ;) – gioele Mar 22 '17 at 15:54
  • This worked for ssh-add for me - I didn't even need to redirect stdout/stderr to get the desired behavior, which was to pop up the ssh-askpass program. (That is, ssh-add < /dev/null was enough.) – Ben Stern Apr 19 '19 at 00:50
1

I had the same problem when I installed seahorse (which provide seahorse-ssh-askpass) without installing the package gnome-keyring on ArchLinux.

Looking at the content of this package gnome-keyring (https://www.archlinux.org/packages/extra/i686/gnome-keyring) may help you solve your problem.

In any case, if you do not mind using seahorse, you can also install the packages seahorse and gnome-keyring (or the equivalent ones for your distribution). If you do not use Gnome, additional steps may be required: https://wiki.archlinux.org/index.php/GNOME_Keyring.

Fabrice
  • 111
  • I agree that this is an effective solution. It doesn't force the use specifically of the ssh-askpass command, but it does provide a graphical prompt the first time a key is needed. It provides it's own socket at $SSH_AUTH_SOCK (typiically under /run/user/NNNNN/keyring/ssh-sock) which acts like an ssh-agent. – Brian Minton Apr 24 '22 at 04:34
-1

In my opinion, the simplest solution is to set the pinentry program of your choice using update-alternatives. For example for KDE this would be:

# review current default pinentry for ssh-askpass
update-alternatives --list ssh-askpass

set

update-alternatives --force --verbose --set ssh-askpass /usr/bin/kssaskpass