From 8e103cb2d0d2710066e97d62a408c6ce7de49422 Mon Sep 17 00:00:00 2001 From: "teor (Tim Wilson-Brown)" Date: Fri, 26 Feb 2016 10:53:57 +0100 Subject: [PATCH] Set EXCLUSIVEADDRUSE on Win32 to avoid a local port-stealing attack --- changes/bug18123 | 4 ++++ src/or/connection.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 changes/bug18123 diff --git a/changes/bug18123 b/changes/bug18123 new file mode 100644 index 0000000000..1359b4ef67 --- /dev/null +++ b/changes/bug18123 @@ -0,0 +1,4 @@ + o Minor bugfixes (security, win32): + - Set SO_EXCLUSIVEADDRUSE on Win32 to avoid a local port-stealing + attack. + Fixes bug 18123; bugfix on all tor versions. Patch by "teor". diff --git a/src/or/connection.c b/src/or/connection.c index 0f2b3e356e..c8fc662129 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1061,6 +1061,31 @@ make_socket_reuseable(tor_socket_t sock) #endif } +#ifdef _WIN32 +/** Tell the Windows TCP stack to prevent other applications from receiving + * traffic from tor's open ports. Return 0 on success, -1 on failure. */ +static int +make_win32_socket_exclusive(tor_socket_t sock) +{ +#ifdef SO_EXCLUSIVEADDRUSE + int one=1; + + /* Any socket that sets REUSEADDR on win32 can bind to a port _even when + * somebody else already has it bound_, and _even if the original socket + * didn't set REUSEADDR_. Use EXCLUSIVEADDRUSE to prevent this port-stealing + * on win32. */ + if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void*) &one, + (socklen_t)sizeof(one))) { + return -1; + } + return 0; +#else + (void) sock; + return 0; +#endif +} +#endif + /** Max backlog to pass to listen. We start at */ static int listen_limit = INT_MAX; @@ -1137,6 +1162,14 @@ connection_listener_new(const struct sockaddr *listensockaddr, tor_socket_strerror(errno)); } +#ifdef _WIN32 + if (make_win32_socket_exclusive(s) < 0) { + log_warn(LD_NET, "Error setting SO_EXCLUSIVEADDRUSE flag on %s: %s", + conn_type_to_string(type), + tor_socket_strerror(errno)); + } +#endif + #if defined(USE_TRANSPARENT) && defined(IP_TRANSPARENT) if (options->TransProxyType_parsed == TPT_TPROXY && type == CONN_TYPE_AP_TRANS_LISTENER) {