Page MenuHome GnuPG

pinentry-gnome3 requires DBUS_SESSION_BUS_ADDRESS to be updated
Closed, ResolvedPublic

Description

pinentry-gnome3 is not working for me, because I am using a separate DBUS
session (via eval "$(dbus-launch)"), and pinentry-gnome3 will use the main
DBUS session:

dbus-daemon[1178]: [session uid=1000 pid=1178] Activating service name='org.gnome.keyring.SystemPrompter' requested by ':1.19' (uid=1000 pid=3259 comm="pinentry-gnome3 --display :1 ")
org.gnome.keyring.SystemPrompter[1178]: Unable to init server: Could not connect: Connection refused

This started to happen recently for me because of a change in Arch Linux'
pinentry package, which prefers pinentry-gnome3 now instead of pinentry-gtk-2
(https://git.archlinux.org/svntogit/packages.git/commit/trunk?h=packages/pinentry&id=6e03488e1a857d9e000c28224cea5b516e664068).

The following patch fixes this, by also adding "DBUS_SESSION_BUS_ADDRESS" (from
the session) to the copied startup env:

diff --git i/agent/gpg-agent.c w/agent/gpg-agent.c
index bd9a471e8..8502e31b8 100644
--- i/agent/gpg-agent.c
+++ w/agent/gpg-agent.c
@@ -1980,7 +1980,7 @@ gpg_error_t
 agent_copy_startup_env (ctrl_t ctrl)
 {
   static const char *names[] =
-    {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL};
+    {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", "DBUS_SESSION_BUS_ADDRESS", NULL};
   gpg_error_t err = 0;
   int idx;
   const char *value;

Maybe this should handle all/more variables from stdenvnames though, assuming
that this is the correct fix.

"DBUS_SESSION_BUS_ADDRESS" is included in stdenvnames, which gets used in the
at_fork callback in agent/call-pinentry.c:213:

static void
atfork_cb (void *opaque, int where)
{
  ctrl_t ctrl = opaque;

  if (!where)
    {
      int iterator = 0;
      const char *name, *assname, *value;

      gcry_control (GCRYCTL_TERM_SECMEM);

      while ((name = session_env_list_stdenvnames (&iterator, &assname)))
        {
          /* For all new envvars (!ASSNAME) and the two medium old
             ones which do have an assuan name but are conveyed using
             environment variables, update the environment of the
             forked process.  */
          if (!assname
              || !strcmp (name, "XAUTHORITY")
              || !strcmp (name, "PINENTRY_USER_DATA"))
            {
              value = session_env_getenv (ctrl->session_env, name);
              if (value)
                gnupg_setenv (name, value, 1);
            }
        }
    }
}

For reference: I am using gpg-connect-agent UPDATESTARTUPTTY /bye to update
the envvars, of course.

Stack trace to start_pinentry:

#0  start_pinentry (ctrl=0x5555557d6fd0) at call-pinentry.c:278
#1  0x00005555555733ba in agent_askpin (ctrl=0x5555557d6fd0, 
    desc_text=0x7ffff0009310 "Please enter the passphrase for the ssh key …", prompt_text=0x0, 
    initial_errtext=0x0, pininfo=0x7ffff7fef2b0, keyinfo=0x7ffff6cbd940 "A648BB3BFD9B2779D1F79783A6A95D39ECB83437", cache_mode=CACHE_MODE_SSH) at call-pinentry.c:1015
#2  0x00005555555771f5 in unprotect (ctrl=0x5555557d6fd0, cache_nonce=0x0, 
    desc_text=0x7ffff0009310 "Please enter the passphrase for the ssh key …", keybuf=0x7ffff6cbda00, 
    grip=0x5555557d7060 "\246H\273;\375\233'y\321\367\227\203\246\251]9\354\270\064\067\001", cache_mode=CACHE_MODE_SSH, lookup_ttl=0x55555556c3cd <ttl_from_sshcontrol>, r_passphrase=0x0)
    at findkey.c:634
#3  0x0000555555577d97 in agent_key_from_file (ctrl=0x5555557d6fd0, cache_nonce=0x0, desc_text=0x5555555b0e58 "Please enter the passphrase for the ssh key%%0A  %F%%0A  (%c)", 
    grip=0x5555557d7060 "\246H\273;\375\233'y\321\367\227\203\246\251]9\354\270\064\067\001", shadow_info=0x7ffff6cbdb18, cache_mode=CACHE_MODE_SSH, 
    lookup_ttl=0x55555556c3cd <ttl_from_sshcontrol>, result=0x7ffff6cbdaf8, r_passphrase=0x0) at findkey.c:926
#4  0x0000555555579eea in agent_pksign_do (ctrl=0x5555557d6fd0, cache_nonce=0x0, desc_text=0x5555555b0e58 "Please enter the passphrase for the ssh key%%0A  %F%%0A  (%c)", 
    signature_sexp=0x7ffff6cbdbe0, cache_mode=CACHE_MODE_SSH, lookup_ttl=0x55555556c3cd <ttl_from_sshcontrol>, overridedata=0x0, overridedatalen=0) at pksign.c:312
#5  0x000055555556f838 in data_sign (ctrl=0x5555557d6fd0, spec=0x7ffff6cbdce0, hash=0x0, hashlen=0, r_sig=0x7ffff6cbdcd0, r_siglen=0x7ffff6cbdcd8) at command-ssh.c:2815
#6  0x000055555556fd6d in ssh_handler_sign_request (ctrl=0x5555557d6fd0, request=0x7ffff000af50, response=0x7ffff000c720) at command-ssh.c:2965
#7  0x0000555555570cf8 in ssh_request_process (ctrl=0x5555557d6fd0, stream_sock=0x7ffff0000b90) at command-ssh.c:3550
#8  0x00005555555710d8 in start_command_handler_ssh (ctrl=0x5555557d6fd0, sock_client=9) at command-ssh.c:3734
#9  0x0000555555562816 in start_connection_thread_ssh (arg=0x5555557d6fd0) at gpg-agent.c:2796
#10 0x00007ffff7486bec in ?? () from /usr/lib/libnpth.so.0
#11 0x00007ffff726e0bc in start_thread () from /usr/lib/libpthread.so.0
#12 0x00007ffff6fa32ff in clone () from /usr/lib/libc.so.6

To summarize:

The agent is supervised by systemd --user, and this has its own bus (the one
you get by default), but I am using eval "$(dbus-launch)" then, because I
have multiple X sessions, and an own DBUS session bus helps with separating
them.
The problem is that pinentry is getting launched by the supervised agent, not
the gnupg cli, and therefore uses the wrong/old DBUS_SESSION_BUS_ADDRESS.

  1. I've also noted that the following patch seems to never have been applied to the master branch?!

https://dev.gnupg.org/rG751b287179c3a485261051a8bc838ee9405fa890
It looks relevant in this context, but agent_send_all_options does not seem to
be involved in my use case(s) at least.

Details

Version
2.2.6