ssh, gpg-agent and pinentry - no tty or curses ?

Hi,
I am using ssh with key authentication and need to enter password upon establishing connection. Gpg-agent is taking care of the key authentication. Every time while logging in from another computer running KDE,Gnome, etc a pop-up window for pinentry presented. I need to change that to tty or curses.
The reason is that sometimes I log in from my Android phone or laptop to workstation A running X11+KDE and after that do ssh to workstation B (also running X11+KDE). And here lies the problem - it is impossible to enter password while logging in B because the pop-up password window shows up on workstation A screen, NOT on my laptop/phone.

I tried to add

pinentry-program "/usr/bin/pinentry-tty"

to .gnupg/gpg-agent.conf. It did not work (I did restart gpg-agent) - the following messages/warning thrown and authentication falls back to password:

sign_and_send_pubkey: signing failed: agent refused operation
sign_and_send_pubkey: signing failed: agent refused operation
sign_and_send_pubkey: signing failed: agent refused operation
Password:

I also tried to set shell variable

export PINENTRY_BINARY="/usr/bin/pinentry-tty"

before running SSH. That also did not work - a qt window pops up anyway. This is also puzzling because the script /usr/bin/pinentry supposed to pick up the correct pinentry version depending on the environment it was called from and one of the very first checks it does it checks if PINENTRY_BINARY is defined and uses it if so.

Currently I have the following versions of pinentry installed:
pinentry-curses
pinentry-emacs
pinentry-gnome3
pinentry-gtk-2
pinentry-qt
pinentry-tty

Does anybody has a working solution for this? I would rather prefer to have a simple pinentry-tty over fancy qt5 windows.

Thank you all for any suggestions.

Have you actually verified it? Modern GNOME will point SSH_AUTH_SOCK to gnome-keyring by default so even if you have gpg-agent running it does not necessarily mean it is actually used. Same may be with KDE, I do not use it.

The reason is that sometimes I log in from my Android phone or laptop to workstation A running X11+KDE and after that do ssh to workstation B (also running X11+KDE). And here lies the problem - it is impossible to enter password while logging in B because the pop-up password window shows up on workstation A screen, NOT on my laptop/phone.

It does not directly answer your question, but does B trust different keys than A? If B trusts your original keys used to log into A, you may consider enabling agent forwarding when logging into A.

Yes:

>echo $SSH_AUTH_SOCK
/run/user/1000/gnupg/S.gpg-agent.ssh

I do not understand what do you mean by trust: “trust” in pgp sense or if they share the same keys? If latter, the machines have different keys.

When you use public key authentication, the keys that you can use are listed in “.ssh/authorized_keys” on the host to which you are connecting. I’m pretty sure that’s what arvidjaar was referring to when he mentioned trust. That’s normally not the same as the machine key.

I’m not sure that I completely understand your issue. But can’t you avoid it by just using “ssh-add” at the command line before your ssh login attempt. That will allow you to enter the passphrase at the terminal where you ran “ssh-add”.

Both machines have .ssh/authorized_keys populated with public keys of clients that connect to them.

Let me try to explain it again. Say I have laptop “L”, workstation W1 (Tumbleweed KDE Plasma5) and workstation W2 (Leap 15.1 KDE Plasma5).

  1. I do ssh in W1. The authentication uses a key, the public part of which is stored in .ssh/authorized_keys on W1. During this process pinentry window pops up on my laptop L, where I enter the key password.

  2. I try to ssh in W2 from W1. I run

export PINENTRY_BINARY="/usr/bin/pinentry-tty"; ssh -i ~/.ssh/id_ed25519 -X user@W2;

after that pinentry window pops up on W1. If I am not nearby W1 I cannot finish authentication.

Notice that $PINENTRY_BINARY is ignored. But it should not if /usr/bin/pinentry script was called.
If I run ssh-add -l on laptop and W1 I cab see keys associated with laptop and W1 respectively. Equivalently .gnupg/sshcontrol has those keys listed.

Also, another sign that gpg-agent handles ssh logins is that after some time (about 2 hours) I need to re-enter passwords if need to open a new connection (the timeout is controlled by {max,default}-cache-ttl{,-ssh} parameters in .gnupg/gpg-agent.conf). As far as I know ssh-agent will cache passwords forever.

It depends on how it is called.

As far as I know, it is called from “gpg-agent”. So it will be the value of “$PINENTRY_BINARY” known to “gpg-agent” that matters.

Also, another sign that gpg-agent handles ssh logins is that after some time (about 2 hours) I need to re-enter passwords if need to open a new connection (the timeout is controlled by {max,default}-cache-ttl{,-ssh} parameters in .gnupg/gpg-agent.conf). As far as I know ssh-agent will cache passwords forever.

For me, “ssh-agent” handles “ssh” logins. I had assumed that it was your choice to use “gpg-agent” for that. But, based on your wording there, it looks as if you may not have intended that.

As far as I know, if I want “gpg-agent” to handle “ssh” authentication, then I need to configure that in “gpg-agent.conf” (in my “.gnupg” directory).

Exactly! It looks like the wrapper script /usr/bin/pinentry does not do what it was supposed to do. Otherwise why it would check for $PINENTRY_BINARY ? It does detect that variable but pinentry-qt is called anyway. I wonder if the choice of pinentry-qt was compiled in gpg.

My choice was to use gpg-agent. One of the reasons was that I do have a use for gpg, wanted to have single utility to generate and maintain keys. The timeout feature of gpg-agent is a welcome improvement over ssh-add in my eyes. And here is my gpg-agent.conf:

>cat ~/.gnupg/gpg-agent.conf
###+++--- GPGConf ---+++###
max-cache-ttl 3000
enable-ssh-support
pinentry-timeout 60
no-allow-mark-trusted
no-allow-external-cache
allow-emacs-pinentry
enforce-passphrase-constraints
min-passphrase-len 16
min-passphrase-nonalpha 6
disable-scdaemon
log-file socket:///home/<user>/.gnupg/log-socket
ssh-fingerprint-digest sha256
###+++--- GPGConf ---+++### Sun 23 Jun 2019 01:33:35 PM EDT
# GPGConf edited this configuration file.
# It will disable options before this marked block, but it will
# never change anything below these lines.

#### extra opts
#verbose
#pinentry-program /usr/bin/pinentry-curses
#pinentry-program /usr/bin/pinentry-tty

and here are relevant lines from .bashrc:

# Set GPG TTY
GPG_TTY=$(tty)
export GPG_TTY

# Refresh gpg-agent tty in case user switches into an X session
# this line might cause login problems !!!!!
#gpg-connect-agent updatestartuptty /bye >/dev/null

# Set SSH to use gpg-agent
unset SSH_AGENT_PID
if  "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
  export SSH_AUTH_SOCK="/run/user/$UID/gnupg/S.gpg-agent.ssh"
fi

I have never carefully tested what it does. But maybe it works from “gpg” commands, which might be passing PINENTRY_BINARY to gpg-agent in their request. But “ssh” commands do not know that they are talking to “gpg-agent”, so they won’t pass on that information.

Otherwise why it would check for $PINENTRY_BINARY ? It does detect that variable but pinentry-qt is called anyway. I wonder if the choice of pinentry-qt was compiled in gpg.

I doubt that. I’m pretty sure that I see “pinentry-gtk” here, even though I am using KDE (yes Gnome is also installed).

[QUOTE[My choice was to use gpg-agent. One of the reasons was that I do have a use for gpg, wanted to have single utility to generate and maintain keys. The timeout feature of gpg-agent is a welcome improvement over ssh-add in my eyes.[/QUOTE]
It isn’t “ssh-add” as far as I know. You should be able to still use “ssh-add” to add a key from the command line. And since you are using “gpg-agent” for ssh, it will still be timed out by the ssh-agent emulation of “gpg-agent”. Or, at least, that’s my assumption.

The script’s logic is simple. First ,it tries if $DISPLAY is defined and/or KDE is running. After that depending on which version of pinentry is installed, it execs it:


<figuring out $DISPLAY, if KDE is running, etc>

# if a user supplied a pinentry binary, use it
if  -n "$PINENTRY_BINARY" ];
then
    export PINENTRY_BINARY="$PINENTRY_BINARY"
# if KDE is detected and pinentry-qt5 exists, use pinentry-qt5
elif  -n "$kde_running" -a "$kde_ver"x = 4x -a -x /usr/bin/pinentry-qt5 ]
then
    < lots of "elif" checking $DISPLAY and installed versions of pinentry>
fi
exec $PINENTRY_BINARY "$@"

Also, in my case I am dead sure that pinentry-qt is executed, one can see from “ps ax | grep pinentry” once the dialog is presented. For what it’s worth gpg “configure” script allows for this option at compile time:

./configure --help 
......
--with-pinentry-pgm=PATH  Use PATH as the default for the pinentry)
......

I will dig deeper, will let now if I figure out what is going on.