commit d2cb92332009567ae778b3570e8fd3420c207446 Author: Nick Mathewson nickm@torproject.org Date: Tue Jul 14 14:48:22 2015 -0400
Remove tor-fw-helper code
It did a good idea, but the code-quality of libupnpc and libnatpnp is so dodgy that I'm not really comfortable including them alongside Tor proper. Instead, we'll recommend that people do the pure-go reimplementation instead. Closes ticket 13338. --- changes/ticket13338 | 6 + configure.ac | 77 ---- src/tools/include.am | 4 +- src/tools/tor-fw-helper/README | 10 + src/tools/tor-fw-helper/include.am | 36 -- src/tools/tor-fw-helper/tor-fw-helper-natpmp.c | 240 ------------ src/tools/tor-fw-helper/tor-fw-helper-natpmp.h | 47 --- src/tools/tor-fw-helper/tor-fw-helper-upnp.c | 193 --------- src/tools/tor-fw-helper/tor-fw-helper-upnp.h | 44 --- src/tools/tor-fw-helper/tor-fw-helper.c | 501 ------------------------ src/tools/tor-fw-helper/tor-fw-helper.h | 59 --- 11 files changed, 17 insertions(+), 1200 deletions(-)
diff --git a/changes/ticket13338 b/changes/ticket13338 new file mode 100644 index 0000000..a1d242f --- /dev/null +++ b/changes/ticket13338 @@ -0,0 +1,6 @@ + o Removed code: + - The internal pure-C tor-fw-helper tool is now removed from the + Tor distribution, in favor of the pure-Go clone available from + https://github.com/Yawning/tor-fw-helper . The libraries used + by the C tor-fw-helper are not, in our opinion, very confidence- + inspiring in their secure-proggramming techniques. Closes ticket 13338. diff --git a/configure.ac b/configure.ac index 214b7e6..029dbbc 100644 --- a/configure.ac +++ b/configure.ac @@ -81,24 +81,6 @@ AC_ARG_ENABLE(asciidoc, *) AC_MSG_ERROR(bad value for --disable-asciidoc) ;; esac], [asciidoc=true])
-# By default, we're not ready to ship a NAT-PMP aware Tor -AC_ARG_ENABLE(nat-pmp, - AS_HELP_STRING(--enable-nat-pmp, [enable NAT-PMP support]), - [case "${enableval}" in - yes) natpmp=true ;; - no) natpmp=false ;; - * ) AC_MSG_ERROR(bad value for --enable-nat-pmp) ;; - esac], [natpmp=false]) - -# By default, we're not ready to ship a UPnP aware Tor -AC_ARG_ENABLE(upnp, - AS_HELP_STRING(--enable-upnp, [enable UPnP support]), - [case "${enableval}" in - yes) upnp=true ;; - no) upnp=false ;; - * ) AC_MSG_ERROR(bad value for --enable-upnp) ;; - esac], [upnp=false]) - # systemd notify support AC_ARG_ENABLE(systemd, AS_HELP_STRING(--enable-systemd, [enable systemd notification support]), @@ -768,65 +750,6 @@ dnl we should try to add -fasynchronous-unwind-tables so that our backtrace dnl code will work. TOR_CHECK_CFLAGS(-fasynchronous-unwind-tables)
-dnl ------------------------------------------------------ -dnl Where do you live, libnatpmp? And how do we call you? -dnl There are no packages for Debian or Redhat as of this patch - -if test "$natpmp" = "true"; then - AC_DEFINE(NAT_PMP, 1, [Define to 1 if we are building with nat-pmp.]) - TOR_SEARCH_LIBRARY(libnatpmp, $trylibnatpmpdir, [-lnatpmp $TOR_LIB_WS32 $TOR_LIB_IPHLPAPI], - [#include <natpmp.h>], - [#ifdef _WIN32 - #define STATICLIB - #endif - #include <natpmp.h>], - [ int r; - natpmp_t natpmp; - natpmpresp_t response; - r = initnatpmp(&natpmp, 0, 0);], - [printf("initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS"); - exit(0);], - [--with-libnatpmp-dir], - [/usr/lib/]) -fi - - -dnl ------------------------------------------------------ -dnl Where do you live, libminiupnpc? And how do we call you? -dnl There are no packages for Debian or Redhat as of this patch - -if test "$upnp" = "true"; then - AC_DEFINE(MINIUPNPC, 1, [Define to 1 if we are building with UPnP.]) - - dnl Before we call TOR_SEARCH_LIBRARY we'll do a quick compile test - dnl to see if we have miniupnpc-1.5 or -1.6 - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <miniupnpc/miniupnpc.h>], - [upnpDiscover(1, 0, 0, 0);exit(0);])],[miniupnpc15="true"],[miniupnpc15="false"]) - - if test "$miniupnpc15" = "true" ; then - AC_DEFINE([MINIUPNPC15],[1],[libminiupnpc version 1.5 found]) - TOR_SEARCH_LIBRARY(libminiupnpc, $trylibminiupnpcdir, [-lminiupnpc $TOR_LIB_WS32 $TOR_LIB_IPHLPAPI], - [#include <miniupnpc/miniwget.h> - #include <miniupnpc/miniupnpc.h> - #include <miniupnpc/upnpcommands.h>], - [void upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport);], - [upnpDiscover(1, 0, 0, 0); exit(0);], - [--with-libminiupnpc-dir], - [/usr/lib/]) - else - TOR_SEARCH_LIBRARY(libminiupnpc, $trylibminiupnpcdir, [-lminiupnpc $TOR_LIB_WS32 $TOR_LIB_IPHLPAPI], - [#include <miniupnpc/miniwget.h> - #include <miniupnpc/miniupnpc.h> - #include <miniupnpc/upnpcommands.h>], - [void upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport, int ipv6, int * error);], - [upnpDiscover(1, 0, 0, 0, 0, 0); exit(0);], - [--with-libminiupnpc-dir], - [/usr/lib/]) - fi -fi - dnl ============================================================ dnl Check for libseccomp
diff --git a/src/tools/include.am b/src/tools/include.am index 5d778c1..ebdd349 100644 --- a/src/tools/include.am +++ b/src/tools/include.am @@ -43,6 +43,4 @@ src_tools_tor_checkkey_LDADD = src/common/libor.a src/common/libor-crypto.a \ @TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
-include src/tools/tor-fw-helper/include.am - - +EXTRA_DIST += src/tools/tor-fw-helper/README diff --git a/src/tools/tor-fw-helper/README b/src/tools/tor-fw-helper/README new file mode 100644 index 0000000..3868cc2 --- /dev/null +++ b/src/tools/tor-fw-helper/README @@ -0,0 +1,10 @@ + +We no longer recommend the use of this tool. Instead, please use the +pure-Go version of tor-fw-helper available at + https://github.com/Yawning/tor-fw-helper + +Why? + +The C code here was fine, but frankly: we don't trust the underlying +libraries. They don't seem to have been written with network security +in mind, and we have very little faith in their safety. diff --git a/src/tools/tor-fw-helper/include.am b/src/tools/tor-fw-helper/include.am deleted file mode 100644 index 1f862e6..0000000 --- a/src/tools/tor-fw-helper/include.am +++ /dev/null @@ -1,36 +0,0 @@ -if USE_FW_HELPER -bin_PROGRAMS+= src/tools/tor-fw-helper/tor-fw-helper -endif - -src_tools_tor_fw_helper_tor_fw_helper_SOURCES = \ - src/tools/tor-fw-helper/tor-fw-helper.c \ - src/tools/tor-fw-helper/tor-fw-helper-natpmp.c \ - src/tools/tor-fw-helper/tor-fw-helper-upnp.c -noinst_HEADERS+= \ - src/tools/tor-fw-helper/tor-fw-helper.h \ - src/tools/tor-fw-helper/tor-fw-helper-natpmp.h \ - src/tools/tor-fw-helper/tor-fw-helper-upnp.h - -if NAT_PMP -nat_pmp_ldflags = @TOR_LDFLAGS_libnatpmp@ -nat_pmp_ldadd = -lnatpmp @TOR_LIB_IPHLPAPI@ -nat_pmp_cppflags = @TOR_CPPFLAGS_libnatpmp@ -else -nat_pmp_ldflags = -nat_pmp_ldadd = -nat_pmp_cppflags = -endif - -if MINIUPNPC -miniupnpc_ldflags = @TOR_LDFLAGS_libminiupnpc@ -miniupnpc_ldadd = -lminiupnpc @TOR_LIB_IPHLPAPI@ -miniupnpc_cppflags = @TOR_CPPFLAGS_libminiupnpc@ -else -miniupnpc_ldflags = -miniupnpc_ldadd = -miniupnpc_cppflags = -endif - -src_tools_tor_fw_helper_tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags) -src_tools_tor_fw_helper_tor_fw_helper_LDADD = src/common/libor.a $(nat_pmp_ldadd) $(miniupnpc_ldadd) -lm @TOR_LIB_WS32@ -src_tools_tor_fw_helper_tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags) -I"$(top_srcdir)/src/ext" diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c deleted file mode 100644 index 6369966..0000000 --- a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2015, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file tor-fw-helper-natpmp.c - * \brief The implementation of our NAT-PMP firewall helper. - **/ - -#include "orconfig.h" -#ifdef NAT_PMP -#ifdef _WIN32 -#define STATICLIB -#endif -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#ifndef _WIN32 -#include <arpa/inet.h> -#endif - -// debugging stuff -#include <assert.h> - -#include "compat.h" - -#include "tor-fw-helper.h" -#include "tor-fw-helper-natpmp.h" - -/** This hooks NAT-PMP into our multi-backend API. */ -static tor_fw_backend_t tor_natpmp_backend = { - "natpmp", - sizeof(struct natpmp_state_t), - tor_natpmp_init, - tor_natpmp_cleanup, - tor_natpmp_fetch_public_ip, - tor_natpmp_add_tcp_mapping -}; - -/** Return the backend for NAT-PMP. */ -const tor_fw_backend_t * -tor_fw_get_natpmp_backend(void) -{ - return &tor_natpmp_backend; -} - -/** Initialize the NAT-PMP backend and store the results in - * <b>backend_state</b>.*/ -int -tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state) -{ - natpmp_state_t *state = (natpmp_state_t *) backend_state; - int r = 0; - - memset(&(state->natpmp), 0, sizeof(natpmp_t)); - memset(&(state->response), 0, sizeof(natpmpresp_t)); - state->init = 0; - state->protocol = NATPMP_PROTOCOL_TCP; - state->lease = NATPMP_DEFAULT_LEASE; - - if (tor_fw_options->verbose) - fprintf(stderr, "V: natpmp init...\n"); - - r = initnatpmp(&(state->natpmp), 0, 0); - if (r == 0) { - state->init = 1; - fprintf(stderr, "V: natpmp initialized...\n"); - return r; - } else { - fprintf(stderr, "V: natpmp failed to initialize...\n"); - return r; - } -} - -/** Tear down the NAT-PMP connection stored in <b>backend_state</b>.*/ -int -tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state) -{ - natpmp_state_t *state = (natpmp_state_t *) backend_state; - int r = 0; - if (tor_fw_options->verbose) - fprintf(stderr, "V: natpmp cleanup...\n"); - r = closenatpmp(&(state->natpmp)); - if (tor_fw_options->verbose) - fprintf(stderr, "V: closing natpmp socket: %d\n", r); - return r; -} - -/** Use select() to wait until we can read on fd. */ -static int -wait_until_fd_readable(tor_socket_t fd, struct timeval *timeout) -{ - int r; - fd_set fds; - -#ifndef WIN32 - if (fd >= FD_SETSIZE) { - fprintf(stderr, "E: NAT-PMP FD_SETSIZE error %d\n", fd); - return -1; - } -#endif - - FD_ZERO(&fds); - FD_SET(fd, &fds); - r = select(fd+1, &fds, NULL, NULL, timeout); - if (r == -1) { - fprintf(stderr, "V: select failed in wait_until_fd_readable: %s\n", - tor_socket_strerror(tor_socket_errno(fd))); - return -1; - } - /* XXXX we should really check to see whether fd was readable, or we timed - out. */ - return 0; -} - -int -tor_natpmp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, - int is_verbose, void *backend_state) -{ - int r = 0; - int x = 0; - int sav_errno; - natpmp_state_t *state = (natpmp_state_t *) backend_state; - - struct timeval timeout; - - if (is_verbose) - fprintf(stderr, "V: sending natpmp portmapping request...\n"); - r = sendnewportmappingrequest(&(state->natpmp), state->protocol, - internal_port, - external_port, - state->lease); - if (is_verbose) - fprintf(stderr, "tor-fw-helper: NAT-PMP sendnewportmappingrequest " - "returned %d (%s)\n", r, r==12?"SUCCESS":"FAILED"); - - do { - getnatpmprequesttimeout(&(state->natpmp), &timeout); - x = wait_until_fd_readable(state->natpmp.s, &timeout); - if (x == -1) - return -1; - - if (is_verbose) - fprintf(stderr, "V: attempting to readnatpmpreponseorretry...\n"); - r = readnatpmpresponseorretry(&(state->natpmp), &(state->response)); - sav_errno = tor_socket_errno(state->natpmp.s); - - if (r<0 && r!=NATPMP_TRYAGAIN) { - fprintf(stderr, "E: readnatpmpresponseorretry failed %d\n", r); - fprintf(stderr, "E: errno=%d '%s'\n", sav_errno, - tor_socket_strerror(sav_errno)); - } - - } while (r == NATPMP_TRYAGAIN); - - if (r != 0) { - /* XXX TODO: NATPMP_* should be formatted into useful error strings */ - fprintf(stderr, "E: NAT-PMP It appears that something went wrong:" - " %d\n", r); - if (r == -51) - fprintf(stderr, "E: NAT-PMP It appears that the request was " - "unauthorized\n"); - return r; - } - - if (r == NATPMP_SUCCESS) { - fprintf(stderr, "tor-fw-helper: NAT-PMP mapped public port %hu to" - " localport %hu liftime %u\n", - (state->response).pnu.newportmapping.mappedpublicport, - (state->response).pnu.newportmapping.privateport, - (state->response).pnu.newportmapping.lifetime); - } - - return (r == NATPMP_SUCCESS) ? 0 : -1; -} - -/** Fetch our likely public IP from our upstream NAT-PMP enabled NAT device. - * Use the connection context stored in <b>backend_state</b>. */ -int -tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options, - void *backend_state) -{ - int r = 0; - int x = 0; - int sav_errno; - natpmp_state_t *state = (natpmp_state_t *) backend_state; - - struct timeval timeout; - - r = sendpublicaddressrequest(&(state->natpmp)); - fprintf(stderr, "tor-fw-helper: NAT-PMP sendpublicaddressrequest returned" - " %d (%s)\n", r, r==2?"SUCCESS":"FAILED"); - - do { - getnatpmprequesttimeout(&(state->natpmp), &timeout); - - x = wait_until_fd_readable(state->natpmp.s, &timeout); - if (x == -1) - return -1; - - if (tor_fw_options->verbose) - fprintf(stderr, "V: NAT-PMP attempting to read reponse...\n"); - r = readnatpmpresponseorretry(&(state->natpmp), &(state->response)); - sav_errno = tor_socket_errno(state->natpmp.s); - - if (tor_fw_options->verbose) - fprintf(stderr, "V: NAT-PMP readnatpmpresponseorretry returned" - " %d\n", r); - - if ( r < 0 && r != NATPMP_TRYAGAIN) { - fprintf(stderr, "E: NAT-PMP readnatpmpresponseorretry failed %d\n", - r); - fprintf(stderr, "E: NAT-PMP errno=%d '%s'\n", sav_errno, - tor_socket_strerror(sav_errno)); - } - - } while (r == NATPMP_TRYAGAIN ); - - if (r != 0) { - fprintf(stderr, "E: NAT-PMP It appears that something went wrong:" - " %d\n", r); - return r; - } - - fprintf(stderr, "tor-fw-helper: ExternalIPAddress = %s\n", - inet_ntoa((state->response).pnu.publicaddress.addr)); - tor_fw_options->public_ip_status = 1; - - if (tor_fw_options->verbose) { - fprintf(stderr, "V: result = %u\n", r); - fprintf(stderr, "V: type = %u\n", (state->response).type); - fprintf(stderr, "V: resultcode = %u\n", (state->response).resultcode); - fprintf(stderr, "V: epoch = %u\n", (state->response).epoch); - } - - return r; -} -#endif - diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h deleted file mode 100644 index abc5e11..0000000 --- a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2015, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file tor-fw-helper-natpmp.h - **/ - -#ifdef NAT_PMP -#ifndef TOR_TOR_FW_HELPER_NATPMP_H -#define TOR_TOR_FW_HELPER_NATPMP_H - -#include <natpmp.h> - -/** This is the default NAT-PMP lease time in seconds. */ -#define NATPMP_DEFAULT_LEASE 3600 -/** NAT-PMP has many codes for success; this is one of them. */ -#define NATPMP_SUCCESS 0 - -/** This is our NAT-PMP meta structure - it holds our request data, responses, - * various NAT-PMP parameters, and of course the status of the motion in the - * NAT-PMP ocean. */ -typedef struct natpmp_state_t { - natpmp_t natpmp; - natpmpresp_t response; - int fetch_public_ip; - int status; - int init; /**< Have we been initialized? */ - int protocol; /**< This will only be TCP. */ - int lease; -} natpmp_state_t; - -const tor_fw_backend_t *tor_fw_get_natpmp_backend(void); - -int tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state); - -int tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state); - -int tor_natpmp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, - int is_verbose, void *backend_state); - -int tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options, - void *backend_state); - -#endif -#endif - diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.c b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c deleted file mode 100644 index e5495c9..0000000 --- a/src/tools/tor-fw-helper/tor-fw-helper-upnp.c +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2015, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file tor-fw-helper-upnp.c - * \brief The implementation of our UPnP firewall helper. - **/ - -#include "orconfig.h" -#ifdef MINIUPNPC -#ifdef _WIN32 -#define STATICLIB -#endif -#include <stdint.h> -#include <string.h> -#include <stdio.h> - -#include <assert.h> - -#include "compat.h" -#include "tor-fw-helper.h" -#include "tor-fw-helper-upnp.h" - -/** UPnP timeout value. */ -#define UPNP_DISCOVER_TIMEOUT 2000 -/** Description of the port mapping in the UPnP table. */ -#define UPNP_DESC "Tor relay" - -/* XXX TODO: We should print these as a useful user string when we return the - * number to a user */ -/** Magic numbers as miniupnpc return codes. */ -#define UPNP_ERR_SUCCESS 0 -#define UPNP_ERR_NODEVICESFOUND 1 -#define UPNP_ERR_NOIGDFOUND 2 -#define UPNP_ERR_ADDPORTMAPPING 3 -#define UPNP_ERR_GETPORTMAPPING 4 -#define UPNP_ERR_DELPORTMAPPING 5 -#define UPNP_ERR_GETEXTERNALIP 6 -#define UPNP_ERR_INVAL 7 -#define UPNP_ERR_OTHER 8 -#define UPNP_SUCCESS 1 - -/** This hooks miniupnpc into our multi-backend API. */ -static tor_fw_backend_t tor_miniupnp_backend = { - "miniupnp", - sizeof(struct miniupnpc_state_t), - tor_upnp_init, - tor_upnp_cleanup, - tor_upnp_fetch_public_ip, - tor_upnp_add_tcp_mapping -}; - -/** Return the backend for miniupnp. */ -const tor_fw_backend_t * -tor_fw_get_miniupnp_backend(void) -{ - return &tor_miniupnp_backend; -} - -/** Initialize the UPnP backend and store the results in - * <b>backend_state</b>.*/ -int -tor_upnp_init(tor_fw_options_t *options, void *backend_state) -{ - /* - This leaks the user agent from the client to the router - perhaps we don't - want to do that? eg: - - User-Agent: Ubuntu/10.04, UPnP/1.0, MiniUPnPc/1.4 - - */ - miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; - struct UPNPDev *devlist; - int r; - - memset(&(state->urls), 0, sizeof(struct UPNPUrls)); - memset(&(state->data), 0, sizeof(struct IGDdatas)); - state->init = 0; - -#ifdef MINIUPNPC15 - devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0); -#else - devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0, 0, NULL); -#endif - if (NULL == devlist) { - fprintf(stderr, "E: upnpDiscover returned: NULL\n"); - return UPNP_ERR_NODEVICESFOUND; - } - - assert(options); - r = UPNP_GetValidIGD(devlist, &(state->urls), &(state->data), - state->lanaddr, UPNP_LANADDR_SZ); - fprintf(stderr, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r, - r==UPNP_SUCCESS?"SUCCESS":"FAILED"); - - freeUPNPDevlist(devlist); - - if (r != 1 && r != 2) - return UPNP_ERR_NOIGDFOUND; - - state->init = 1; - return UPNP_ERR_SUCCESS; -} - -/** Tear down the UPnP connection stored in <b>backend_state</b>.*/ -int -tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state) -{ - - miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; - assert(options); - - if (state->init) - FreeUPNPUrls(&(state->urls)); - state->init = 0; - - return UPNP_ERR_SUCCESS; -} - -/** Fetch our likely public IP from our upstream UPnP IGD enabled NAT device. - * Use the connection context stored in <b>backend_state</b>. */ -int -tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state) -{ - miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; - int r; - char externalIPAddress[16]; - - if (!state->init) { - r = tor_upnp_init(options, state); - if (r != UPNP_ERR_SUCCESS) - return r; - } - - r = UPNP_GetExternalIPAddress(state->urls.controlURL, - state->data.first.servicetype, - externalIPAddress); - - if (r != UPNPCOMMAND_SUCCESS) - goto err; - - if (externalIPAddress[0]) { - fprintf(stderr, "tor-fw-helper: ExternalIPAddress = %s\n", - externalIPAddress); tor_upnp_cleanup(options, state); - options->public_ip_status = 1; - return UPNP_ERR_SUCCESS; - } else { - goto err; - } - - err: - tor_upnp_cleanup(options, state); - return UPNP_ERR_GETEXTERNALIP; -} - -int -tor_upnp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, - int is_verbose, void *backend_state) -{ - int retval; - char internal_port_str[6]; - char external_port_str[6]; - miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; - - if (!state->init) { - fprintf(stderr, "E: %s but state is not initialized.\n", __func__); - return -1; - } - - if (is_verbose) - fprintf(stderr, "V: UPnP: internal port: %u, external port: %u\n", - internal_port, external_port); - - tor_snprintf(internal_port_str, sizeof(internal_port_str), - "%u", internal_port); - tor_snprintf(external_port_str, sizeof(external_port_str), - "%u", external_port); - - retval = UPNP_AddPortMapping(state->urls.controlURL, - state->data.first.servicetype, - external_port_str, internal_port_str, -#ifdef MINIUPNPC15 - state->lanaddr, UPNP_DESC, "TCP", 0); -#else - state->lanaddr, UPNP_DESC, "TCP", 0, 0); -#endif - - return (retval == UPNP_ERR_SUCCESS) ? 0 : -1; -} - -#endif - diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h deleted file mode 100644 index bc9476e..0000000 --- a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2015, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file tor-fw-helper-upnp.h - * \brief The main header for our firewall helper. - **/ - -#ifdef MINIUPNPC -#ifndef TOR_TOR_FW_HELPER_UPNP_H -#define TOR_TOR_FW_HELPER_UPNP_H - -#include <miniupnpc/miniwget.h> -#include <miniupnpc/miniupnpc.h> -#include <miniupnpc/upnpcommands.h> -#include <miniupnpc/upnperrors.h> - -/** This is a magic number for miniupnpc lan address size. */ -#define UPNP_LANADDR_SZ 64 - -/** This is our miniupnpc meta structure - it holds our request data, - * responses, and various miniupnpc parameters. */ -typedef struct miniupnpc_state_t { - struct UPNPUrls urls; - struct IGDdatas data; - char lanaddr[UPNP_LANADDR_SZ]; - int init; -} miniupnpc_state_t; - -const tor_fw_backend_t *tor_fw_get_miniupnp_backend(void); - -int tor_upnp_init(tor_fw_options_t *options, void *backend_state); - -int tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state); - -int tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state); - -int tor_upnp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port, - int is_verbose, void *backend_state); - -#endif -#endif - diff --git a/src/tools/tor-fw-helper/tor-fw-helper.c b/src/tools/tor-fw-helper/tor-fw-helper.c deleted file mode 100644 index fdc0e1a..0000000 --- a/src/tools/tor-fw-helper/tor-fw-helper.c +++ /dev/null @@ -1,501 +0,0 @@ -/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2015, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file tor-fw-helper.c - * \brief The main wrapper around our firewall helper logic. - **/ - -/* - * tor-fw-helper is a tool for opening firewalls with NAT-PMP and UPnP; this - * tool is designed to be called by hand or by Tor by way of a exec() at a - * later date. - */ - -#include "orconfig.h" -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <getopt.h> -#include <time.h> -#include <string.h> -#include <assert.h> - -#include "container.h" - -#ifdef _WIN32 -#include <winsock2.h> -#endif - -#include "tor-fw-helper.h" -#ifdef NAT_PMP -#include "tor-fw-helper-natpmp.h" -#endif -#ifdef MINIUPNPC -#include "tor-fw-helper-upnp.h" -#endif - -/** This is our meta storage type - it holds information about each helper - including the total number of helper backends, function pointers, and helper - state. */ -typedef struct backends_t { - /** The total number of backends */ - int n_backends; - /** The backend functions as an array */ - tor_fw_backend_t backend_ops[MAX_BACKENDS]; - /** The internal backend state */ - void *backend_state[MAX_BACKENDS]; -} backends_t; - -/** Initialize each backend helper with the user input stored in <b>options</b> - * and put the results in the <b>backends</b> struct. */ -static int -init_backends(tor_fw_options_t *options, backends_t *backends) -{ - int n_available = 0; - int i, r, n; - tor_fw_backend_t *backend_ops_list[MAX_BACKENDS]; - void *data = NULL; - /* First, build a list of the working backends. */ - n = 0; -#ifdef MINIUPNPC - backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_miniupnp_backend(); -#endif -#ifdef NAT_PMP - backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_natpmp_backend(); -#endif - n_available = n; - - /* Now, for each backend that might work, try to initialize it. - * That's how we roll, initialized. - */ - n = 0; - for (i=0; i<n_available; ++i) { - data = calloc(1, backend_ops_list[i]->state_len); - if (!data) { - perror("calloc"); - exit(1); - } - r = backend_ops_list[i]->init(options, data); - if (r == 0) { - backends->backend_ops[n] = *backend_ops_list[i]; - backends->backend_state[n] = data; - n++; - } else { - free(data); - } - } - backends->n_backends = n; - - return n; -} - -/** Return the proper commandline switches when the user needs information. */ -static void -usage(void) -{ - fprintf(stderr, "tor-fw-helper usage:\n" - " [-h|--help]\n" - " [-T|--test-commandline]\n" - " [-v|--verbose]\n" - " [-g|--fetch-public-ip]\n" - " [-p|--forward-port ([<external port>]:<internal port>)]\n"); -} - -/** Log commandline options to a hardcoded file <b>tor-fw-helper.log</b> in the - * current working directory. */ -static int -log_commandline_options(int argc, char **argv) -{ - int i, retval; - FILE *logfile; - time_t now; - - /* Open the log file */ - logfile = fopen("tor-fw-helper.log", "a"); - if (NULL == logfile) - return -1; - - /* Send all commandline arguments to the file */ - now = time(NULL); - retval = fprintf(logfile, "START: %s\n", ctime(&now)); - for (i = 0; i < argc; i++) { - retval = fprintf(logfile, "ARG: %d: %s\n", i, argv[i]); - if (retval < 0) - goto error; - - retval = fprintf(stderr, "ARG: %d: %s\n", i, argv[i]); - if (retval < 0) - goto error; - } - now = time(NULL); - retval = fprintf(logfile, "END: %s\n", ctime(&now)); - - /* Close and clean up */ - retval = fclose(logfile); - return retval; - - /* If there was an error during writing */ - error: - fclose(logfile); - return -1; -} - -/** Iterate over over each of the supported <b>backends</b> and attempt to - * fetch the public ip. */ -static void -tor_fw_fetch_public_ip(tor_fw_options_t *tor_fw_options, - backends_t *backends) -{ - int i; - int r = 0; - - if (tor_fw_options->verbose) - fprintf(stderr, "V: tor_fw_fetch_public_ip\n"); - - for (i=0; i<backends->n_backends; ++i) { - if (tor_fw_options->verbose) { - fprintf(stderr, "V: running backend_state now: %i\n", i); - fprintf(stderr, "V: size of backend state: %u\n", - (int)(backends->backend_ops)[i].state_len); - fprintf(stderr, "V: backend state name: %s\n", - (char *)(backends->backend_ops)[i].name); - } - r = backends->backend_ops[i].fetch_public_ip(tor_fw_options, - backends->backend_state[i]); - fprintf(stderr, "tor-fw-helper: tor_fw_fetch_public_ip backend %s " - " returned: %i\n", (char *)(backends->backend_ops)[i].name, r); - } -} - -/** Print a spec-conformant string to stdout describing the results of - * the TCP port forwarding operation from <b>external_port</b> to - * <b>internal_port</b>. */ -static void -tor_fw_helper_report_port_fw_results(uint16_t internal_port, - uint16_t external_port, - int succeded, - const char *message) -{ - char *report_string = NULL; - - tor_asprintf(&report_string, "%s %s %u %u %s %s\n", - "tor-fw-helper", - "tcp-forward", - external_port, internal_port, - succeded ? "SUCCESS" : "FAIL", - message); - fprintf(stdout, "%s", report_string); - fflush(stdout); - tor_free(report_string); -} - -#define tor_fw_helper_report_port_fw_fail(i, e, m) \ - tor_fw_helper_report_port_fw_results((i), (e), 0, (m)) - -#define tor_fw_helper_report_port_fw_success(i, e, m) \ - tor_fw_helper_report_port_fw_results((i), (e), 1, (m)) - -/** Return a heap-allocated string containing the list of our - * backends. It can be used in log messages. Be sure to free it - * afterwards! */ -static char * -get_list_of_backends_string(backends_t *backends) -{ - char *backend_names = NULL; - int i; - smartlist_t *backend_names_sl = smartlist_new(); - - assert(backends->n_backends); - - for (i=0; i<backends->n_backends; ++i) - smartlist_add(backend_names_sl, (char *) backends->backend_ops[i].name); - - backend_names = smartlist_join_strings(backend_names_sl, ", ", 0, NULL); - smartlist_free(backend_names_sl); - - return backend_names; -} - -/** Iterate over each of the supported <b>backends</b> and attempt to add a - * port forward for the port stored in <b>tor_fw_options</b>. */ -static void -tor_fw_add_ports(tor_fw_options_t *tor_fw_options, - backends_t *backends) -{ - int i; - int r = 0; - int succeeded = 0; - - if (tor_fw_options->verbose) - fprintf(stderr, "V: %s\n", __func__); - - /** Loop all ports that need to be forwarded, and try to use our - * backends for each port. If a backend succeeds, break the loop, - * report success and get to the next port. If all backends fail, - * report failure for that port. */ - SMARTLIST_FOREACH_BEGIN(tor_fw_options->ports_to_forward, - port_to_forward_t *, port_to_forward) { - - succeeded = 0; - - for (i=0; i<backends->n_backends; ++i) { - if (tor_fw_options->verbose) { - fprintf(stderr, "V: running backend_state now: %i\n", i); - fprintf(stderr, "V: size of backend state: %u\n", - (int)(backends->backend_ops)[i].state_len); - fprintf(stderr, "V: backend state name: %s\n", - (const char *) backends->backend_ops[i].name); - } - - r = - backends->backend_ops[i].add_tcp_mapping(port_to_forward->internal_port, - port_to_forward->external_port, - tor_fw_options->verbose, - backends->backend_state[i]); - if (r == 0) { /* backend success */ - tor_fw_helper_report_port_fw_success(port_to_forward->internal_port, - port_to_forward->external_port, - backends->backend_ops[i].name); - succeeded = 1; - break; - } - - fprintf(stderr, "tor-fw-helper: tor_fw_add_port backend %s " - "returned: %i\n", - (const char *) backends->backend_ops[i].name, r); - } - - if (!succeeded) { /* all backends failed */ - char *list_of_backends_str = get_list_of_backends_string(backends); - char *fail_msg = NULL; - tor_asprintf(&fail_msg, "All port forwarding backends (%s) failed.", - list_of_backends_str); - tor_fw_helper_report_port_fw_fail(port_to_forward->internal_port, - port_to_forward->external_port, - fail_msg); - tor_free(list_of_backends_str); - tor_free(fail_msg); - } - - } SMARTLIST_FOREACH_END(port_to_forward); -} - -/** Called before we make any calls to network-related functions. - * (Some operating systems require their network libraries to be - * initialized.) (from common/compat.c) */ -static int -tor_fw_helper_network_init(void) -{ -#ifdef _WIN32 - /* This silly exercise is necessary before windows will allow - * gethostbyname to work. */ - WSADATA WSAData; - int r; - r = WSAStartup(0x101, &WSAData); - if (r) { - fprintf(stderr, "E: Error initializing Windows network layer " - "- code was %d", r); - return -1; - } - /* WSAData.iMaxSockets might show the max sockets we're allowed to use. - * We might use it to complain if we're trying to be a server but have - * too few sockets available. */ -#endif - return 0; -} - -/** Parse the '-p' argument of tor-fw-helper. Its format is - * [<external port>]:<internal port>, and <external port> is optional. - * Return NULL if <b>arg</b> was c0rrupted. */ -static port_to_forward_t * -parse_port(const char *arg) -{ - smartlist_t *sl = smartlist_new(); - port_to_forward_t *port_to_forward = NULL; - char *port_str = NULL; - int ok; - int port; - - smartlist_split_string(sl, arg, ":", 0, 0); - if (smartlist_len(sl) != 2) - goto err; - - port_to_forward = tor_malloc(sizeof(port_to_forward_t)); - if (!port_to_forward) - goto err; - - port_str = smartlist_get(sl, 0); /* macroify ? */ - port = (int)tor_parse_long(port_str, 10, 1, 65535, &ok, NULL); - if (!ok && strlen(port_str)) /* ":1555" is valid */ - goto err; - port_to_forward->external_port = port; - - port_str = smartlist_get(sl, 1); - port = (int)tor_parse_long(port_str, 10, 1, 65535, &ok, NULL); - if (!ok) - goto err; - port_to_forward->internal_port = port; - - goto done; - - err: - tor_free(port_to_forward); - - done: - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - smartlist_free(sl); - - return port_to_forward; -} - -/** Report a failure of epic proportions: We didn't manage to - * initialize any port forwarding backends. */ -static void -report_full_fail(const smartlist_t *ports_to_forward) -{ - if (!ports_to_forward) - return; - - SMARTLIST_FOREACH_BEGIN(ports_to_forward, - const port_to_forward_t *, port_to_forward) { - tor_fw_helper_report_port_fw_fail(port_to_forward->internal_port, - port_to_forward->external_port, - "All backends (NAT-PMP, UPnP) failed " - "to initialize!"); /* XXX hardcoded */ - } SMARTLIST_FOREACH_END(port_to_forward); -} - -int -main(int argc, char **argv) -{ - int r = 0; - int c = 0; - - tor_fw_options_t tor_fw_options; - backends_t backend_state; - - memset(&tor_fw_options, 0, sizeof(tor_fw_options)); - memset(&backend_state, 0, sizeof(backend_state)); - - // Parse CLI arguments. - while (1) { - int option_index = 0; - static struct option long_options[] = - { - {"verbose", 0, 0, 'v'}, - {"help", 0, 0, 'h'}, - {"port", 1, 0, 'p'}, - {"fetch-public-ip", 0, 0, 'g'}, - {"test-commandline", 0, 0, 'T'}, - {0, 0, 0, 0} - }; - - c = getopt_long(argc, argv, "vhp:gT", - long_options, &option_index); - if (c == -1) - break; - - switch (c) { - case 'v': tor_fw_options.verbose = 1; break; - case 'h': tor_fw_options.help = 1; usage(); exit(1); break; - case 'p': { - port_to_forward_t *port_to_forward = parse_port(optarg); - if (!port_to_forward) { - fprintf(stderr, "E: Failed to parse '%s'.\n", optarg); - usage(); - exit(1); - } - - /* If no external port was given (it's optional), set it to be - * equal with the internal port. */ - if (!port_to_forward->external_port) { - assert(port_to_forward->internal_port); - if (tor_fw_options.verbose) - fprintf(stderr, "V: No external port was given. Setting to %u.\n", - port_to_forward->internal_port); - port_to_forward->external_port = port_to_forward->internal_port; - } - - if (!tor_fw_options.ports_to_forward) - tor_fw_options.ports_to_forward = smartlist_new(); - - smartlist_add(tor_fw_options.ports_to_forward, port_to_forward); - - break; - } - case 'g': tor_fw_options.fetch_public_ip = 1; break; - case 'T': tor_fw_options.test_commandline = 1; break; - case '?': break; - default : fprintf(stderr, "Unknown option!\n"); usage(); exit(1); - } - } - - { // Verbose output - - if (tor_fw_options.verbose) - fprintf(stderr, "V: tor-fw-helper version %s\n" - "V: We were called with the following arguments:\n" - "V: verbose = %d, help = %d, fetch_public_ip = %u\n", - tor_fw_version, tor_fw_options.verbose, tor_fw_options.help, - tor_fw_options.fetch_public_ip); - - if (tor_fw_options.verbose && tor_fw_options.ports_to_forward) { - fprintf(stderr, "V: TCP forwarding:\n"); - SMARTLIST_FOREACH(tor_fw_options.ports_to_forward, - const port_to_forward_t *, port_to_forward, - fprintf(stderr, "V: External: %u, Internal: %u\n", - port_to_forward->external_port, - port_to_forward->internal_port)); - } - } - - if (tor_fw_options.test_commandline) { - return log_commandline_options(argc, argv); - } - - // See if the user actually wants us to do something. - if (!tor_fw_options.fetch_public_ip && !tor_fw_options.ports_to_forward) { - fprintf(stderr, "E: We require a port to be forwarded or " - "fetch_public_ip request!\n"); - usage(); - exit(1); - } - - // Initialize networking - if (tor_fw_helper_network_init()) - exit(1); - - // Initalize the various fw-helper backend helpers - r = init_backends(&tor_fw_options, &backend_state); - if (!r) { // all backends failed: - // report our failure - report_full_fail(tor_fw_options.ports_to_forward); - fprintf(stderr, "tor-fw-helper: All backends failed.\n"); - exit(1); - } else { // some backends succeeded: - fprintf(stderr, "tor-fw-helper: %i NAT traversal helper(s) loaded\n", r); - } - - // Forward TCP ports. - if (tor_fw_options.ports_to_forward) { - tor_fw_add_ports(&tor_fw_options, &backend_state); - } - - // Fetch our public IP. - if (tor_fw_options.fetch_public_ip) { - tor_fw_fetch_public_ip(&tor_fw_options, &backend_state); - } - - // Cleanup and exit. - if (tor_fw_options.ports_to_forward) { - SMARTLIST_FOREACH(tor_fw_options.ports_to_forward, - port_to_forward_t *, port, - tor_free(port)); - smartlist_free(tor_fw_options.ports_to_forward); - } - - exit(0); -} - diff --git a/src/tools/tor-fw-helper/tor-fw-helper.h b/src/tools/tor-fw-helper/tor-fw-helper.h deleted file mode 100644 index 4ebc75d..0000000 --- a/src/tools/tor-fw-helper/tor-fw-helper.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. - * Copyright (c) 2010-2015, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file tor-fw-helper.h - * \brief The main header for our firewall helper. - **/ - -#ifndef TOR_TOR_FW_HELPER_H -#define TOR_TOR_FW_HELPER_H - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <getopt.h> -#include <time.h> - -/** The current version of tor-fw-helper. */ -#define tor_fw_version "0.2" - -/** This is an arbitrary hard limit - We currently have two (NAT-PMP and UPnP). - We're likely going to add the Intel UPnP library but nothing else comes to - mind at the moment. */ -#define MAX_BACKENDS 23 - -/** Forward traffic received in port <b>external_port</b> in the - * external side of our NAT to <b>internal_port</b> in this host. */ -typedef struct { - uint16_t external_port; - uint16_t internal_port; -} port_to_forward_t; - -/** This is where we store parsed commandline options. */ -typedef struct { - int verbose; - int help; - int test_commandline; - struct smartlist_t *ports_to_forward; - int fetch_public_ip; - int nat_pmp_status; - int upnp_status; - int public_ip_status; -} tor_fw_options_t; - -/** This is our main structure that defines our backend helper API; each helper - * must conform to these public methods if it expects to be handled in a - * non-special way. */ -typedef struct tor_fw_backend_t { - const char *name; - size_t state_len; - int (*init)(tor_fw_options_t *options, void *backend_state); - int (*cleanup)(tor_fw_options_t *options, void *backend_state); - int (*fetch_public_ip)(tor_fw_options_t *options, void *backend_state); - int (*add_tcp_mapping)(uint16_t internal_port, uint16_t external_port, - int is_verbose, void *backend_state); -} tor_fw_backend_t; -#endif -