agen gpg mengatakan agen ada, tetapi gpg mengatakan agen tidak ada?

9

Saya kesulitan dengan beberapa masalah saat menulis gpg dengan bashmenggunakan kotak Debian 6.0.6. Saya memiliki skrip yang melakukan serangkaian operasi dan ingin memastikan bahwa agen gpg tersedia sebelum mencoba untuk melanjutkan.

Karena gpg-agent tidak akan mengambil tindakan dan mengembalikan kesuksesan jika diluncurkan ketika sudah berjalan, memastikan agen hadir sesederhana:

eval $(gpg-agent --daemon)

gpg-agent mulai, atau akan melaporkan:

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

dan mengembalikan 0 (sukses) jika sudah berjalan.

Masalah muncul ketika agen sudah berjalan di sesi lain. gpg-agentmengatakan bahwa itu sudah berjalan ... tetapi gpgdengan sendirinya mengklaim bahwa itu tidak tersedia.

$ 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

Ini membuat saya frustrasi dan frustrasi. Tampaknya gpg-agentmendeteksi agen cara yang berbeda untuk gpg sendiri. Lebih buruk lagi, gpgtidak menawarkan cara untuk menanyakan apakah agen tersedia dengan cara yang dapat skrip, sama seperti suka mengabaikan penerima dengan diam-diam dengan kunci yang tidak dapat digunakan dan masih mengembalikan kesuksesan, sehingga sangat sulit untuk mendeteksi masalah ini sebelum memulai batch. Saya tidak ingin masuk ke parsing keluaran gpg untuk alasan i18n antara lain.

Anda dapat mereproduksi ini dengan memastikan Anda tidak memiliki gpg-agent yang berjalan atau telah GPG_AGENT_INFOdiatur, kemudian di satu terminal berjalan eval $(gpg-agent --daemon)dan di terminal lain menjalankan di atas. Anda akan perhatikan bahwa gpg-agent mengatakan itu sudah berjalan, tetapi gpg gagal terhubung ke agen.

Ide ide?

UPDATE : gpg-agentmendeteksi agen lain dengan mencari file soket di lokasi yang terkenal dan menulis untuk menguji keaslian, dan per ini 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

sementara GnuPG tampaknya hanya melihat lingkungan, mengabaikan lokasi soket yang terkenal. Dalam 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 */
}

Saya tidak benar-benar ingin membunuh agen hanya untuk memastikan saya bisa memulainya lagi, dan tidak ada tempat standar di mana agen pengguna mungkin menulis file lingkungan. Lebih buruk lagi, saya bahkan tidak bisa menguji keberadaan GPG_AGENT_INFOdi lingkungan karena itu bisa merujuk pada agen basi (mati) yang sejak itu diganti ... dan gpgjuga tidak juga gpg-agentmenyediakan opsi baris perintah untuk melakukan ping agen dan mengembalikan true jika itu baik.

Craig Ringer
sumber
Saya juga bertanya pada milis gpg-pengguna; Saya akan menautkan ke posting setelah muncul di arsip.
Craig Ringer
Unix.SE Cara mengkonfigurasi gpg untuk memasukkan frasa sandi hanya sekali per sesi menyelesaikan beberapa masalah saya - pada sistem pengguna tunggal.
Joel Purra

Jawaban:

6
  1. Anda dapat memeriksa kode keluar dari gpg-connect-agent /bye
  2. Anda dapat memeriksa apakah soket yang diberikan dalam $ GPG_AGENT_INFO ada. Itu seharusnya cukup tetapi Anda juga dapat memeriksa dengan fuser atau apakah apakah proses yang diberikan dalam $ GPG_AGENT_INFO adalah yang telah membuka soket. Dan jika Anda ingin menjadi sangat lengkap, Anda juga dapat memeriksa apakah / proc / $ PID / exe adalah tautan ke / usr / bin / gpg-agent (atau apa pun).
Hauke ​​Laging
sumber
Sayangnya, tak satu pun dari ini menyelesaikan masalah. (1) menentukan dengan benar apakah gpg-agent sedang berjalan, tetapi ia tidak menguji dengan cara yang sama gpgdengan self-nya, sehingga ia dapat berhasil ketika gpg kemudian gagal terhubung ke agen. Hal yang sama berlaku untuk (2) bahwa agen mungkin berjalan, tetapi GPG_AGENT_INFO tidak diatur dalam sesi saat ini, dan tidak ada cara yang jelas untuk meminta gpg-agentperintah untuk GPG_AGENT_INFOagen yang sudah berjalan.
Craig Ringer
3

Sejauh ini solusi terbaik yang saya miliki adalah kekacauan mengerikan berikut:

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

Ini akan memeriksa GPG_AGENT_INFOdi lingkungan dan jika sudah diatur, pastikan gpg-agent benar-benar berjalan. (Saya belum yakin bagaimana ini berinteraksi dengan implementasi gpg-agent lain seperti agen GNOME). Jika info agen diatur tetapi agen tidak berjalan itu tidak tahu bagaimana cara mengatasi dan menyerah.

Jika info agen tidak disetel itu memeriksa untuk melihat apakah agen berjalan. Jika ya, ia mencari info env di beberapa lokasi terkenal dan jika gagal menemukannya, menyerah.

Jika agen tidak berjalan dan info agen tidak disetel, agen mulai, menulis file env ke lokasi pribadi, dan melanjutkan.

Untuk mengatakan bahwa saya tidak senang dengan peretasan yang mengerikan, tidak bersahabat, dan tidak dapat diandalkan ini merupakan pernyataan yang meremehkan.

Sangat mengejutkan bahwa gpg, alat keamanan / crypto, akan mengabaikan argumen dan melanjutkan. --use-agentharus menjadi kesalahan fatal jika agen tidak berjalan, setidaknya secara opsional, sebanyak menetapkan -rdengan penerima yang tidak valid harus menjadi kesalahan daripada diabaikan. Fakta bahwa gpgmenemukan agennya cara yang berbeda dengan gpg-agentperintah itu membingungkan.

Craig Ringer
sumber
Seperti biasa dapat dibuat lebih berantakan ... :-) Jika GPG_AGENT_INFO tidak diatur (atau salah) dan Anda tahu PID (mis. Dengan pgrep gpg-agent) maka ypu dapat melakukan ini untuk menemukan soket:lsof -n -p $PID | grep S.gpg-agent$ | awk '{print $NF}'
Hauke ​​Laging
1
@ Hokukeaging ... jika itu benar-benar gpg-agenttidak mengatakan gnome-keyring-daemondi tempat kerja. karena itu belum cukup mengerikan: S. Saya kagum bahwa itu semua berantakan tidak konsisten.
Craig Ringer
! test -v GPG_AGENT_INFO tidak berfungsi di Mac OS X. Anda harus menggunakan sesuatu seperti itu [ -z ${GPG_AGENT_INFO+x} ].
Dan Loewenherz
2

Pada sistem Ubuntu saya gpg-agentdikonfigurasikan untuk menulis file lingkungannya ~/.gnupg/gpg-agent-info-$(hostname)(yang dilakukan oleh /etc/X11/Xsession.d/90gpg-agent). Jika sistem Anda tidak melakukan ini, Anda bisa memodifikasi cara agen mulai menulis file lingkungan di lokasi yang terkenal yang nantinya dapat bersumber. Sebagai contoh:

$ gpg-agent --daemon --write-env-file="$HOME/.gnupg/gpg-agent-info"
$ source ~/.gnupg/gpg-agent-info
Mgorven
sumber
Ya, masalahnya adalah saya menggunakan alat scripting yang harus portabel; Saya tidak bisa benar-benar mengandalkan detail distro. gpg-agent tidak akan menulis file env jika agen sudah berjalan dan saya tidak bisa menentukan di mana file env mungkin sudah ada. Jika gpg-agent --write-env-file akan menanyakan agen yang sedang berjalan dan menulis file env, itu akan baik-baik saja, tetapi tidak.
Craig Ringer
1
NB:gpg-agent[2333]: WARNING: "--write-env-file" is an obsolete option - it has no effect
Kent Fredric