Reliably determining that the agent is available and starting it if not

Craig Ringer craig at 2ndquadrant.com
Fri Feb 22 01:21:19 CET 2013


Hi all

I'm scripting gpg to batch re-encrypt some files, and I've run into a
surprising problem I was hoping for some advice on.

I expected it to be simple to make sure that the a GPG agent (either the
"gpg-agent" program or something like Gnome's built-in agent) were
available and usable by gpg before proceeding, so the user doesn't get
buried in repeated password prompts. It's turned out to be anything but,
to the point where I feel I must be missing something.

The root of the problem is that the `gpg-agent' command tests for the
existence of an agent a different way to how `gpg' its self does - and
gpg offers no command line test for agent availability, since
--use-agent is simply ignored if the agent can't be used.

gpg-agent looks for an existing agent socket at $HOME/.gnupg/S.gpg-agent
. If one exists it connects to it to check that the agent is alive. It
does this even if no GPG_AGENT_INFO env var is set. If gpg-agent finds a
running agent it will not write the env file or print the definitions
for GPG_AGENT_INFO to stdout, so you cannot invoke gpg-agent to discover
the details of an already-running agent.

gpg, however, looks only at GPG_AGENT_INFO. If it is not set but
--use-agent is passed, gpg will print the local translation of the
message "gpg-agent is not available in this session" and then continue.
It offers no command line flag like --require-agent. --use-agent --batch
has a similar effect, but cannot be used to add the user's key to the
agent if it's not already cached. There doesn't seem to be an equivalent
of "gpg-add" like ssh's "ssh-add".

What all this means is that there doesn't seem to be a reliable way to
determine how to connect to a running agent if there is one, or start
one if there isn't. This seems like such a basic thing that I'm really
hoping I'm missing something really obvious.

The closest I've come so far is this horror:

if ! test -v GPG_AGENT_INFO; then
    if gpg-agent 2>/dev/null; then
        if test -e /tmp/.gpg-agent-$USER/env; then
            . /tmp/.gpg-agent-$USER/env
        elif test -e ~/.gpg-agent-info; then
            . ~/.gpg-agent-info
        else
            echo 'A gpg agent is running, but we cannot find its socket
info because'
            echo 'the GPG_AGENT_INFO env var is not set and gpg agent
info has not been'
            echo 'written to any expected location. Cannot continue.
Please report this'
            echo 'issue for investigation.'
            exit 5
        fi
    else
        mkdir /tmp/.gpg-agent-$USER
        chmod 700 /tmp/.gpg-agent-$USER
        gpg-agent --daemon --write-env-file /tmp/.gpg-agent-$USER/env
        . /tmp/.gpg-agent-$USER/env
    fi
    # The env file doesn't include an export statement
    export GPG_AGENT_INFO
else
    if ! gpg-agent 2>/dev/null; then
        echo 'GPG_AGENT_INFO is set, but cannot connect to the agent.'
        echo 'Unsure how to proceed, so aborting execution. Please
report this'
        echo 'issue for investigation.'
        exit 5
    fi
fi

This is neither reliable, clean, nor user-friendly. The only real
solution would require that I patch gpg to fall back on the well known
agent socket location if GPG_AGENT_INFO is unset but use-agent is
enabled, or patch gpg-agent to query the existing agent and print
GPG_AGENT_INFO value for it if it's run and an agent already exists.

-- 
 Craig Ringer                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/attachments/20130222/53a6db20/attachment-0001.htm>


More information about the Gnupg-users mailing list