[Pkg-gnupg-commit] [libassuan] 02/11: Support SOCKS5 for assuan_sock_connect.

Eric Dorland eric at moszumanska.debian.org
Thu Nov 12 16:14:46 UTC 2015


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository libassuan.

commit 85ece74a11718338dcd76d6e43ea8100183df02f
Author: Werner Koch <wk at gnupg.org>
Date:   Sun Oct 18 16:24:34 2015 +0200

    Support SOCKS5 for assuan_sock_connect.
    
    * src/assuan-socket.c: Include netinet/in.h and arpa/inet.h.
    (SOCKS_PORT, TOR_PORT): New constants.
    (tor_mode): New variable.
    (_assuan_sock_set_flag): Add flags "tor-mode" and "socks".
    (_assuan_sock_get_flag): Ditto.
    (do_readn, do_writen): Always build.
    (socks5_connect): New.
    (use_socks): New.
    (_assuan_sock_connect): Divert to socks5_connect if requested.
    
    * tests/socks5.c: New.
    * configure.ac (AH_TOP): Define GPGRT_ENABLE_ES_MACROS.
    (AC_CHECK_FUNC): Check for getaddrinfo.
    * tests/Makefile.am (testtools): New. Add socks5.
    (AM_LDFLAGS): Add -no-install for easier debugging.
    --
    
    A future extension might be a new assuan_sock_direct_connect call
    takes the hostname as a string and returns a new socket.  This allows
    the proxy to do the resolving.  However, in the long term these socket
    wrapper should be moved to libgpgrt (aka libgpg-error).
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
---
 configure.ac        |   6 +-
 doc/assuan.texi     |  14 +++
 src/assuan-socket.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 tests/Makefile.am   |   8 +-
 tests/socks5.c      | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 496 insertions(+), 12 deletions(-)

diff --git a/configure.ac b/configure.ac
index 040ce7f..8e8768f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -126,6 +126,10 @@ AH_TOP([
 
 /* Enable gpg-error's strerror macro under W32CE.  */
 #define GPG_ERR_ENABLE_ERRNO_MACROS 1
+
+/* Provide the es_ macro for estream.  */
+#define GPGRT_ENABLE_ES_MACROS 1
+
 ])
 
 AH_BOTTOM([
@@ -356,7 +360,7 @@ AM_PATH_GPG_ERROR(1.8,, AC_MSG_ERROR([libgpg-error was not found]))
 #
 # Checks for library functions.
 #
-AC_CHECK_FUNCS([flockfile funlockfile inet_pton stat])
+AC_CHECK_FUNCS([flockfile funlockfile inet_pton stat getaddrinfo])
 
 # On some systems (e.g. Solaris) nanosleep requires linking to librl.
 # Given that we use nanosleep only as an optimization over a select
diff --git a/doc/assuan.texi b/doc/assuan.texi
index c822190..9161f0b 100644
--- a/doc/assuan.texi
+++ b/doc/assuan.texi
@@ -2082,6 +2082,20 @@ this flag for connecting to a Cygwin style socket because no state is
 required at the client.  On non-Windows platforms setting this flag is
 ignored, reading the flag always returns a value of 0.
 
+ at item tor-mode
+ at itemx socks
+If @var{value} is 1 globally enable SOCKS5 mode for new connections
+using IPv6 or IPv4. @var{fd} must be set to @code{ASSUAN_INVALID_FD} A
+future extension may allow to disable SOCKS5 mode for a specified
+socket but globally disabling SOCKS5 mode is not possible.  Using the
+flag ``tor-mode'' expects the SOCKS5 proxy to listen on port 9050, the
+flag ``socks'' expects the proxy to listen on port 1080.
+
+Connections to the loopback address are not routed though the SOCKS
+proxy.  UDP requests are not supported at all.  The proxy will be
+connected at address 127.0.0.1; an IPv6 connection to the proxy is not
+yet supported.
+
 @end table
 
 
diff --git a/src/assuan-socket.c b/src/assuan-socket.c
index ae90802..9a6ee66 100644
--- a/src/assuan-socket.c
+++ b/src/assuan-socket.c
@@ -34,6 +34,8 @@
 #else
 # include <sys/types.h>
 # include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
 #endif
 #include <errno.h>
 #ifdef HAVE_SYS_STAT_H
@@ -74,11 +76,17 @@
 # define ENAMETOOLONG EINVAL
 #endif
 
+
 #ifndef SUN_LEN
 # define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
 	               + strlen ((ptr)->sun_path))
 #endif
 
+
+/* The standard SOCKS and TOR port.  */
+#define SOCKS_PORT 1080
+#define TOR_PORT   9050
+
 /* In the future, we can allow access to sock_ctx, if that context's
    hook functions need to be overridden.  There can only be one global
    assuan_sock_* user (one library or one application) with this
@@ -86,6 +94,12 @@
    needed.  */
 static assuan_context_t sock_ctx;
 
+/* This global flag can be set using assuan_sock_set_flag to enable
+   TOR or SOCKS mode for all sockets.  It may not be reset.  The value
+   is the port to be used. */
+static unsigned short tor_mode;
+
+
 
 #ifdef HAVE_W32_SYSTEM
 /* A table of active Cygwin connections.  This is only used for
@@ -498,8 +512,10 @@ _assuan_sock_new (assuan_context_t ctx, int domain, int type, int proto)
 
 int
 _assuan_sock_set_flag (assuan_context_t ctx, assuan_fd_t sockfd,
-		      const char *name, int value)
+                       const char *name, int value)
 {
+  (void)ctx;
+
   if (!strcmp (name, "cygwin"))
     {
 #ifdef HAVE_W32_SYSTEM
@@ -511,6 +527,39 @@ _assuan_sock_set_flag (assuan_context_t ctx, assuan_fd_t sockfd,
       /* Setting the Cygwin flag on non-Windows is ignored.  */
 #endif
     }
+  else if (!strcmp (name, "tor-mode") || !strcmp (name, "socks"))
+    {
+      /* If SOCKFD is ASSUAN_INVALID_FD this controls global flag to
+         switch AF_INET and AF_INET6 into TOR mode by using a SOCKS5
+         proxy on localhost:9050.  It may only be switched on and this
+         needs to be done before any new threads are started.  Once
+         TOR mode has been enabled, TOR mode can be disabled for a
+         specific socket by using SOCKFD with a VALUE of 0.  */
+      if (sockfd == ASSUAN_INVALID_FD)
+        {
+          if (tor_mode && !value)
+            {
+              gpg_err_set_errno (EPERM);
+              return -1; /* Clearing the global flag is not allowed.  */
+            }
+          else if (value)
+            {
+              if (*name == 's')
+                tor_mode = SOCKS_PORT;
+              else
+                tor_mode = TOR_PORT;
+            }
+        }
+      else if (tor_mode && sockfd != ASSUAN_INVALID_FD)
+        {
+          /* Fixme: Disable/enable tormode for the given context.  */
+        }
+      else
+        {
+          gpg_err_set_errno (EINVAL);
+          return -1;
+        }
+    }
   else
     {
       gpg_err_set_errno (EINVAL);
@@ -535,6 +584,15 @@ _assuan_sock_get_flag (assuan_context_t ctx, assuan_fd_t sockfd,
       *r_value = 0;
 #endif
     }
+  else if (!strcmp (name, "tor-mode"))
+    {
+      /* FIXME: Find tor-mode for the given socket.  */
+      *r_value = tor_mode == TOR_PORT;
+    }
+  else if (!strcmp (name, "socks"))
+    {
+      *r_value = tor_mode == SOCKS_PORT;
+    }
   else
     {
       gpg_err_set_errno (EINVAL);
@@ -547,7 +605,6 @@ _assuan_sock_get_flag (assuan_context_t ctx, assuan_fd_t sockfd,
 
 /* Read NBYTES from SOCKFD into BUFFER.  Return 0 on success.  Handle
    EAGAIN and EINTR.  */
-#ifdef HAVE_W32_SYSTEM
 static int
 do_readn (assuan_context_t ctx, assuan_fd_t sockfd,
           void *buffer, size_t nbytes)
@@ -561,7 +618,7 @@ do_readn (assuan_context_t ctx, assuan_fd_t sockfd,
       if (n < 0 && errno == EINTR)
         ;
       else if (n < 0 && errno == EAGAIN)
-        Sleep (100);
+        _assuan_usleep (ctx, 100000); /* 100ms */
       else if (n < 0)
         return -1;
       else if (!n)
@@ -598,7 +655,164 @@ do_writen (assuan_context_t ctx, assuan_fd_t sockfd,
 
   return ret;
 }
-#endif /*HAVE_W32_SYSTEM*/
+
+
+/* Connect using the SOCKS5 protocol.  */
+static int
+socks5_connect (assuan_context_t ctx, int sock,
+                struct sockaddr *addr, socklen_t length)
+{
+  int ret;
+  /* struct sockaddr_in6 proxyaddr_in6; */
+  struct sockaddr_in  proxyaddr_in;
+  struct sockaddr *proxyaddr;
+  size_t proxyaddrlen;
+  struct sockaddr_in6 *addr_in6;
+  struct sockaddr_in  *addr_in;
+  unsigned char buffer[22];
+  size_t buflen;
+
+  /* memset (&proxyaddr_in6, 0, sizeof proxyaddr_in6); */
+  memset (&proxyaddr_in, 0, sizeof proxyaddr_in);
+
+  /* Connect to local host.  */
+  /* Fixme: First try to use IPv6.  */
+  proxyaddr_in.sin_family = AF_INET;
+  proxyaddr_in.sin_port = htons (tor_mode);
+  proxyaddr_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+  proxyaddr = (struct sockaddr *)&proxyaddr_in;
+  proxyaddrlen = sizeof proxyaddr_in;
+  ret = _assuan_connect (ctx, sock, proxyaddr, proxyaddrlen);
+  if (ret)
+    return ret;
+  buffer[0] = 5; /* RFC-1928 VER field.  */
+  buffer[1] = 1; /* NMETHODS */
+  buffer[2] = 0; /* Method: No authentication required. */
+
+  /* Negotiate method.  */
+  ret = do_writen (ctx, sock, buffer, 3);
+  if (ret)
+    return ret;
+  ret = do_readn (ctx, sock, buffer, 2);
+  if (ret)
+    return ret;
+  if (buffer[0] != 5 || buffer[1] != 0 )
+    {
+      /* Socks server returned wrong version or does not support our
+         requested method.  */
+      gpg_err_set_errno (ENOTSUP); /* Fixme: Is there a better errno? */
+      return -1;
+    }
+
+  /* Send request details (rfc-1928, 4).  */
+  buffer[0] = 5; /* VER  */
+  buffer[1] = 1; /* CMD = CONNECT  */
+  buffer[2] = 0; /* RSV  */
+  if (addr->sa_family == AF_INET6)
+    {
+      addr_in6 = (struct sockaddr_in6 *)addr;
+
+      buffer[3] = 4; /* ATYP = IPv6 */
+      memcpy (buffer+ 4, &addr_in6->sin6_addr.s6_addr, 16); /* DST.ADDR */
+      memcpy (buffer+20, &addr_in6->sin6_port, 2);          /* DST.PORT */
+      buflen = 22;
+    }
+  else
+    {
+      addr_in = (struct sockaddr_in *)addr;
+
+      buffer[3] = 1; /* ATYP = IPv4 */
+      memcpy (buffer+4, &addr_in->sin_addr.s_addr, 4); /* DST.ADDR */
+      memcpy (buffer+8, &addr_in->sin_port, 2);        /* DST.PORT */
+      buflen = 10;
+    }
+  ret = do_writen (ctx, sock, buffer, buflen);
+  if (ret)
+    return ret;
+  ret = do_readn (ctx, sock, buffer, buflen);
+  if (ret)
+    return ret;
+  if (buffer[0] != 5 || buffer[2] != 0 )
+    {
+      /* Socks server returned wrong version or the reserved field is
+         not zero.  */
+      gpg_err_set_errno (EPROTO);
+      return -1;
+    }
+  if (buffer[1])
+    {
+      switch (buffer[1])
+        {
+        case 0x01: /* general SOCKS server failure.  */
+          gpg_err_set_errno (ENETDOWN);
+          break;
+        case 0x02: /* connection not allowed by ruleset.  */
+          gpg_err_set_errno (EACCES);
+          break;
+        case 0x03: /* Network unreachable */
+          gpg_err_set_errno (ENETUNREACH);
+          break;
+        case 0x04: /* Host unreachable */
+          gpg_err_set_errno (EHOSTUNREACH);
+          break;
+        case 0x05: /* Connection refused */
+          gpg_err_set_errno (ECONNREFUSED);
+          break;
+        case 0x06: /* TTL expired */
+          gpg_err_set_errno (ETIMEDOUT);
+          break;
+        case 0x08: /* Address type not supported */
+          gpg_err_set_errno (EPROTONOSUPPORT);
+          break;
+        case 0x07: /* Command not supported */
+        default:
+          gpg_err_set_errno (ENOTSUP); /* Fixme: Is there a better errno? */
+        }
+      return -1;
+    }
+  /* FIXME: We have not way to store the actual address used by the
+     server.  */
+
+
+  return 0;
+}
+
+
+/* Return true if SOCKS shall be used.  This is the case if tor_mode
+   is enabled and and the desired address is not the loopback
+   address.  */
+static int
+use_socks (struct sockaddr *addr)
+{
+  if (!tor_mode)
+    return 0;
+  else if (addr->sa_family == AF_INET6)
+    {
+      struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
+      const unsigned char *s;
+      int i;
+
+      s = (unsigned char *)&addr_in6->sin6_addr.s6_addr;
+      if (s[15] != 1)
+        return 1;   /* Last octet is not 1 - not the loopback address.  */
+      for (i=0; i < 15; i++, s++)
+        if (*s)
+          return 1; /* Non-zero octet found - not the loopback address.  */
+
+      return 0; /* This is the loopback address.  */
+    }
+  else if (addr->sa_family == AF_INET)
+    {
+      struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
+
+      if (*(unsigned char*)&addr_in->sin_addr.s_addr == 127)
+        return 0; /* Loopback (127.0.0.0/8) */
+
+      return 1;
+    }
+  else
+    return 0;
+}
 
 
 int
@@ -658,11 +872,13 @@ _assuan_sock_connect (assuan_context_t ctx, assuan_fd_t sockfd,
         }
       return ret;
     }
+  else if (use_socks (addr))
+    {
+      return socks5_connect (ctx, HANDLE2SOCKET (sockfd), addr, addrlen);
+    }
   else
     {
-      int ret;
-      ret = _assuan_connect (ctx, HANDLE2SOCKET (sockfd), addr, addrlen);
-      return ret;
+      return _assuan_connect (ctx, HANDLE2SOCKET (sockfd), addr, addrlen);
     }
 #else
 # if HAVE_STAT
@@ -697,7 +913,15 @@ _assuan_sock_connect (assuan_context_t ctx, assuan_fd_t sockfd,
 
     }
 # endif /*HAVE_STAT*/
-  return _assuan_connect (ctx, sockfd, addr, addrlen);
+
+  if (use_socks (addr))
+    {
+      return socks5_connect (ctx, sockfd, addr, addrlen);
+    }
+  else
+    {
+      return _assuan_connect (ctx, sockfd, addr, addrlen);
+    }
 #endif
 }
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 024ffe2..0ccb981 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -20,11 +20,13 @@
 
 TESTS_ENVIRONMENT =
 
-EXTRA_DIST = motd ce-createpipe.c
+EXTRA_DIST = motd ce-createpipe.c $(testtools)
 
 BUILT_SOURCES =
 CLEANFILES =
 
+testtools = socks5
+
 TESTS = version pipeconnect
 
 if HAVE_W32CE_SYSTEM
@@ -35,10 +37,10 @@ if USE_DESCRIPTOR_PASSING
 TESTS += fdpassing
 endif
 
-
 AM_CFLAGS = $(GPG_ERROR_CFLAGS)
+AM_LDFLAGS = -no-install
 
 noinst_HEADERS = common.h
-noinst_PROGRAMS = $(TESTS) $(w32cetools)
+noinst_PROGRAMS = $(TESTS) $(w32cetools) $(testtools)
 LDADD = ../src/libassuan.la  $(NETLIBS) $(GPG_ERROR_LIBS)
 
diff --git a/tests/socks5.c b/tests/socks5.c
new file mode 100644
index 0000000..c179108
--- /dev/null
+++ b/tests/socks5.c
@@ -0,0 +1,240 @@
+/* socks5.c - Check the SOCKS5 client feature
+ * Copyright (C) 2015 g10 Code GmbH
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Assuan is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#ifdef HAVE_W32_SYSTEM
+# ifdef HAVE_WINSOCK2_H
+#  include <winsock2.h>
+# endif
+# include <windows.h>
+#else /*!HAVE_W32_SYSTEM*/
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netdb.h>
+#endif /*!HAVE_W32_SYSTEM*/
+
+#include "../src/assuan.h"
+#include "common.h"
+
+#ifndef HAVE_GETADDRINFO
+int
+main (void)
+{
+  fputs ("socks5: getaddrinfo not supported\n", stderr);
+  return 77; /* Skip test.  */
+}
+#else /* HAVE_GETADDRINFO */
+
+

+/*
+
+     M A I N
+
+*/
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  gpg_error_t err;
+  int only_v6 = 0;
+  int only_v4 = 0;
+  int use_tor = 0;
+  int disable_socks = 0;
+  assuan_fd_t sock = ASSUAN_INVALID_FD;
+  estream_t infp, outfp;
+  int c;
+
+  if (argc)
+    {
+      log_set_prefix (*argv);
+      argc--; argv++;
+    }
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          puts (
+"usage: ./socks5 [options] HOST PORT\n"
+"\n"
+"Options:\n"
+"  --verbose        Show what is going on\n"
+"  --use-tor        Use port 9050 instead of 1080\n"
+"  --inet6-only     Use only IPv6\n"
+"  --inet4-only     Use only IPv4\n"
+"  --disable-socks  Connect w/o SOCKS\n"
+);
+          exit (0);
+        }
+      if (!strcmp (*argv, "--verbose"))
+        {
+          verbose = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose = debug = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "-6") || !strcmp (*argv, "--inet6-only"))
+        {
+          only_v6 = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "-4") || !strcmp (*argv, "--inet4-only"))
+        {
+          only_v4 = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--use-tor"))
+        {
+          use_tor = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--disable-socks"))
+        {
+          disable_socks = 1;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        {
+          log_error ("unknown option '%s'\n", *argv);
+          exit (1);
+        }
+    }
+
+  if (argc != 2)
+    {
+      fputs ("usage: socks5 HOST PORT\n", stderr);
+      exit (1);
+    }
+
+  assuan_set_assuan_log_prefix (log_prefix);
+
+  if (!assuan_check_version (ASSUAN_VERSION))
+    log_error ("assuan_check_version returned an error\n");
+
+  assuan_sock_init ();
+
+  if (!disable_socks
+      && assuan_sock_set_flag (ASSUAN_INVALID_FD,
+                               use_tor? "tor-mode":"socks", 1))
+    {
+      err = gpg_error_from_syserror ();
+      log_fatal ("setting %s mode failed: %s\n",
+                 use_tor? "TOR": "SOCKS", gpg_strerror (err));
+    }
+
+  {
+    struct addrinfo hints, *res, *ai;
+    int ret;
+    int anyok = 0;
+
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_socktype = SOCK_STREAM;
+    ret = getaddrinfo (argv[0], argv[1], &hints, &res);
+    if (ret)
+      {
+        log_error ("error resolving '%s': %s\n", argv[0], gai_strerror (ret));
+        exit (1);
+      }
+
+    for (ai = res; ai; ai = ai->ai_next)
+      {
+        if (ai->ai_family == AF_INET && only_v6)
+          continue;
+        if (ai->ai_family == AF_INET6 && only_v4)
+          continue;
+
+        if (sock != ASSUAN_INVALID_FD)
+          assuan_sock_close (sock);
+        sock = assuan_sock_new (ai->ai_family, ai->ai_socktype,
+                                ai->ai_protocol);
+        if (sock == ASSUAN_INVALID_FD)
+          {
+            err = gpg_error_from_syserror ();
+            log_error ("error creating socket: %s\n", gpg_strerror (err));
+            freeaddrinfo (res);
+            exit (1);
+          }
+
+        if (assuan_sock_connect (sock,  ai->ai_addr, ai->ai_addrlen))
+          {
+            err = gpg_error_from_syserror ();
+            log_error ("assuan_sock_connect (%s) failed: %s\n",
+                       ai->ai_family == AF_INET6? "v6" :
+                       ai->ai_family == AF_INET ? "v4" : "?",
+                       gpg_strerror (err));
+          }
+        else
+          {
+            log_info ("assuan_sock_connect succeeded (%d)\n",
+                      ai->ai_family == AF_INET6? "v6" :
+                      ai->ai_family == AF_INET ? "v4" : "?");
+            anyok = 1;
+            break;
+          }
+      }
+    freeaddrinfo (res);
+    if (!anyok)
+      exit (1);
+  }
+
+  infp = es_fdopen_nc (sock, "rb");
+  if (!infp)
+    {
+      err = gpg_error_from_syserror ();
+      assuan_sock_close (sock);
+      log_fatal ("opening inbound stream failed: %s\n", gpg_strerror (err));
+    }
+  outfp = es_fdopen (sock, "wb");
+  if (!outfp)
+    {
+      err = gpg_error_from_syserror ();
+      es_fclose (infp);
+        assuan_sock_close (sock);
+        log_fatal ("opening outbound stream failed: %s\n", gpg_strerror (err));
+    }
+
+  es_fputs ("HEAD / HTTP/1.0\r\n\r\n", outfp);
+  es_fflush (outfp);
+  while ((c = es_fgetc (infp)) != EOF)
+    {
+      putchar (c);
+      if (c == '\n')
+        break;
+    }
+  es_fclose (infp);
+  es_fclose (outfp);
+
+  return errorcount ? 1 : 0;
+}
+#endif /*HAVE_GETADDRINFO*/

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/libassuan.git



More information about the Pkg-gnupg-commit mailing list