#869416 pinentry-gtk2: fails to request passphrase when importing OpenPGP secret key with Seahorse

Package:
gcr
Source:
gcr
Description:
GNOME crypto services (daemon and tools)
Submitter:
Date:
2023-04-26 15:00:03 UTC
Severity:
normal
Tags:
#869416#5
Date:
2017-07-23 11:02:34 UTC
From:
To:
Hi,

both on Tails 3.0.1 (Stretch) and current Debian sid (GNOME), if
/usr/bin/pinentry-gtk-2 is configured as the pinentry tool with
update-alternatives (or pinentry-program in gpg-agent.conf), then
importing a passphrase-protected secret key from Seahorse fails.

Seahorse says:

  Import failed: key 0x...: public key "uid <email>" imported

And the Journal says:

  gpg-agent[11835]: starting a new PIN Entry
  gpg-agent[11835]: DBG: connection to PIN entry established
  gpg-agent[11835]: DBG: chan_6 -> INQUIRE PINENTRY_LAUNCHED 11914 gtk2:curses 1.0.0 ? ? ?
  gpg-agent[11835]: DBG: chan_6 <- END
  gpg-agent[11835]: DBG: error calling pinentry: Inappropriate ioctl for device <Pinentry>
  gpg-agent[11835]: command 'IMPORT_KEY' failed: Inappropriate ioctl for device <Pinentry>
  gpg-agent[11835]: DBG: chan_6 -> ERR 83918950 Inappropriate ioctl for device <Pinentry>
  gpg-agent[11835]: DBG: chan_6 <- [eof]

Note that:

 * This problem doesn't happen when using pinentry-gnome3.
   The difference I see in gpg-agent's debug log is that when using
   pinentry-gnome3, I see a number of OPTION commands sent to
   gpg-agent, e.g. OPTION display=:1, while I see no such thing when
   using pinentry-gtk-2. I'm not sure who's responsible for sending
   these options.

 * Importing the same key with gpg on the command line in GNOME
   Terminal works just fine: the expected pinentry-gtk2 dialog is
   displayed and the key is imported as a result.

 * This might be a bug in Seahorse, or in some underlying plumbing it
   uses, or in pinentry-gtk2.

Details and some initial research:
https://labs.riseup.net/code/issues/12733

Anything else I should try?

#869416#10
Date:
2017-07-25 02:39:24 UTC
From:
To:
Hello,

intrigeri@debian.org writes:

I guess that pinentry is invoked with no DISPLAY and no GPG_TTY.  It
failed to open window, and then, it failed at isatty (3), then return
ENOTTY (its error string: "Inappropriate ioctl for device").

When DISPLAY is there for gpgme, gpgme sends "OPTION display=:1" to
gpg-agent.

Does Seahorse have DISPLAY env var?

I think that gpg has DISPLAY env var under GNOME Terminal.

#869416#15
Date:
2017-07-30 18:23:36 UTC
From:
To:
Hi!

Thanks for your fast answer! My replies are inline below.

NIIBE Yutaka:

OK, this makes sense :)

Apparently yes:

  $ tr '\0' '\n' <  /proc/$(pgrep seahorse)/environ | grep -E '^(GPG|DISPLAY)'
  DISPLAY=:1
  GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1

Anything else I should try? Something about $GPG_TTY, or starting
Seahorse from GNOME Terminal (instead of the GNOME Overview), perhaps?

Cheers,

#869416#20
Date:
2017-07-31 02:21:08 UTC
From:
To:
Thanks for your reply.

intrigeri <intrigeri@debian.org> wrote:

It seems that the most likely case is the following scenario:

  (1) Upon login, gpg-agent is invoked with no DISPLAY.
  (2) While Sheahorse has DISPLAY and invokes gpg by gpgme,
      gpg connects to existing gpg-agent.
  (3) Because gpg-agent has no DISPLAY, when gpg-agent invokes
      pinentry, it fails at isatty(3).

Could you please try this?

  $ gpg-connect-agent updatestartuptty /bye

It should be done from your GNOME Terminal, before importing key by
Seahorse.  It updates variables of DISPLAY and TTY in gpg-agent.

#869416#25
Date:
2017-08-11 22:48:43 UTC
From:
To:
Hi again!

NIIBE & I just spent some time debugging this. After some strace &
shell wrapping fun, we identified that for some reason, gpg-agent runs
pinentry-gtk2 without $DISPLAY set in its environment, although it
(gpg-agent) does have $DISPLAY in its own environment according to
/proc/$(pgrep gpg-agent)/environ.

Pointing pinentry-program to a shell wrapper that exports DISPLAY=:0
before exec'ing pinentry-gtk-2 works around the problem.

So I'm reassigning this to gnupg-agent, where the root cause of the
problem seems to live.

Thanks a lot :)

#869416#38
Date:
2017-08-11 20:54:40 UTC
From:
To:
Hi,

NIIBE Yutaka:

This doesn't seem to be the case:

  # tr '\0' '\n' <  /proc/$(pgrep gpg-agent)/environ | grep -E '^(GPG|DISPLAY|TTY)'
  DISPLAY=:0

I've verified that this gpg-agent is the one running as the desktop
user (/usr/bin/gpg-agent --supervised). This might invalidate the next
steps of this hypothesis i.e.:

I've tried. But then I see no relevant change to gpg-agent's
environment:

  # tr '\0' '\n' <  /proc/$(pgrep gpg-agent)/environ | grep -E '^(GPG|DISPLAY|TTY)'
  DISPLAY=:0

debug-all:

  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK Pleased to meet you, process 2130
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- RESET
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- OPTION ttyname=/dev/pts/2
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- OPTION ttytype=xterm-256color
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- OPTION display=:0
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- OPTION putenv=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- OPTION lc-ctype=fr_FR.UTF-8
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- OPTION lc-messages=fr_FR.UTF-8
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- updatestartuptty
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 -> OK
  Aug 11 22:47:34 gpg-agent[2069]: DBG: chan_8 <- [eof]

… and then the key importation fails in the exact same way as before:
I'm not asked for the passphrase and the debug-all logs are the same :(

FWIW I've tried both on GNOME/X.Org and GNOME/Wayland (up-to-date sid).

Cheers,

#869416#43
Date:
2017-08-17 09:46:27 UTC
From:
To:
intrigeri <intrigeri@debian.org> wrote:

It seems for me that gpg-agent can not do anything for this bug.

I tried to locate the invocation of "gpg" from seahorse.  I figured out
that when this issue occurred (replacing gpg by shell script), it was
invoked by something like

	gpg --status-fd 20 --import

and environment variables are only LOCALE and PWD.  This is the cause of
the problem;  Environment variables (like GPG_TTY, DISPLAY) should be
provided by the parent process.

Also, I ran "seahorse" with the setting of:

    export GPGME_DEBUG=9:/tmp/gpgme.log

... and I realized that the invocation of gpg --import is not through
gpgme.

Then, I found: in seahorse/src/seahorse-import-dialog.c, there is a call
to function gcr_import_button_new.  I think that this is the function to
create the "Import" button in the particular dialog.

Now, I guess that the problem is in the implementaiton of libgcr library.

While I'm reading gcr-3.20.0/gcr/gcr-gnupg-process.c, getting the source
by apt source libgcr-base-3-1, I suspect the function
_gcr_gnupg_process_run_async, which doesn't provide GPG_TTY and/or
DISPLAY to "gpg" process.

#869416#48
Date:
2017-08-18 03:43:57 UTC
From:
To:
NIIBE Yutaka <gniibe@fsij.org> wrote:

Attached is a patch for gcr to fix this issue.  When I apply this patch
to build libgcr-base-3-1 package (and install), the problem of seahorse
has gone.

I also created a ticket for GnuPG upstream to improve its documentation:

https://dev.gnupg.org/T3353

I put the patch in public domain, or it may be distributed
under the licence of LGPL-2.1+.

#869416#57
Date:
2017-09-03 10:17:40 UTC
From:
To:
NIIBE Yutaka:

Amazing, thanks! I'm going to forward this bug report + your patch upstream.

Cheers,

#869416#72
Date:
2017-09-11 12:47:33 UTC
From:
To:
Hi NIIBE!

intrigeri:

The upstream maintainer says that adding a dependency on GTK+ is not
a option, and suggests another (probably simpler) approach:
https://bugzilla.gnome.org/show_bug.cgi?id=787543#c1

Can you please take a look, and maybe attach an updated patch?

Also, I can act as a proxy between you/Debian and Stef/GNOME if you
want, but it would be simpler if you could reply directly on the GNOME
bugzilla, so please consider adding yourself to the CC list there :)

Cheers,

#869416#79
Date:
2017-09-27 01:51:41 UTC
From:
To:
intrigeri <intrigeri@debian.org> wrote:

OK.

Attached is updated patch for gcr to fix this issue, by simply supplying
parent's environ untouched, intended to be put under debian/patches/.
While this patch fixes the particular issue, I think that more clean up
will be needed, perhaps.

The function g_spawn_async_with_pipes let inherit child process parent's
environ when envp=NULL.  By the change, _gcr_gnupg_process_run_async
does so for its envp, when GCR_GNUPG_PROCESS_RESPECT_LOCALE is
specified.

I put the patch in public domain, or it may be distributed
under the licence of LGPL-2.1+.

It is tested by seahorse and pinentry-gtk-2.

#869416#90
Date:
2022-07-23 10:21:11 UTC
From:
To:
Hi,

NIIBE Yutaka (2017-09-27):

Thanks! I noticed, a few years later, that this patch had not been
proposed upstream, so I added it to
https://gitlab.gnome.org/GNOME/gcr/-/issues/80.

Cheers,