expected behavior unclear when using gpg from ssh on a machine with a running X11 session
Open, NormalPublic

Description

see https://bugs.debian.org/842015

A user logs into a graphical workstation, and leaves themselves logged in.

they move away from the workstation, but later ssh into the same workstation and
try to use gpg from the ssh session, which isn't connected to the graphical
display at all.

What is the expected behavior, given that gpg itself won't prompt the user for a
passphrase?

Details

Version
gnome
dkg set Version to 2.1.15.
dkg added a subscriber: dkg.
werner added a subscriber: werner.Nov 5 2016, 3:26 PM

They need to run

gpg-connect-agent updatestartuptty /bye

to tell gpg-agent where to open the Pinentry. Depending on how they log in
either a curses or GUI Pinentry will be shown. I.e.

  ssh -X example.org
  gpg-connect-agent updatestartuptty /bye
  gpg --decrypt ....

shows a GUI Pinentry. If -X is not used the curses pinentry comes up.

dkg added a comment.Nov 5 2016, 11:12 PM

In your example, i don't think updatestartuptty is necessary for text-mode
prompting -- the "gpg --decrypt …" process will be able to detect which tty it
is connected to and pass it to the agent.

But the question here has to do with graphical consoles as well, and i don't
think there's a clear answer yet.

There are two X11 graphical sessions in the example:

a) the local machine's graphical console, where the user is currently sitting,
running ssh *to* the remote machine
b) the remote machine's graphical console, where the user is logged in, but idle

There are also three kinds of pinentry user-attention-getting mechanisms:

0) terminal

  1. X11
  2. d-bus

finally, i'll note that there are (at least) two d-bus user sessions running in
this example: on the remote host and on the local host. I'm assuming in this
example that the user has a single shared d-bus session across all logins on the
computer (this is the dbus-user-session model, which is well-aligned with the
gpg-agent standard-socket model, where there is one running process per user per
machine)

Since "ssh -X remote" forwards the X11 session but not the d-bus session, any
d-bus-based pinentry (like pinentry-gnome3) will connect to the d-bus session on
the remote machine. But the d-bus session on the remote machine is *also*
connected to the remote graphical (X11) console.

pinentry on the remote machine has two choices:

x) talk to the d-bus session it is connected to (which will trigger a prompt on
the remote graphical console, or
y) fall back to curses

If it chooses (x) then the user is unlikely to see the prompt (they're not
sitting in front of that graphical console). But it's not clear how to
distinguish the situation from normal use in order to choose (y).

Perhaps gcr needs to refuse to prompt in the event that the graphical session is
known-idle/locked (in screensaver mode, whatever). Then the pinentry could know
to fall back to the tty because of the locked screen. If it does that, then the
error case (where the graphical prompt is shown on the idle session) is limited
to situations where the user left the remote graphical console unlocked. I
don't know whether we can get gcr to report that successfully or not, though.

dkg added a comment.Nov 6 2016, 6:37 AM

Perhaps gcr needs to refuse to prompt in the event that the graphical session is
known-idle/locked (in screensaver mode, whatever). Then the pinentry could know
to fall back to the tty because of the locked screen.

I just spent a while trying to research this, and i'm afraid that the code i've
written to detect whether gcr is available does nothing to detect whether the
screen is currently locked.

Furthermore, when "getpin" is called against a dbus session that is locked, it
immediately returns with a "Cancelled" message, in a way that is pretty
difficult to diagnose.

However, it looks like i can query the gnome screensaver via dbus to see whether
the screen is locked. From the command line, that's:

dbus-send --print-reply=literal --session --dest=org.gnome.ScreenSaver

/org/gnome/ScreenSaver org.gnome.ScreenSaver.GetActive

which returns a boolean true or false depending on whether the screen is locked.

We'd just need to translate it into GDBus, i think, perhaps using something
higher-level like g_dbus_connection_call(), or something lower-level, like
g_dbus_connection_send_message_with_reply() (or their synchronous variants):

file:///usr/share/doc/libglib2.0-doc/gio/GDBusConnection.html#g-dbus-connection-call
file:///usr/share/doc/libglib2.0-doc/gio/GDBusConnection.html#g-dbus-connection-send-message-with-reply

dkg added a comment.Nov 6 2016, 8:18 AM

Attached is a patch to check for locked screensaver and fall back to curses if
detected.

werner added a comment.Nov 6 2016, 6:03 PM

Interesting stuff. My solution wouyld be to switch to the gtk pinetry, but I'll
take care care of your patch tomorrow.

werner claimed this task.Nov 6 2016, 6:03 PM
werner removed a project: gnupg.

Changed category to pinentry - this is a pinentry-gnome (ie. gcr) problem.

werner changed Version from 2.1.15 to gnome.Mar 2 2017, 7:55 PM