13

I read man ssh-add and I don't see a flag for passing a passphrase like we have in ssh which is -p.

I tried

# the -K is for macOS's ssh-add but it's not relevant
ssh-add -q -K ~/.ssh/id_rsa <<< $passphrase

But I get the following output:

ssh_askpass: exec(/usr/X11R6/bin/ssh-askpass): No such file or directory

How can I pass a password w/o triggering a prompt

Update

Adding more context to what I'm doing, I'm creating a script to create SSH keys for me. It will generate the passphrase, the SSH key using that passphrase, and add it to the agent.

# ...
passphrase=$(generate_password)

ssh-keygen -t rsa -b 4096 -C $email -f $filename -N $passphrase -q
ssh-add -q -K $filename

Following Stephen's answer, I'm not sure how would that work. Seems like I'd had to create a temporal script and save it to disk, in order for SSH_ASKPASS to work. Any ideas?

ctrl-alt-delor
  • 27,473
  • 9
  • 58
  • 102

2 Answers2

22

From the ssh-add manpage:

 DISPLAY and SSH_ASKPASS
         If ssh-add needs a passphrase, it will read the passphrase from
         the current terminal if it was run from a terminal.  If ssh-add
         does not have a terminal associated with it but DISPLAY and
         SSH_ASKPASS are set, it will execute the program specified by
         SSH_ASKPASS (by default ``ssh-askpass'') and open an X11 window
         to read the passphrase.  This is particularly useful when calling
         ssh-add 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.)

So we can use this to cheat a little.

We start with no identities in the agent:

$ ssh-add -l
The agent has no identities.

So now we need a program that will supply the password:

$ cat x
#!/bin/sh
echo test123

And then convince ssh-add to use that script:

$ DISPLAY=1 SSH_ASKPASS="./x" ssh-add test < /dev/null
Identity added: test (sweh@godzilla)

And there it is:

$ ssh-add -l                                          
2048 SHA256:07qZby7TafI10LWAMSvGFreY75L/js94pFuNcbhfSC0 sweh@godzilla (RSA)

Edit to add, based on revised question:

The password could be passed as a variable, and the askpass script use that variable.

For example:

$ cat /usr/local/sbin/auto-add-key
#!/bin/sh
echo $SSH_PASS

$ SSH_PASS=test123 DISPLAY=1 SSH_ASKPASS=/usr/local/sbin/auto-add-key ssh-add test < /dev/null
Identity added: test (sweh@godzilla)

In the workflow presented you would do SSH_PASS=$passphrase to use the newly generated passphrase.

Stephen Harris
  • 42,369
  • 5
  • 94
  • 123
6

You can use script(1) as a mini-expect.

On Linux:

{ sleep .1; echo password; } | script -q /dev/null -c 'ssh-add /path/to/identity'

On BSD:

{ sleep .1; echo password; } | script -q /dev/null ssh-add /path/to/identity

You may want to increase the delay (sleep .3 or sleep 1) if the right hand of the pipeline is slow to start. For anything more complex, use expect. Do not use sshpass since it's really no better than script and itself subject to races.

  • You're right about the flag, I don't know why that came to mind; maybe it's a different tool that takes -p as password(?) I can't remember. Anyways, you're right – Christopher Francisco Mar 08 '20 at 06:20
  • Could you break down the first part of the expression, and how the solution works? I'm not sure why the sleep call – Christopher Francisco Mar 08 '20 at 06:21
  • Yes, `sshpass`. See the updated answer, I think the BSD syntax works in MacOS, too. –  Mar 08 '20 at 06:21
  • The `sleep` is to give time to `ssh-add` to start, print its prompt and turn echo mode off on the pseudo-terminal created by `script`. Like with any pipeline, both sides of the pipeline are started in any order, and are run in parallel, _at the same time_. –  Mar 08 '20 at 06:23
  • For this kind of timing problems (which also badly affect `sshpass`), see this [Q&A](https://serverfault.com/a/1005485/487680). –  Mar 08 '20 at 06:26
  • @ChristopherFrancisco please con/infirm if the BSD `script` syntax also works on MacOS as it does on FreeBSD, since I have no MacOS to test on (it should, according to the manpage). So I could correct it before leaving. Thanks. –  Mar 08 '20 at 07:31