gpg-agent diz que o agente existe, mas o gpg diz que o agente não existe?

9

Estou lutando com alguns problemas ao criar scripts em gpg com bash em uma caixa do Debian 6.0.6. Eu tenho um script que faz um lote de operações e quer ter certeza de que um agente gpg está disponível antes de tentar prosseguir.

Como o gpg-agent não executará nenhuma ação e retornará o sucesso se iniciado quando já estiver em execução, garantir que o agente esteja presente é tão simples quanto:

eval $(gpg-agent --daemon)

gpg-agent start ou informará:

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

e retorne 0 (sucesso) se já estiver em execução.

O problema surge quando um agente já está sendo executado em outra sessão. gpg-agent diz que já está em execução ... mas gpg diz que não está disponível.

$ 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

Isso me deixa frustrado e confuso. Parece que gpg-agent está detectando o agente de uma maneira diferente do gpg. Pior, gpg não oferece nenhuma maneira de perguntar se o agente está disponível de maneira programável, da mesma forma que gosta de ignorar silenciosamente os destinatários com chaves inutilizáveis e ainda retornar sucesso, por isso é muito difícil detectar esse problema antes de iniciar o lote. Eu não quero entrar na análise do output do gpg por razões entre outras.

Você pode reproduzir isso certificando-se de não ter um agente gpg em execução ou ter GPG_AGENT_INFO definido, depois em um terminal executando eval $(gpg-agent --daemon) e em outro terminal executando o acima. Você notará que o gpg-agent diz que ele já está em execução, mas o gpg não consegue se conectar ao agente.

Idéias?

UPDATE : gpg-agent detecta outro agente procurando por um arquivo de soquete em um local bem conhecido e escrevendo para ele para testar a vitalidade, por isso 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

enquanto o GnuPG parece olhar apenas para o ambiente, ignorando a localização do socket bem conhecido. Em 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 */
}

Eu realmente não quero matar o agente apenas para ter certeza de que posso iniciá-lo novamente, e não há um local padrão onde o agente do usuário possa gravar um arquivo de ambiente. Pior, não posso nem testar a presença de GPG_AGENT_INFO no ambiente, pois isso pode se referir a um agente obsoleto que foi substituído desde então ... e nem gpg nem gpg-agent fornecem uma opção de linha de comando para pingar o agente e retornar true se estiver correto.

    
por Craig Ringer 21.02.2013 / 15:06

4 respostas

6

  1. Você pode verificar o código de saída de gpg-connect-agent /bye
  2. Você pode verificar se o soquete fornecido em $ GPG_AGENT_INFO existe. Isso deve ser suficiente, mas você também pode verificar com o fusor ou com o lsof se o processo fornecido em $ GPG_AGENT_INFO é aquele que abriu o soquete. E se você quiser ser realmente exaustivo, você também pode verificar se / proc / $ PID / exe é um link para / usr / bin / gpg-agent (ou qualquer outro).
por 21.02.2013 / 17:05
3

Até agora, a melhor solução que tenho é a seguinte confusão horrível:

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

Isto irá verificar por GPG_AGENT_INFO no ambiente e se estiver definido, certifique-se de que o gpg-agent esteja realmente rodando. (Ainda não tenho certeza de como isso interage com outras implementações do agente gpg, como o agente do GNOME). Se as informações do agente estiverem definidas, mas o agente não estiver em execução, ele não saberá como lidar e desistir.

Se as informações do agente não estiverem definidas, ele verificará se o agente está sendo executado. Se for, ele procura as informações de env em alguns locais bem conhecidos e, se não conseguir encontrá-las, desiste.

Se o agente não estiver em execução e as informações do agente não estiverem definidas, ele iniciará um agente, gravará o arquivo env em um local privado e continuará.

Dizer que estou insatisfeito com esse hack horrível, hostil e pouco confiável é um eufemismo.

É muito surpreendente que gpg , uma ferramenta de segurança / criptografia, ignore os argumentos e continue. --use-agent deve ser um erro fatal se um agente não estiver sendo executado, pelo menos opcionalmente, da mesma forma que especificar -r com um destinatário inválido deve ser um erro em vez de ignorado. O fato de gpg encontrar seu agente de maneira diferente do comando gpg-agent é desconcertante.

    
por 22.02.2013 / 00:57
3

A versão principal do agente gpg em execução é 2. Você deve invocar gpg2 em vez de gpg como respondido aqui: link

    
por 02.06.2017 / 20:36
2

No meu sistema Ubuntu gpg-agent está configurado para gravar seu arquivo de ambiente em ~/.gnupg/gpg-agent-info-$(hostname) (que é feito por /etc/X11/Xsession.d/90gpg-agent ). Se o seu sistema não fizer isso, você poderá modificar a maneira como o agente é iniciado para gravar um arquivo de ambiente em um local bem conhecido, que pode ser posteriormente originado. Por exemplo:

$ gpg-agent --daemon --write-env-file="$HOME/.gnupg/gpg-agent-info"
$ source ~/.gnupg/gpg-agent-info
    
por 21.02.2013 / 18:02