TenForward

技術ブログ。はてなダイアリーから移転しました

GnuPGで鍵取得しようとするとdirmngrに繋がらないと怒られる

単なるメモ。Plamo-7.0 開発中環境でのお話。

gnupg 2.1.19 までは大丈夫なんだけど、gnupg 2.1.23、2.2.0、2.2.1 にすると、dirmngr がうまく動かない… (2.1.20 〜 22 は作ってないので知らない)。

$ gpg --recv-keys ()
gpg: connecting dirmngr at '/home/karma/.gnupg/S.dirmngr' failed: IPC connect呼び出しに失敗しました
gpg: 鍵サーバからの受信に失敗しました: dirmngrがありません

となる。この時、dirmngr は起動しているけど、

tcp        0      1 10.200.200.232:45602    127.0.0.1:9050          SYN_SENT    27056/dirmngr

のように、どうやら Tor に接続に行っている模様。これコンパイル時に無効化できんの? もしくはデフォルト使わないってできんの?

もちろん dirmngr.conf で使わないように設定すれば使わない。でも Plamo では、システムワイドで dirmngr 起動するわけではなく、ユーザごとに起動することになるので、ユーザの dirmngr.conf にいちいち書かなければならない。

$ cat ~/.gnupg/dirmngr.conf 
no-use-tor

いや、GnuPG 詳しくないから知らんけど

マニュアルには The default is to use Tor if it is available on startup or after reloading dirmngr. と書いてある。でも Tor なんて入ってないと思うんだけど…

GnuPGのdirmngrのコード見ると、dirmngr/server.c

/* This function returns true if a Tor server is running.  The status
 * is cached for the current connection.  */
static int
is_tor_running (ctrl_t ctrl)
{
  /* Check whether we can connect to the proxy.  */

  if (!ctrl || !ctrl->server_local)
    return 0; /* Ooops.  */

  if (!ctrl->server_local->tor_state)
    {
      assuan_fd_t sock;

      sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
      if (sock == ASSUAN_INVALID_FD)
        ctrl->server_local->tor_state = -1; /* Not running.  */
      else
        {
          assuan_sock_close (sock);
          ctrl->server_local->tor_state = 1; /* Running.  */
        }
    }
  return (ctrl->server_local->tor_state > 0);
}

こんな関数がある。ここで tor_state が 1 になってる?

libassuan を見ると、src/assuan-socket.c 内に

_assuan_sock_connect_byname (assuan_context_t ctx, const char *host,
                             unsigned short port, int reserved,
                             const char *credentials, unsigned int flags)
{
  assuan_fd_t fd;
  unsigned short socksport;

  if ((flags & ASSUAN_SOCK_TOR))
    socksport = TOR_PORT;
  else if ((flags & ASSUAN_SOCK_SOCKS))
    socksport = SOCKS_PORT;
  else
    {
      gpg_err_set_errno (ENOTSUP);
      return ASSUAN_INVALID_FD;
    }

  if (host && !*host)
    {
      /* Error out early on an empty host name.  See below.  */
      gpg_err_set_errno (EINVAL);
      return ASSUAN_INVALID_FD;
    }

  fd = _assuan_sock_new (ctx, AF_INET, SOCK_STREAM, 0);
  if (fd == ASSUAN_INVALID_FD)
    return fd;

  /* For HOST being NULL we pass an empty string which indicates to
     socks5_connect to stop midway during the proxy negotiation.  Note
     that we can't pass NULL directly as this indicates IP address
     mode to the called function.  */
  if (socks5_connect (ctx, fd, socksport,
                      credentials, host? host:"", port, NULL, 0))
    {
      int save_errno = errno;
      assuan_sock_close (fd);
      gpg_err_set_errno (save_errno);
      return ASSUAN_INVALID_FD;
    }

  return fd;
}

なんて関数がある。よくわからんw

いや、違うな。dirmngr に Tor のオプションを指定すると、オプションが --use-tor--no-use-tor かに関わらず dirmngr はすぐに起動するけど、何も指定しないと起動後 127.0.0.1:9050 へのアクセスをして、だいぶタイムアウトを待った後に、使わない設定で起動するな。dirmngr.conf を準備して、ちゃんと設定しろ、ということかな。なんて不便なソフトウェアだ。

$ strace dirmngr --server --homedir /home/karma/.gnupg -vvv --debug-all
  :(snip)
write(2, "dirmngr[27628]: enabled debug fl"..., 108dirmngr[27628]: enabled debug flags: x509 crypto memory cache memstat hashing ipc dns network lookup extprog) = 108
write(2, "\n", 1
)                       = 1
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(9050), sin_addr=inet_addr("127.0.0.1")}, 16
  :(↑でだんまり)
  :(snip)

うん、接続を延々待ってるわ。これで失敗したあとにちゃんと dirmngr は起動して、クライアントからのリクエストに応える。不便すぎて涙出るな。