Gpg never asks for password in an X session which had `gpg --decrypt`

This may not sound like a NixOS specific issue but I’m having trouble debugging it, because all solutions suggested for other distros’, don’t help me hence I’m not sure whether this is a NixOS specific issue or GnuPG upstream behaviour change / bug.

Basically, the issue is that gpg acts differently in a bare TTY and in an X session which started with startx.

In a bare tty

If I run gpg --decrypt ... and then pkill gpg-agent I need to reenter my password on the next gpg --decrypt ... - everything is fine.

In an X session

If I login to a certain TTY and run a gpg --decrypt command and then startx, I can’t make the agent forget my password. Even if I kill it from htop it doesn’t ask for a password.

Other Info

I use nixos-unstable and I don’t use any of the available programs.gnupg settings in my configuration.nix.

All of the following commands don’t make a difference for gpg-agent inside an X session:

pkill scdaemon
pkill gpg-agent
gpg-connect-agent /bye >/dev/null 2>&1
gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1
gpgconf --reload gpg-agent

As suggested here: https://unix.stackexchange.com/a/543856/135796

This bothers me because I’ve configured (scripted) my WM to run gpg-connect-agent reloadagent /bye when the screensaver locks the computer. But again, it doesn’t prevent gpg from decrypting files without my password.

1 Like

What WM and Displaymanager are you using?
Have you tried with an unconfigured wm & displaymanager (except for the „gpg-connect-agentwm…“ part) just to see if that works?
and my last idea would be to check if it maybe has something todo with privileges. Are you running some things as root?

tll;dr: enable the programs.gnupg.agent setting. The 20.03 release notes have details.

On unstable had been a breaking change to how gpg works… I am also not very happy about it since it breaks on non-nixos as well as on nixos that never had gpg stuff in the systems configuration.

CC @flokli @fpletz

2019-11-08 (Friday), nixos1@discoursemail.com (Doron Behar via NixOS Discourse):

If I run gpg --decrypt ... and then pkill gpg-agent I need
to reenter my password on the next gpg --decrypt ... -
everything is fine.

How do you run the gpg-agent? Do have gpg launch it on demand
or are you using socket activation?

If I login to a certain TTY and run a gpg --decrypt command
and then startx, I can’t make the agent forget my password.
Even if I kill it from htop it doesn’t ask for a password.

What pinentry program do you use (grep ^pinentry-program ~/.gnupg/gpg-agent.conf)? When the agent loses track of the
session you’re on it may end up spawning the pinentry on a
different terminal, like the one on the console that’s being
assumed by your x session.

Quoting rl-2003.xml:

GnuPG is now built without support for a graphical passphrase entry by default. Please enable the gpg-agent user service via the NixOS option programs.gnupg.agent.enable. Note that upstream recommends using gpg-agent and will spawn a gpg-agent on the first invocation of GnuPG anyway.

I don’t understand what this has to do with OP’s issue of gpg-agent not getting killed.

Tangentially, why doesn’t is support graphical pinentry by default anymore? Does that mean GUI apps won’t ask me for my GPG passphrase anymore?

Thanks for all the comments guys. I’ve opened a bug report in GnuPG’s bug tracker:

https://dev.gnupg.org/T4744

I think I’ve managed to track the issue down to a certain dbus issue I have applied a workaround for a while ago. Unfortunately, disabling that workaround fixes GnuPG’s behaviour but it breaks other applications more severely. I’ll explain:

Back when I’ve initially configured my system, I wanted to use startx as a desktop manager and Awesome as WM. I didn’t want to enable Awesome from my configuration.nix because I wanted to feel the “user freedom” of applying (e.g) overlays to my awesome packages without having to change root owned files.

Then I noticed, that a certain program I spawn in the background of my X sessions - mpd-mpris, doesn’t work as expected: (1) When it’s running I don’t see an mpd player with playerctl -l and (2) when ever I try to rerun it, I see a new dbus-daemon process in htop every time I spawn mpd-mpris.

While investigating that, I noticed that NixOS’ startx doesn’t run these commands:

if test -z "$DBUS_SESSION_BUS_ADDRESS"; then
	eval $(dbus-launch --exit-with-session --sh-syntax)
fi
systemctl --user import-environment DISPLAY XAUTHORITY

if command -v dbus-update-activation-environment >/dev/null 2>&1; then
	dbus-update-activation-environment --all --systemd --verbose
fi

While other desktop managers do run these commands as part of their wrapping of xinit or whatever. Evidence:

I’ve also noticed these commands exist in Arch Linux somewhere in /etc/ by default and there, I’ve had no such problems as with mpd-mpris.

Hence, my workaround was including these dbus commands in my .xinitrc and this has thankfully solved mpd-mpris’ issue. Moreover, I’ve been proven my workaround is correct because according to my tests, with whatever window & desktop managers, $DBUS_SESSION_BUS_ADDRESS has a value in these tested X sessions of something like:

unix:abstract=/tmp/dbus-tFb5MypqHu,guid=a4834e61f0e7d3158e5610d75dc7be4c

Without adding these dbus commands to my .xinitrc, $DBUS_SESSION_BUS_ADDRESS is empty and this explains why e.g mpd-mpris doesn’t know how to connect to dbus and that’s why it spawns a new dbus-daemon every time it tries to run.

When I tried removing these lines from my .xinitrc, I’ve found that gpg asks for passwords also inside X sessions, just like outside of it.

Here are other details I’ve also mentioned in upstream’s bug report:

  • My pinentry-program is /home/doron/.bin/pinentry which is a script I wrote which has:
#!/bin/sh
# BASED ON https://unix.stackexchange.com/a/236747/135796
# choose pinentry depending on PINENTRY_USER_DATA
# requires pinentry-curses and pinentry-gtk2
# this *only works* with gpg 2
# see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=802020

case $PINENTRY_USER_DATA in
	"")
		exec pinentry-tty "$@"
		;;
	curses|emacs|gnome3|gtk-2|qt|tty)
		exec pinentry-${PINENTRY_USER_DATA} "$@"
		;;
	*)
		echo there is no such pinentry program: pinentry-"${PINENTRY_USER_DATA}" >&2
		exit 1
esac

How do you run the gpg-agent? Do have gpg launch it on demand
or are you using socket activation?

  • With either gpg-agent.socket enabled as a systemd user service (when the package gnupg is installed to my user environment) or when I enable the relevant programs.gnupg options, I can always see 1 gpg-agent process in htop.
  • Even if I disable the systemd unit gpg-agent.socket, I see a gpg-agent process spawned whenever I run a gpg command.
  • There is never more then 1 gpg-agent process running, gpg doesn’t allow that.

Perhaps the most interesting detail to mention (also mentioned in upstream’s bug report) is:

  • In systemd’s journal, I can see this log line when I try to reload the agent:
gpg-agent[12823]: Failed to lookup password for key n/A85E4FC6C29CD42DB9DACBB14871FBABAAC9BC95 with secret service: Cannot autolaunch D-Bus without X11 $DISPLAY

What makes the issue a valid upstream’s bug IMO is the fact that for whatever reason the agent doesn’t know how to lookup the password, it allows the decryption without password no matter what.

BTW I’ve also tried running manually gpg-agent (while the systemd service & socket are stopped & disabled) like this:

env -u XAUTHORITY -u DBUS_SESSION_BUS_ADDRESS -u DISPLAY gpg-agent --daemon

But no luck, the password is still never prompted.

2 Likes