Page MenuHome GnuPG

pinentry-qt on wayland does not fallback to pinentry-curses
Open, LowPublic

Description

Long story.

I'm migrating my desktop setup to wayland (ideally without xwayland running).

Previously under X, I had pinentry-program /usr/bin/pinentry-gtk-2. If I would ssh to this system and do something which made gpg-agent invoke (right?) the pinentry program, I would get pinentry-curses in my face and happily enter the passphrase.

I found that pinentry-qt works natively in wayland, and does fallback as well, so I got my above use-case working. Good!

But, in order to get screen sharing to work (relying on xdg-desktop-portal et al), I had to make my wayland compositor exec these:

systemctl --user import-environment WAYLAND_DISPLAY
dbus-update-activation-environment WAYLAND_DISPLAY

(not entirely sure if WAYLAND_DISPLAY needs to be injected in both places, or in which if only one)

This broke pinentry-qt's fallback. My above use-case results in (when git trying to sign commit):

error: gpg failed to sign the data
fatal: failed to write commit object

I'm not quite sure of how the calling of the pinentry program works, and why this confuses pinentry. git calls gpg which finds and talks to gpg-agent which invokes pinentry because it needs a passphrase? Does gpg advice gpg-agent about which pinentry to use? Since it could see WAYLAND_DISPLAY/DISPLAY, maybe whether user is on a tty, or so. Or is it more like the pinentry-program inheriting {WAYLAND_,}DISPLAY from gpg-agent, and "trying" to use them and then falling back...

Details

Version
1.2.0

Event Timeline

ikloecker added a subscriber: ikloecker.

pinentry does the following to check if it's running in a GUI session:

// check a few environment variables that are usually set on X11 or Wayland sessions
const bool hasWaylandDisplay = qEnvironmentVariableIsSet("WAYLAND_DISPLAY");
const bool isWaylandSessionType = qgetenv("XDG_SESSION_TYPE") == "wayland";
const bool hasX11Display = pinentry_have_display(argc, argv);
const bool isX11SessionType = qgetenv("XDG_SESSION_TYPE") == "x11";
const bool isGUISession = hasWaylandDisplay || isWaylandSessionType || hasX11Display || isX11SessionType;

i.e. it checks if a few environment variables are set or have a specific value.

Tell git to call gpg with the arguments --pinentry-mode loopback. Then gpg will ask for the passphrase in the terminal.

It looks like having it set will stop fallback from working entirely? Would you say that this cannot be fixed if WAYLAND_DISPLAY is set like I do above?

I guess I'm still not sure about how pinentry is called. But now it sounds more like it is called in the context of the user application, like git using gpg, and inherits their environment?

The gpg --pinentry-mode loopback workaround is good to have, thank you! Then I can at least manage without changing pinentry-program and restarting gpg-agent. But, when I have my ssh-keys also in gpg-agent, I might be out of luck, or is there some other workaround? Something you can tell gpg-agent or so?

It looks like having it set will stop fallback from working entirely? Would you say that this cannot be fixed if WAYLAND_DISPLAY is set like I do above?

Yes, if the WAYLAND_DISPLAY environment variable is set for pinentry, then it assumes that the display server can be used.

I guess I'm still not sure about how pinentry is called. But now it sounds more like it is called in the context of the user application, like git using gpg, and inherits their environment?

pinentry is invoked by gpg-agent. Usually, programs that use gpg-agent (e.g. gpg or Kleopatra via gpgme) pass the DISPLAY variable to gpg-agent which it forwards to pinentry. This way gpg-agent/pinentry knows which display to use even if gpg-agent itself was started without the DISPLAY variable.

The gpg --pinentry-mode loopback workaround is good to have, thank you! Then I can at least manage without changing pinentry-program and restarting gpg-agent. But, when I have my ssh-keys also in gpg-agent, I might be out of luck, or is there some other workaround? Something you can tell gpg-agent or so?

I don't know. I think, I haven't fully understood what your use cases are. You use screen sharing (To do what? To use a GUI program on remote system B on the local system A?) and ssh to some system (You ssh from A to B and use git on B and this fails?).

Maybe it's better to explain what you are trying to do on the gnupg-users mailing list. There are many people on this list who use gpg remotely in different ways and they might have much better ideas how to solve your use cases than me.