gpg-agent mówi, że agent istnieje, ale gpg mówi, że agent nie istnieje?

9

Walczę z pewnymi problemami podczas pisania skryptu na gpg bashna pudełku Debiana 6.0.6. Mam skrypt, który wykonuje wiele operacji i chce się upewnić, że gpg-agent jest dostępny, zanim spróbuje kontynuować.

Ponieważ gpg-agent nie podejmie żadnych działań i zwróci sukces, jeśli zostanie uruchomiony, gdy jest już uruchomiony, upewnienie się, że agent jest obecny, jest tak proste, jak:

eval $(gpg-agent --daemon)

gpg-agent rozpocznie się lub zgłosi:

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

i zwraca 0 (sukces), jeśli już działa.

Problem powstaje, gdy agent jest już uruchomiony w innej sesji. gpg-agentmówi, że już działa ... ale gpgsam twierdzi, że jest niedostępny.

$ 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

To sprawia, że ​​jestem sfrustrowany i zdezorientowany. Wygląda na gpg-agentto, że wykrywa agenta w inny sposób, aby samemu sobie radzić z gpg. Co gorsza, gpgnie można zapytać, czy agent jest dostępny w formie skryptowej, ponieważ lubi cicho ignorować odbiorców za pomocą bezużytecznych kluczy i nadal zwracać sukces, więc bardzo trudno jest wykryć ten problem przed rozpoczęciem partii. Nie chcę wchodzić w parsowanie wyników gpg, między innymi z powodów i18n.

Możesz to odtworzyć, upewniając się, że nie masz uruchomionego lub GPG_AGENT_INFOskonfigurowanego agenta gpg , a następnie w jednym terminalu uruchomionym eval $(gpg-agent --daemon)i w innym terminalu uruchomionym powyżej. Zauważysz, że gpg-agent mówi, że już działa, ale gpg nie łączy się z agentem.

Pomysły?

AKTUALIZACJA : gpg-agentwykrywa innego agenta, szukając pliku gniazda w znanej lokalizacji i pisząc do niego w celu przetestowania żywotności, według tego 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

podczas gdy GnuPG wydaje się patrzeć tylko na środowisko, ignorując dobrze znaną lokalizację gniazda. W 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 */
}

Tak naprawdę nie chcę zabijać agenta, aby upewnić się, że mogę go uruchomić ponownie, i nie ma standardowego miejsca, w którym agent użytkownika mógłby zapisać plik środowiska. Co gorsza, nie mogę nawet przetestować obecności GPG_AGENT_INFOw środowisku, ponieważ może to odnosić się do przestarzałego (martwego) agenta, który został zastąpiony ... i nie może gpgteż gpg-agentzapewnić opcji wiersza polecenia do pingowania agenta i zwrócenia wartości true, jeśli jest to ok.

Craig Ringer
źródło
Zapytałem również na liście mailingowej użytkowników gpg; Link do posta, gdy pojawi się w archiwach.
Craig Ringer
Unix.SE Jak skonfigurować gpg, aby wprowadzał hasło tylko raz na sesję, rozwiązał niektóre z moich problemów - jednak w systemie dla jednego użytkownika.
Joel Purra

Odpowiedzi:

6
  1. Możesz sprawdzić kod wyjścia gpg-connect-agent /bye
  2. Możesz sprawdzić, czy gniazdo podane w $ GPG_AGENT_INFO istnieje. To powinno wystarczyć, ale możesz także sprawdzić za pomocą utrwalacza lub lsof, czy proces podany w $ GPG_AGENT_INFO to ten, który otworzył gniazdo. A jeśli chcesz być naprawdę wyczerpujący, możesz również sprawdzić, czy / proc / $ PID / exe jest linkiem do / usr / bin / gpg-agent (lub cokolwiek innego).
Hauke ​​Laging
źródło
Niestety żadne z nich nie rozwiązuje problemu. (1) poprawnie określa, czy gpg-agent działa, ale nie testuje w taki sam sposób, gpgjak robi to samo, więc może się powieść, gdy gpg następnie nie połączy się z agentem. To samo dotyczy (2), ponieważ agent może być uruchomiony, ale GPG_AGENT_INFO nie jest ustawiony w bieżącej sesji i nie ma widocznego sposobu, aby poprosić o gpg-agentpolecenie GPG_AGENT_INFOjuż działającego agenta.
Craig Ringer
3

Jak dotąd najlepszym obejściem jest następujący ohydny bałagan:

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

Spowoduje to sprawdzenie GPG_AGENT_INFOw środowisku i jeśli jest ustawione, upewnij się, że gpg-agent faktycznie działa. (Nie jestem jeszcze pewien, jak to współdziała z innymi implementacjami gpg-agent, takimi jak agent GNOME). Jeśli informacje o agencie są ustawione, ale agent nie działa, nie wie, jak sobie z tym poradzić i się poddaje.

Jeśli informacje o agencie nie są ustawione, sprawdza, czy agent jest uruchomiony. Jeśli tak, szuka informacji o env w kilku dobrze znanych lokalizacjach, a jeśli nie uda się jej znaleźć, poddaje się.

Jeśli agent nie działa, a informacje o agencie nie są ustawione, uruchamia agenta, zapisuje plik env w prywatnej lokalizacji i kontynuuje.

Stwierdzenie, że jestem niezadowolony z tego okropnego, wrogiego i niewiarygodnego włamania, jest niedopowiedzeniem.

To bardzo zaskakujące, że gpgnarzędzie bezpieczeństwa / szyfrowania zignoruje argumenty i przejdzie dalej. --use-agentpowinien być błędem krytycznym, jeśli agent nie jest uruchomiony, przynajmniej opcjonalnie, ponieważ określenie -rz niepoprawnym odbiorcą powinno być błędem, a nie ignorowane. Fakt, że gpgjego agent różni się od gpg-agentpolecenia, jest oszałamiający.

Craig Ringer
źródło
Jak zwykle można to zrobić jeszcze bardziej bałagan ... :-) Jeśli GPG_AGENT_INFO nie jest (lub źle) ustawiony i znasz PID (np. Przez pgrep gpg-agent), możesz to zrobić, aby znaleźć gniazdo:lsof -n -p $PID | grep S.gpg-agent$ | awk '{print $NF}'
Hauke ​​Laging
1
@HaukeLaging ... jeśli to naprawdę gpg-agentnie powiedz gnome-keyring-daemonw pracy. bo to nie było już wystarczająco okropne: S. Dziwi mnie, że to wszystko jest tak niespójne.
Craig Ringer
! test -v GPG_AGENT_INFO nie działa w systemie Mac OS X. Zamiast tego musisz użyć czegoś takiego [ -z ${GPG_AGENT_INFO+x} ].
Dan Loewenherz
2

W moim systemie Ubuntu gpg-agentjest skonfigurowany do zapisywania pliku środowiska ~/.gnupg/gpg-agent-info-$(hostname)( do czego służy /etc/X11/Xsession.d/90gpg-agent). Jeśli Twój system tego nie robi, możesz zmodyfikować sposób, w jaki agent uruchamia się, aby zapisać plik środowiska w dobrze znanej lokalizacji, którą można później uzyskać. Na przykład:

$ gpg-agent --daemon --write-env-file="$HOME/.gnupg/gpg-agent-info"
$ source ~/.gnupg/gpg-agent-info
mgorven
źródło
Tak, problem polega na tym, że piszę narzędzia skryptowe, które muszą być przenośne; Naprawdę nie mogę polegać na szczegółach specyficznych dla dystrybucji. gpg-agent nie napisze pliku env, jeśli agent już działa i nie mogę ustalić, gdzie może być już plik env. Jeśli gpg-agent --write-env-file zapyta aktualnie działającego agenta i napisze plik env, byłoby dobrze, ale tak nie jest.
Craig Ringer
1
NB:gpg-agent[2333]: WARNING: "--write-env-file" is an obsolete option - it has no effect
Kent Fredric