gpg-agent sagt, dass Agent existiert, aber gpg sagt, dass Agent nicht existiert?

9

Ich habe mit einigen Problemen zu kämpfen, während ich gpg bashauf einer Debian 6.0.6-Box skripte. Ich habe ein Skript, das eine Reihe von Operationen ausführt und sicherstellen möchte, dass ein GPG-Agent verfügbar ist, bevor er versucht, fortzufahren.

Da gpg-agent keine Maßnahmen ergreift und Erfolg zurückgibt, wenn es gestartet wird, während es bereits ausgeführt wird, ist es so einfach sicherzustellen, dass der Agent vorhanden ist wie:

eval $(gpg-agent --daemon)

gpg-agent starten oder berichten:

gpg-agent[21927]: a gpg-agent is already running - not starting a new one

und 0 zurückgeben (Erfolg), wenn bereits ausgeführt.

Das Problem tritt auf, wenn ein Agent bereits in einer anderen Sitzung ausgeführt wird. gpg-agentsagt, dass es bereits läuft ... aber gpgsein Selbst behauptet dann, dass es nicht verfügbar ist.

$ gpg-agent --version
gpg-agent (GnuPG) 2.0.19
libgcrypt 1.5.0
$ gpg --version
gpg (GnuPG) 1.4.13

$ eval $(gpg-agent --daemon)
gpg-agent[21927]: a gpg-agent is already running - not starting a new one
$ gpg -d demo-file.asc
gpg: gpg-agent is not available in this session

Das macht mich frustriert und verwirrt. Es scheint, dass gpg-agentder Agent auf eine andere Weise erkannt wird, um sich selbst zu gpgieren. Schlimmer noch, es gpggibt keine Möglichkeit zu fragen, ob der Agent skriptfähig verfügbar ist, da er Empfänger mit unbrauchbaren Schlüsseln gerne stillschweigend ignoriert und dennoch Erfolg zurückgibt. Daher ist es sehr schwierig, dieses Problem zu erkennen, bevor der Stapel gestartet wird. Ich möchte unter anderem aus i18n-Gründen nicht auf die Analyse der Ausgabe von gpg eingehen.

Sie können dies reproduzieren, indem Sie sicherstellen, dass kein GPG-Agent ausgeführt oder GPG_AGENT_INFOfestgelegt wurde, und zwar in einem Terminal, das ausgeführt wird, eval $(gpg-agent --daemon)und in einem anderen Terminal , in dem das oben genannte ausgeführt wird. Sie werden feststellen, dass gpg-agent angibt, dass es bereits ausgeführt wird, gpg jedoch keine Verbindung zum Agenten herstellen kann.

Ideen?

UPDATE : gpg-agenterkennt einen anderen Agenten durch die Suche nach einer Socket - Datei in einem gut bekannten Standort und Schreiben , um es zu Test für Lebendigkeit, eine pro dies strace:

socket(PF_FILE, SOCK_STREAM, 0)         = 5
connect(5, {sa_family=AF_FILE, sun_path="/home/craig/.gnupg/S.gpg-agent"}, 32) = 0
fcntl(5, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(5, F_GETFL)                       = 0x2 (flags O_RDWR)
select(6, [5], NULL, NULL, {0, 0})      = 1 (in [5], left {0, 0})
read(5, "OK Pleased to meet you, process "..., 1002) = 38
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f41a3e61000
write(2, "gpg-agent: gpg-agent running and"..., 43gpg-agent: gpg-agent running and available
) = 43

während GnuPG nur die Umgebung zu betrachten scheint und den bekannten Socket-Speicherort ignoriert. In common/simple-pwquery.c:

/* Try to open a connection to the agent, send all options and return
   the file descriptor for the connection.  Return -1 in case of
   error. */
static int
agent_open (int *rfd)
{
  int rc;
  int fd;
  char *infostr, *p;
  struct sockaddr_un client_addr;
  size_t len;
  int prot;
  char line[200];
  int nread;

  *rfd = -1;
  infostr = getenv ( "GPG_AGENT_INFO" );
  if ( !infostr || !*infostr )
    infostr = default_gpg_agent_info;
  if ( !infostr || !*infostr )
    {
#ifdef SPWQ_USE_LOGGING
      log_error (_("gpg-agent is not available in this session\n"));
#endif
      return SPWQ_NO_AGENT;
    }
    /* blah blah blah truncated blah */
}

Ich möchte den Agenten nicht wirklich töten, nur um sicherzustellen, dass ich ihn erneut starten kann, und es gibt keinen Standardort, an dem der Agent des Benutzers möglicherweise eine Umgebungsdatei schreibt. Schlimmer noch, ich kann nicht einmal Test auf das Vorhandensein von GPG_AGENT_INFOin der Umwelt , da dies zu einem abgestandenen (tot) Mitteln beziehen könnte, die seit worden ist ersetzt ... und weder gpgnoch gpg-agenteine Befehlszeilenoption für das Mittel ping und true zurück , wenn es okay.

Craig Ringer
quelle
Ich habe auch auf der Mailingliste der GPG-Benutzer nachgefragt. Ich werde auf den Beitrag verlinken, sobald er im Archiv erscheint.
Craig Ringer
Unix.SE Das Konfigurieren von gpg für die Eingabe der Passphrase nur einmal pro Sitzung löste einige meiner Probleme - allerdings auf einem Einzelbenutzersystem.
Joel Purra

Antworten:

6
  1. Sie können den Exit-Code von überprüfen gpg-connect-agent /bye
  2. Sie können überprüfen, ob der in $ GPG_AGENT_INFO angegebene Socket vorhanden ist. Das sollte ausreichen, aber Sie können auch mit fuser oder lsof prüfen, ob der in $ GPG_AGENT_INFO angegebene Prozess derjenige ist, der den Socket geöffnet hat. Und wenn Sie wirklich umfassend sein möchten, können Sie auch überprüfen, ob / proc / $ PID / exe ein Link zu / usr / bin / gpg-agent (oder was auch immer) ist.
Hauke ​​Laging
quelle
Leider löst keines dieser Probleme das Problem. (1) stellt korrekt fest, ob der gpg-Agent ausgeführt wird, testet jedoch nicht auf die gleiche Weise wie er gpgselbst. Daher kann es erfolgreich sein, wenn gpg anschließend keine Verbindung zum Agenten herstellt. Das Gleiche gilt für (2), da der Agent möglicherweise ausgeführt wird, GPG_AGENT_INFO jedoch in der aktuellen Sitzung nicht festgelegt ist und es keine offensichtliche Möglichkeit gibt, den gpg-agentBefehl nach dem GPG_AGENT_INFOeines bereits ausgeführten Agenten zu fragen .
Craig Ringer
3

Bisher ist die beste Problemumgehung, die ich habe, das folgende schreckliche Durcheinander:

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

Dadurch wird GPG_AGENT_INFOin der Umgebung überprüft, und wenn es festgelegt ist, stellen Sie sicher, dass gpg-agent tatsächlich ausgeführt wird. (Ich bin mir noch nicht sicher, wie dies mit anderen GPG-Agent-Implementierungen wie dem GNOME-Agenten interagiert.) Wenn die Agenteninformationen festgelegt sind, der Agent jedoch nicht ausgeführt wird, weiß er nicht, wie er damit umgehen soll, und gibt auf.

Wenn die Agenteninformationen nicht festgelegt sind, wird überprüft, ob der Agent ausgeführt wird. Wenn dies der Fall ist, sucht es an einigen bekannten Stellen nach den env-Informationen und gibt auf, wenn es sie nicht findet.

Wenn der Agent nicht ausgeführt wird und die Agenteninformationen nicht festgelegt sind, startet er einen Agenten, schreibt die env-Datei an einen privaten Speicherort und fährt fort.

Zu sagen, dass ich mit diesem schrecklichen, benutzerfeindlichen und unzuverlässigen Hack unzufrieden bin, ist eine Untertreibung.

Es ist sehr überraschend, dass gpgein Sicherheits- / Krypto-Tool Argumente ignoriert und fortfährt. --use-agentsollte ein schwerwiegender Fehler sein, wenn ein Agent zumindest optional nicht ausgeführt wird, ebenso wie die Angabe -rmit einem ungültigen Empfänger ein Fehler sein sollte, anstatt ignoriert zu werden. Die Tatsache, dass gpgsein Agent anders als der gpg-agentBefehl ist, ist verwirrend.

Craig Ringer
quelle
Wie üblich kann es noch unordentlicher gemacht werden ... :-) Wenn GPG_AGENT_INFO nicht (oder falsch) eingestellt ist und Sie die PID kennen (z. B. von pgrep gpg-agent), kann ypu dies tun, um die Buchse zu finden:lsof -n -p $PID | grep S.gpg-agent$ | awk '{print $NF}'
Hauke ​​Laging
1
@HaukeLaging ... wenn es bei der Arbeit wirklich gpg-agentnicht heißt gnome-keyring-daemon. Weil es nicht schon schrecklich genug war: S. Ich bin erstaunt, dass das alles so inkonsistent ist.
Craig Ringer
! test -v GPG_AGENT_INFO funktioniert nicht unter Mac OS X. Sie müssen [ -z ${GPG_AGENT_INFO+x} ]stattdessen so etwas wie verwenden.
Dan Loewenherz
2

Auf meinem Ubuntu-System gpg-agentist so konfiguriert, dass es seine Umgebungsdatei schreibt ~/.gnupg/gpg-agent-info-$(hostname)(was von gemacht wird /etc/X11/Xsession.d/90gpg-agent). Wenn Ihr System dies nicht tut, können Sie die Art und Weise ändern, in der der Agent gestartet wird, um eine Umgebungsdatei an einem bekannten Speicherort zu schreiben, der später bezogen werden kann. Zum Beispiel:

$ gpg-agent --daemon --write-env-file="$HOME/.gnupg/gpg-agent-info"
$ source ~/.gnupg/gpg-agent-info
mgorven
quelle
Ja, das Problem ist, dass ich Skript-Tools verwende, die portabel sein müssen. Ich kann mich nicht wirklich auf distro-spezifische Details verlassen. gpg-agent schreibt keine env-Datei, wenn ein Agent bereits ausgeführt wird und ich nicht feststellen kann, wo sich möglicherweise bereits eine env-Datei befindet. Wenn gpg-agent --write-env-file den aktuell ausgeführten Agenten abfragen und eine env-Datei schreiben würde, wäre das in Ordnung, aber nicht.
Craig Ringer
1
NB:gpg-agent[2333]: WARNING: "--write-env-file" is an obsolete option - it has no effect
Kent Fredric