Bug#778657: [Pkg-gnupg-maint] Bug#778657: gnupg-agent: Test for existing gpg-agent in /etc/X11/Xsession.d/90gpg-agent is always true

2015-06-30 Thread Daniel Kahn Gillmor
Control: severity 778657 normal
Control: done 778657 2.0.26-4

Hi Brian--

Sorry to take a while to get back to you on this.  I don't think these
changes are appropriate for the /etc/X11/Xsession.d/90gpg-agent and i
think some of your analysis of the (admittedly baroque) code is mistaken
(see discussion below), so i'm closing this bug because i think there's
nothing to do for it.

If you think my analysis below is mistaken, please reopen the bug and
explain what you think should happen next!

On Tue 2015-02-17 19:40:45 -0500, Brian C. Duggan wrote:
 The gpg-agent Xsession.d script looks as if it wants to test for an
 existing, usable gpg-agent. It looks as if it is supposed to skip
 starting a new one for the X session if it finds an existing gpg-agent
 process.

That's right.  If an existing process provides gpg-agent (and indicates
it with the $GPG_AGENT_INFO environment variable), the Xsession.d script
should avoid starting up a new agent.

 I wanted to use this functionality to run gpg-agent as a user service
 under systemd as the sole gpg-agent process for all my sessions. I set
 up and enabled the service. systemd starts all enabled user services
 on the first user login. I logged in on a virtual console and verified
 that gpg-agent was running and I could connect to it. Then I logged in
 to an X session and noticed that X had still started its own
 gpg-agent.

We don't currently recommend running gpg-agent as a systemd user
service, for a number of reasons.

 * gpg-agent is likely to change over to --use-standard-socket by
   default.  This is probably incompatible with multiple systemd user
   sessions running concurrently.

 * gpg2 and related tools that need to talk to the agent will also soon
   start auto-launching the daemon when it is needed but not present.

I can understand the desire to have all of this session-oriented stuff
managed by a real distinct session manager, but that's not where gnupg
is at right now.

(btw, if you want to work on getting gpg-agent to function as a systemd
service, i'd be keen to see that happen.  But i think there may be some
tricky issues with it, like the ones described above.  Please come talk
to us at pkg-gnupg-ma...@lists.alioth.debian.org or on #debian-gnupg
about it.)

 The code that looks like it should check for gpg-agent is here:

 /etc/X11/Xsession.d/90gpg-agent:
 6: if grep -qs '^[[:space:]]*use-agent' $GNUPGHOME/gpg.conf 
 $GNUPGHOME/options 
 7:test -x $GPGAGENT 
 8:{ test -z $GPG_AGENT_INFO || ! $GPGAGENT 2/dev/null; }; then

 GPGAGENT=/usr/bin/gpg-agent

 When run without arguments, gpg-agent's exit status will be 0 if it
 can connect to an existing gpg-agent process, a positive value if it
 cannot. Regardless of exit status, gpg-agent run without arguments
 writes all output to stderr.

 So, the second part of the expression in line 8 is alwys true.  The
 output of '$GPAGENT 2/dev/null' is always an empty string because
 gpg-agent sends all output to stderr. [ !  ] is true.

but we're not in [ (test) here.  the test invocation applies to:

   -z $GPG_AGENT_INFO

then || is a shell conjunction which splits the test from the second
half, which is just looking at the return value of an invocation of
$GPGAGENT.

 So, the entire expression on line 8 is always true. But in my testing,
 I also couldn't configure X so that it passed environment variables to
 the X session. I wrote a .xsession file like this:

 #!/bin/sh
 export MYTESTVAR=test
 eval startxfce4

 and then added 'echo $MYTESTVAR  /tmp/mytestvar' to 90gpg-agent. But
 the corresponding echo-to-file statement in 90gpg-agent never wrote
 anything. Am I missing an obvious method of passing $GPG_AGENT_INFO to
 90gpg-agent?

This would normally be done by an earlier stage of the Xsession.d
directory, or by pam hooks that were triggered during gdm login.  by the
time your .xsession is invoked, the rest of Xsession.d/ has already been
sourced.

Lastly, i think ~/.gnupg/.gpg-agent-info is deprecated upstream, so
changing the Xsession.d/ script to depend more heavily on it would be
problematic, even if the rest of the analysis were correct.

Let me know if you have any more questions.

Regards,

--dkg


signature.asc
Description: PGP signature


Bug#778657: gnupg-agent: Test for existing gpg-agent in /etc/X11/Xsession.d/90gpg-agent is always true

2015-02-17 Thread Brian C. Duggan
Package: gnupg-agent
Version: 2.0.26-4
Severity: important
Tags: patch

Dear Maintainer,

The gpg-agent Xsession.d script looks as if it wants to test for an existing, 
usable gpg-agent. It looks as if it is supposed to skip starting a new one for 
the X session if it finds an existing gpg-agent process.

I wanted to use this functionality to run gpg-agent as a user service under 
systemd as the sole gpg-agent process for all my sessions. I set up and enabled 
the service. systemd starts all enabled user services on the first user login. 
I logged in on a virtual console and verified that gpg-agent was running and I 
could connect to
it. Then I logged in to an X session and noticed that X had still started its 
own gpg-agent.

The code that looks like it should check for gpg-agent is here:

/etc/X11/Xsession.d/90gpg-agent:
6: if grep -qs '^[[:space:]]*use-agent' $GNUPGHOME/gpg.conf 
$GNUPGHOME/options 
7:test -x $GPGAGENT 
8:{ test -z $GPG_AGENT_INFO || ! $GPGAGENT 2/dev/null; }; then

GPGAGENT=/usr/bin/gpg-agent

When run without arguments, gpg-agent's exit status will be 0 if it can connect 
to an existing gpg-agent process, a positive value if it cannot. Regardless of 
exit status, gpg-agent run without arguments writes all output to stderr.

So, the second part of the expression in line 8 is alwys true. The output of 
'$GPAGENT 2/dev/null' is always an empty string because gpg-agent sends all 
output to stderr. [ !  ] is true.

So, the entire expression on line 8 is always true. But in my testing, I also 
couldn't configure X so that it passed environment variables to the X session. 
I wrote a .xsession file like this:

#!/bin/sh
export MYTESTVAR=test
eval startxfce4

and then added 'echo $MYTESTVAR  /tmp/mytestvar' to 90gpg-agent. But the 
corresponding echo-to-file statement in 90gpg-agent never wrote anything. Am I 
missing an obvious method of passing $GPG_AGENT_INFO to 90gpg-agent?

If the intent of line 8 is to keep each X session from starting its own 
gpg-agent if another gpg-agent is running and connectable, then the script 
should test the return value of gpg-agent without arguments, not the output. If 
there are no ways to pass environment to startx or startxfce4, then 90gpg-agent 
will also have to attempt to load $HOME/.gpg-agent-info.

I made those changes my 90gpg-agent file, inline. I also attached the changes 
as a patch to gnupg2/debian/gnupg-agent.xsession.

Thanks,
Brian

-- System Information:
Debian Release: 8.0
  APT prefers testing-updates
  APT policy: (500, 'testing-updates'), (500, 'testing')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages gnupg-agent depends on:
ii  libassuan02.1.2-2
ii  libc6 2.19-13
ii  libgcrypt20   1.6.2-4+b1
ii  libgpg-error0 1.17-3
ii  libpth20  2.0.7-20
ii  libreadline6  6.3-8+b3
ii  pinentry-gtk2 [pinentry]  0.8.3-2

Versions of packages gnupg-agent recommends:
ii  gnupg   1.4.18-6
ii  gnupg2  2.0.26-4

gnupg-agent suggests no packages.

-- Configuration Files:
/etc/X11/Xsession.d/90gpg-agent changed:
: ${GNUPGHOME=$HOME/.gnupg}
GPGAGENT=/usr/bin/gpg-agent
PID_FILE=$GNUPGHOME/gpg-agent-info-$(hostname)
INFO_FILE=$HOME/.gpg-agent-info
if test -f $INFO_FILE; then
   eval $(cat $INFO_FILE)
   # Exports GPG_AGENT_INFO, SSH_AUTH_SOCK, etc.
   eval $(cut -d= -f 1  $INFO_FILE | xargs echo export)
fi
if test -x $GPGAGENT; then
   # Invoking gpg-agent with no arguments exits successfully if the agent
   # is already running as pointed by $GPG_AGENT_INFO
   $GPGAGENT 2/dev/null
   GPGAGENT_RUNNING=$?
else
   GPGAGENT_RUNNING=1
fi
if grep -qs '^[[:space:]]*use-agent' $GNUPGHOME/gpg.conf $GNUPGHOME/options 

   ( test -z $GPG_AGENT_INFO || $GPGAGENT_RUNNING -gt 0 ); then
   if [ -r $PID_FILE ]; then
   . $PID_FILE
   fi
   STARTUP=$GPGAGENT --daemon --sh --write-env-file=$PID_FILE $STARTUP
fi


-- no debconf information
diff --git a/debian/gnupg-agent.xsession b/debian/gnupg-agent.xsession
index eb8c5847..7ecaefe2 100644
--- a/debian/gnupg-agent.xsession
+++ b/debian/gnupg-agent.xsession
@@ -2,18 +2,29 @@
 
 GPGAGENT=/usr/bin/gpg-agent
 PID_FILE=$GNUPGHOME/gpg-agent-info-$(hostname)
+INFO_FILE=$HOME/.gpg-agent-info
+
+if test -f $INFO_FILE; then
+   eval $(cat $INFO_FILE)
+   # Exports GPG_AGENT_INFO, SSH_AUTH_SOCK, etc.
+   eval $(cut -d= -f 1  $INFO_FILE | xargs echo export)
+fi
+
+if test -x $GPGAGENT; then
+   # Invoking gpg-agent with no arguments exits successfully if the agent
+   # is already running as pointed by $GPG_AGENT_INFO
+   $GPGAGENT 2/dev/null
+   GPGAGENT_RUNNING=$?
+else
+   GPGAGENT_RUNNING=1
+fi
 
 if grep -qs '^[[:space:]]*use-agent' $GNUPGHOME/gpg.conf $GNUPGHOME/options 
-   test -x $GPGAGENT 
-   { test -z $GPG_AGENT_INFO