aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2015-10-18 14:24:34 +0000
committerWerner Koch <[email protected]>2015-10-18 14:37:52 +0000
commit85ece74a11718338dcd76d6e43ea8100183df02f (patch)
treed4e880ffea00bc432aff88b9331d387957340e5e /tests
parentPost release updates (diff)
downloadlibassuan-85ece74a11718338dcd76d6e43ea8100183df02f.tar.gz
libassuan-85ece74a11718338dcd76d6e43ea8100183df02f.zip
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 <[email protected]>
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am8
-rw-r--r--tests/socks5.c240
2 files changed, 245 insertions, 3 deletions
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*/