Ssh – Connecting SSH and Git to gpg-agent

gpggpg-agentsmartcardssh

I'm running a YubiKey NEO with the OpenPGP applet to store my GPG keys on the smart card. I've stopped all other SSH and GPG agents manually by removing their startup entries (On elementary OS Luna, Ubuntu 12.04).

I've then started the scdaemon process, making sure that its environment variable is exported:

$ scdaemon --daemon
SCDAEMON_INFO=/tmp/gpg-zKwfGU/S.scdaemon:13142:1; export SCDAEMON_INFO;
$ SCDAEMON_INFO=/tmp/gpg-zKwfGU/S.scdaemon:13142:1; export SCDAEMON_INFO;

I then started the gpg-agent process, again making sure that the environment variables are exported:

$ gpg-agent --enable-ssh-support --daemon --write-env-file "${HOME}/.gpg-agent-info" 
GPG_AGENT_INFO=/tmp/gpg-9UaXHX/S.gpg-agent:13322:1; export GPG_AGENT_INFO;
SSH_AUTH_SOCK=/tmp/gpg-WAYxYZ/S.gpg-agent.ssh; export SSH_AUTH_SOCK;
SSH_AGENT_PID=13322; export SSH_AGENT_PID;
$ GPG_AGENT_INFO=/tmp/gpg-9UaXHX/S.gpg-agent:13322:1; export GPG_AGENT_INFO;
$ SSH_AUTH_SOCK=/tmp/gpg-WAYxYZ/S.gpg-agent.ssh; export SSH_AUTH_SOCK;
$ SSH_AGENT_PID=13322; export SSH_AGENT_PID;

I now go to connect to my SSH server:

$ ssh user@myhost.net
Permission denied (publickey).

Weird.

If I try running the ssh process from gpg-agent like so, it just works™:

$ gpg-agent --enable-ssh-support --daemon ssh user@myhost.net

It prompts me for my PIN using pinentry, just as expected, and the connection succeeds.

What am I missing in order to be able to use my smart card as an SSH key, seamlessly? Is there a way to make sure that I don't have to prefix calls to ssh with gpg-daemon? I know I could make a Bash alias, but I don't think that really solves the problem.


Update

I've found that a part of the problem is that gpg-agent starts on its own without --enable-ssh-support, which seems to be a part of the problem. I don't see it in Startup Applications inside of the System Control Panel, but it starts on its own as my login user. It's not inside of /etc/xdg/autostart. Where can I find this and disable it? In my startup applications in the meantime, I just run:

killall -9 gpg-agent && gpg-agent --enable-ssh-support --daemon \
    --sh --write-env-file=$HOME/.gpg-agent-info

I then source that file and export its environment variables and it just works.

My ~/.gnupg/gpg-agent.conf already contains a line enable-ssh-support, but it seems to not be having an effect.

How can I stop the other gpg-agent process from starting on login?

Best Answer

As it turns out, the gpg-agent process started by X doesn't load the right configuration file and therefore doesn't enable SSH support, which breaks things. Here's the file as provided by the gpg-agent DEB package:

/etc/X11/Xsession.d/90gpg-agent:

: ${GNUPGHOME=$HOME/.gnupg}

GPGAGENT=/usr/bin/gpg-agent
PID_FILE="$GNUPGHOME/gpg-agent-info-$(hostname)"

if grep -;s '^[[:space:]]*use-agent' "$GNUPGHOME/gpg.conf" "$GNUPGHOME/options" &&
    test -x $GPGAGENT &&
    { test -z "$GPG_AGENT_INFO" || ! $GPGAGENT 2>/dev/null ; }; then

    if [ -r "$PID_FILE" ]; then
        . "$PID_FILE"
    fi

    # Invoking gpg-agent with no arguments exits successfully if the agent
    # is already running as pointed by $GPG_AGENT_INFO
    if ! $GPGAGENT 2>/dev/null; then
        STARTUP="$GPGAGENT --daemon --sh --write-env-file=$PID_FILE $STARTUP"
    fi
fi

I've replaced this script with something much more simple and effective:

if [ ! -z "$(pgrep gpg-agent)" ]; then
    $GPGAGENT --daemon --enable-ssh-support --sh --write-env-file=$PID_FILE
fi

This will ensure that SSH support is always present. I'm not sure why gpg-agent wasn't looking at ~/.gnupg/gpg-agent.conf to enable SSH support, but this solution works, so I'm happy.

Related Question