Wie kann ich dem ssh-agent mitteilen, dass er sich beenden soll?

Helmut Waitzmann nn.throttle at xoxy.net
So Dez 14 02:48:24 CET 2014


Mathias Bauer <mbauer at mailbox.org> writes:

> Hallo Helmut,
>
> * Helmut Waitzmann schrieb am Fr, 12. Dez 2014, um 20:18 (+0100):
>
> hier läuft
>   $ gpg-agent --version
>   gpg-agent (GnuPG) 2.0.19
>

Bei mir ist es

$ gpg-agent --version
gpg-agent (GnuPG) 2.0.14
libgcrypt 1.4.5
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

> Ein TERM beendet den Agenten; bei drei TERMs oder einem INT
> geschieht das sofort (ohne Rücksicht auf Verluste).  Die
> Prozessnummer ist Teil von GPG_AGENT_INFO:
>   /path/to/socket/S.gpg-agent:12345:1
>
> Mit einigen (POSIX-)Shell-Kommandos erhält man:
>
>   P="${GPG_AGENT_INFO#*:}"
>   P="${P%:*}"

Ah ja, also 3 Teile, getrennt mit je einem „:“.  Vermutet habe ich das
auch, konnte aber in der Dokumentation keinen Hinweis finden, ob es
immer (d.h. auch in Zukunft) genau 3 Teile sind, und auch nicht, was
geschieht, wenn im Socketnamen ein Doppelpunkt enthalten ist.

Mein ssh-agent weigert sich, das Socket anzulegen, wenn ich ihm das
Option „--use-standard-socket“ mitgebe und GNUPGHOME einen „:“ enthält.
Soweit also keine Gefahr für mehr als 2 „:“ in GPG_AGENT_INFO.  Nur das
Handbuch schweigt halt dazu.

>
>> „Verlässlich“ heißt: Auch im Fall, dass der Agent abgestürzt
>> ist und bereits ein anderer, unbeteiligter Prozess gestartet
>> wurde, der zufällig seine Prozessnummer erhalten hat, muss
>> sichergestellt werden können, dass dann nicht fälschlicherweise
>> dem anderen Prozess ein TERM‐Signal geschickt wird.
>
> Kurz: Steckt hinter P wirklich der Agent?  Das ist jetzt nicht
> mehr ganz so lustig:
>
>   if [ -n "$P" ] && \
>      [ -d "/proc/$P" ] && \
>      [ "x$(/bin/readlink "/proc/$P/exe")" = x/usr/bin/gpg-agent ]
>   then
>     kill -TERM "$P"
>     sleep 2
>     kill -0 "$P" >/dev/null 2>&1 && kill -INT "$P"
>     sleep 1
>     kill -0 "$P" >/dev/null 2>&1 && kill -KILL "$P"
>   fi
>
> Erklärung: *Wenn* es (a) ein P gibt und (b) einen Prozess dazu
> und (c) dessen auführbare Datei mit dem Pfad zum Agent-Programm
> übereinstimmt, *dann* beende den Agent freundlich und warte.
> Wenn er danach immer noch da ist, beende ihn "unfreundlich".
>
> Diese Prüfung ist zwar immer noch offen für Race conditions, aber
> doch etwas sicherer.

Ja, danke, verstanden.

Ich hatte gehofft, dass da vielleicht der gpg-connect-agent helfen
könnte, den gpg-agent zu finden, oder – noch besser – ihm zu sagen, er
solle sich beenden.  Schade, das das nicht geht.

> Behandlung von GPG_AGENT_INFO, Agent mit --write-env-file
> starten,...

> Natürlich kannst Du auch einfach mit
>
>   killall -v -TERM gpg-agent
>
> alle Agenten grob beenden.  Aber das empfehle ich nicht pauschal.

Mir ist da auch nicht wohl dabei.

> Das ganze Vorgehen ist abhängig davon, wie Deine Sessions
> gestartet werden, ob Konsole und/oder X, ob mehrere parallel,
> etc.

Einen gpg-agent möchte ich bei jedem Einloggen zur Verfügung haben,
egal, ob auf der Konsole oder mit X11.

Ich hätte nichts dagegen, wenn es machbar wäre, auf jedem Rechner, der
das gemeinsame NFS‐HOME‐Verzeichnis nutzt, nur einen gpg-agent für alle
Sessions zu nutzen.  Das hätte den Vorteil, dass ich diesen einen
gpg-agent nicht beenden muss:  Er soll ja sowieso für alle weitere
Sessions (egal, ob augenblickliche oder zukünftige) verwendet werden.
Das bedeutet aber, dass ich beim Einloggen nicht einfach einen gpg-agent
starten kann, denn es könnte ja bereits einer laufen.  Deswegen kann
dann der Fall eintreten (wenn doch noch kein gpg-agent läuft), dass gpg2
selber einen startet.  Weil ich dabei aber keine Möglichkeit habe,
"${GPG_AGENT_INFO}" an andere bereits laufende Prozesse (etwa ein
Mailerprogramm) weiterzugeben, müsste das Socket des von gpg2
gestarteten gpg-agents dann immer an derselben Stelle im Dateisystem zu
finden sein, ich müsste also in gpg-agents Konfigurationsdatei
„use-standard-socket“ vermerken.  Das aber ist laut Dokumentation nicht
erlaubt, wenn "${GNUPGHOME-"${HOME}/.gnupg"}" vom NFS kommt.

Also bleibt wohl nur die Vorgehensweise „für jedes Login‐Session einen
eigenen gpg-agent“:  Weil dabei bei jedem Login in jedem Fall ein
gpg-agent gestartet wird, kann die von ihm herausgegebene
Umgebungsvariable GPG_AGENT_INFO einfach an alle weiteren Prozesse des
Sessions vererbt werden und es entsteht auch nicht das Problem, dass
gpg2 selber einen gpg-agent startet.

Ah, da tauchen noch ein paar Fragen auf:

Ich habe durch Ausprobieren festgestellt:  Die mit dem Option
„--write-env-file“ vom Agent erzeugte Umgebungsvariablen‐Datei wird
weder geleert noch entfernt, wenn sich der Agent nach Empfang eines
TERM‐Signals beendet.  Das Socket aber wird entfernt.

Kann ich daran, ob das in "${GPG_AGENT_INFO%:*:*}" genannte Socket
vorhanden ist, sehen, ob ein gpg-agent läuft?  Dann könnte ich das als
weiteres notwendiges Kriterium nutzen, ehe ich beim Ausloggen ein
TERM‐Signal in Richtung gpg-agent schicke.  Aber auch hier gäbe es
dasselbe Race‐Condition wie oben.

Wird die vom Agent mit Option „--write-env-file“ erzeugte
Umgebungsvariablen‐Datei von gpg2, gpg-connect-agent oder gpg-agent
gelesen oder ist sie nur eine Alternative zu

$ eval "$(gpg-agent --daemon)"

?
> Ich hoffe, die obigen Schritte helfen Dir erst einmal weiter.

Ja, das tun sie.  Vielen Dank.

Grüße,

Helmut




Mehr Informationen über die Mailingliste Gnupg-de