Can I get SSH to use an askpass program even if it was run from a terminal?
This will be a bit more complicated, but combination of several pieces will make it working:
Explanation
To force
ssh
to use$SSH_ASKPASS
program, you can't allowssh
to see the realtty
. It is just condition. This can be done by usingsetsid
and using-n
switch tossh
.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.Set up
ControlMaster
inssh_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
tellssetsid
to wait for the program to end. In this case, that happens when SSH goes to the background. Combined withssh -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.
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
With OpenSSH 8.4 you can set $SSH_ASKPASS_REQUIRE
environment variable to force
. Quoting ssh(1) man page:
SSH_ASKPASS_REQUIRE Allows further control over the use of
an askpass program. If this variable
is set to "never" then ssh will never
attempt to use one. If it is set to
"prefer", then ssh will prefer to use
the askpass program instead of the TTY
when requesting passwords. Finally, if
the variable is set to "force", then
the askpass program will be used for
all passphrase input regardless of
whether DISPLAY is set.
As OpenSSH 8.4 was released September 27, 2020 you will need to wait a bit to have this feature available in any major Linux distribution.