[git] Assuan - branch, master, updated. libassuan-2.3.0-2-g85ece74

by Werner Koch cvs at cvs.gnupg.org
Sun Oct 18 16:42:39 CEST 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "IPC library used by GnuPG".

The branch, master has been updated
       via  85ece74a11718338dcd76d6e43ea8100183df02f (commit)
      from  3aec1981cfd0a7b29750965c065a45ad928e66dc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
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>

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*/

-----------------------------------------------------------------------

Summary of changes:
 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(-)
 create mode 100644 tests/socks5.c


hooks/post-receive
-- 
IPC library used by GnuPG
http://git.gnupg.org




More information about the Gnupg-commits mailing list