[tor-commits] [tor/master] Commit second draft of Jake's SOCKS5-over-AF_UNIX patch. See ticket #12585.
nickm at torproject.org
nickm at torproject.org
Tue Jan 13 18:11:44 UTC 2015
commit 8d59ddf3cba541c6578dff121e8f0623a7606bab
Author: Jacob Appelbaum <jacob at appelbaum.net>
Date: Mon Aug 11 12:27:04 2014 -0700
Commit second draft of Jake's SOCKS5-over-AF_UNIX patch. See ticket #12585.
Signed-off-by: Andrea Shepard <andrea at torproject.org>
---
changes/bug12585 | 9 ++
doc/tor.1.txt | 9 ++
src/common/address.c | 18 ++++
src/or/config.c | 24 +++++
src/or/connection.c | 246 ++++++++++++++++++++++++++++++++++++----------
src/or/connection_edge.c | 6 +-
src/or/main.c | 4 +
src/or/or.h | 8 ++
src/or/relay.c | 5 +-
9 files changed, 275 insertions(+), 54 deletions(-)
diff --git a/changes/bug12585 b/changes/bug12585
new file mode 100644
index 0000000..ccdcd17
--- /dev/null
+++ b/changes/bug12585
@@ -0,0 +1,9 @@
+ o Major features (security)
+ - Implementation of SocksSocket option - SocksSocket implements a SOCKS
+ proxy reachable by Unix Domain Socket. This allows client applications to
+ communicate with Tor without having the ability to create AF_INET or
+ AF_INET6 family sockets. If an application has permission to create a socket
+ with AF_UNIX, it may directly communicate with Tor as if it were an other
+ SOCKS proxy. This should allow high risk applications to be entirely prevented
+ from connecting directly with TCP/IP, they will be able to only connect to the
+ internet through AF_UNIX and only through Tor.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 9e86a67..43aade9 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -483,6 +483,15 @@ GENERAL OPTIONS
in accordance to RFC 1929. Both username and password must be between 1 and
255 characters.
+[[SocksSocket]] **SocksSocket** __Path__::
+ Like SocksPort, but listens on a Unix domain socket, rather than a TCP
+ socket. (Unix and Unix-like systems only.)
+
+[[SocksSocketsGroupWritable]] **SocksSocketsGroupWritable** **0**|**1**::
+ If this option is set to 0, don't allow the filesystem group to read and
+ write unix sockets (e.g. SocksSocket). If the option is set to 1, make
+ the SocksSocket socket readable and writable by the default GID. (Default: 0)
+
[[KeepalivePeriod]] **KeepalivePeriod** __NUM__::
To keep firewalls from expiring connections, send a padding keepalive cell
every NUM seconds on open connections that are in use. If the connection
diff --git a/src/common/address.c b/src/common/address.c
index a809260..1c3777f 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -121,6 +121,15 @@ tor_addr_to_sockaddr(const tor_addr_t *a,
}
}
+/** Set address <b>a</b> to zero. This address belongs to
+ * the AF_UNIX family. */
+static void
+tor_addr_make_af_unix(tor_addr_t *a)
+{
+ memset(a, 0, sizeof(*a));
+ a->family = AF_UNIX;
+}
+
/** Set the tor_addr_t in <b>a</b> to contain the socket address contained in
* <b>sa</b>. */
int
@@ -142,6 +151,9 @@ tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
tor_addr_from_in6(a, &sin6->sin6_addr);
if (port_out)
*port_out = ntohs(sin6->sin6_port);
+ } else if (sa->sa_family == AF_UNIX) {
+ tor_addr_make_af_unix(a);
+ return 0;
} else {
tor_addr_make_unspec(a);
return -1;
@@ -421,6 +433,10 @@ tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
ptr = dest;
}
break;
+ case AF_UNIX:
+ tor_snprintf(dest, len, "AF_UNIX");
+ ptr = dest;
+ break;
default:
return NULL;
}
@@ -816,6 +832,8 @@ tor_addr_is_null(const tor_addr_t *addr)
}
case AF_INET:
return (tor_addr_to_ipv4n(addr) == 0);
+ case AF_UNIX:
+ return 1;
case AF_UNSPEC:
return 1;
default:
diff --git a/src/or/config.c b/src/or/config.c
index 2fa077e..e080e77 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -190,6 +190,8 @@ static config_var_t option_vars_[] = {
V(ControlPortWriteToFile, FILENAME, NULL),
V(ControlSocket, LINELIST, NULL),
V(ControlSocketsGroupWritable, BOOL, "0"),
+ V(SocksSocket, LINELIST, NULL),
+ V(SocksSocketsGroupWritable, BOOL, "0"),
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
V(CookieAuthFile, STRING, NULL),
@@ -1030,6 +1032,20 @@ options_act_reversible(const or_options_t *old_options, char **msg)
}
#endif
+#ifndef HAVE_SYS_UN_H
+ if (options->SocksSocket || options->SocksSocketsGroupWritable) {
+ *msg = tor_strdup("Unix domain sockets (SocksSocket) not supported "
+ "on this OS/with this build.");
+ goto rollback;
+ }
+#else
+ if (options->SocksSocketsGroupWritable && !options->SocksSocket) {
+ *msg = tor_strdup("Setting SocksSocketGroupWritable without setting"
+ "a SocksSocket makes no sense.");
+ goto rollback;
+ }
+#endif
+
if (running_tor) {
int n_ports=0;
/* We need to set the connection limit before we can open the listeners. */
@@ -6120,6 +6136,12 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid ControlSocket configuration");
goto err;
}
+ if (parse_unix_socket_config(ports,
+ options->SocksSocket,
+ CONN_TYPE_AP_LISTENER) < 0) {
+ *msg = tor_strdup("Invalid SocksSocket configuration");
+ goto err;
+ }
}
if (! options->ClientOnly) {
if (parse_port_config(ports,
@@ -6163,6 +6185,8 @@ parse_ports(or_options_t *options, int validate_only,
!! count_real_listeners(ports, CONN_TYPE_OR_LISTENER);
options->SocksPort_set =
!! count_real_listeners(ports, CONN_TYPE_AP_LISTENER);
+ options->SocksSocket_set =
+ !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER);
options->TransPort_set =
!! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER);
options->NATDPort_set =
diff --git a/src/or/connection.c b/src/or/connection.c
index c67cc3c..ad7e6de 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -308,6 +308,8 @@ entry_connection_new(int type, int socket_family)
entry_conn->ipv4_traffic_ok = 1;
else if (socket_family == AF_INET6)
entry_conn->ipv6_traffic_ok = 1;
+ else if (socket_family == AF_UNIX)
+ entry_conn->is_socks_socket = 1;
return entry_conn;
}
@@ -516,9 +518,10 @@ connection_free_(connection_t *conn)
buf_free(conn->outbuf);
} else {
if (conn->socket_family == AF_UNIX) {
- /* For now only control ports can be Unix domain sockets
+ /* For now only control and SOCKS ports can be Unix domain sockets
* and listeners at the same time */
- tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
+ tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER ||
+ conn->type == CONN_TYPE_AP_LISTENER);
if (unlink(conn->address) < 0 && errno != ENOENT) {
log_warn(LD_NET, "Could not unlink %s: %s", conn->address,
@@ -954,6 +957,47 @@ check_location_for_unix_socket(const or_options_t *options, const char *path)
}
#endif
+#ifdef HAVE_SYS_UN_H
+/** Check whether we should be willing to open an AF_UNIX socket in
+ * <b>path</b>. Return 0 if we should go ahead and -1 if we shouldn't. */
+static int
+check_location_for_socks_unix_socket(const or_options_t *options,
+ const char *path)
+{
+ int r = -1;
+ char *p = tor_strdup(path);
+ cpd_check_t flags = CPD_CHECK_MODE_ONLY;
+ if (get_parent_directory(p)<0 || p[0] != '/') {
+ log_warn(LD_GENERAL, "Bad unix socket address '%s'. Tor does not support "
+ "relative paths for unix sockets.", path);
+ goto done;
+ }
+
+ if (options->SocksSocketsGroupWritable)
+ flags |= CPD_GROUP_OK;
+
+ if (check_private_dir(p, flags, options->User) < 0) {
+ char *escpath, *escdir;
+ escpath = esc_for_log(path);
+ escdir = esc_for_log(p);
+ log_warn(LD_GENERAL, "Before Tor can create a SocksSocket in %s, the "
+ "directory %s needs to exist, and to be accessible only by the "
+ "user%s account that is running Tor. (On some Unix systems, "
+ "anybody who can list a socket can connect to it, so Tor is "
+ "being careful.)", escpath, escdir,
+ options->SocksSocketsGroupWritable ? " and group" : "");
+ tor_free(escpath);
+ tor_free(escdir);
+ goto done;
+ }
+
+ r = 0;
+ done:
+ tor_free(p);
+ return r;
+}
+#endif
+
/** Tell the TCP stack that it shouldn't wait for a long time after
* <b>sock</b> has closed before reusing its port. Return 0 on success,
* -1 on failure. */
@@ -1029,30 +1073,103 @@ connection_listener_new(const struct sockaddr *listensockaddr,
}
if (listensockaddr->sa_family == AF_INET ||
- listensockaddr->sa_family == AF_INET6) {
+ listensockaddr->sa_family == AF_INET6 ||
+ (listensockaddr->sa_family == AF_UNIX &&
+ type != CONN_TYPE_CONTROL_LISTENER)) {
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
if (is_tcp)
start_reading = 1;
- tor_addr_from_sockaddr(&addr, listensockaddr, &usePort);
+ if ( listensockaddr->sa_family == AF_INET ||
+ listensockaddr->sa_family == AF_INET6) {
- log_notice(LD_NET, "Opening %s on %s",
- conn_type_to_string(type), fmt_addrport(&addr, usePort));
-
- s = tor_open_socket_nonblocking(tor_addr_family(&addr),
- is_tcp ? SOCK_STREAM : SOCK_DGRAM,
- is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
- if (!SOCKET_OK(s)) {
- log_warn(LD_NET,"Socket creation failed: %s",
- tor_socket_strerror(tor_socket_errno(-1)));
- goto err;
+ tor_addr_from_sockaddr(&addr, listensockaddr, &usePort);
+
+ log_notice(LD_NET, "Opening %s on %s",
+ conn_type_to_string(type), fmt_addrport(&addr, usePort));
+
+ s = tor_open_socket_nonblocking(tor_addr_family(&addr),
+ is_tcp ? SOCK_STREAM : SOCK_DGRAM,
+ is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
+ if (!SOCKET_OK(s)) {
+ log_warn(LD_NET, "Socket creation failed: %s",
+ tor_socket_strerror(tor_socket_errno(-1)));
+ goto err;
+ }
+
+ if (make_socket_reuseable(s) < 0) {
+ log_warn(LD_NET, "Error setting SO_REUSEADDR flag on %s: %s",
+ conn_type_to_string(type),
+ tor_socket_strerror(errno));
+ }
}
- if (make_socket_reuseable(s) < 0) {
- log_warn(LD_NET, "Error setting SO_REUSEADDR flag on %s: %s",
- conn_type_to_string(type),
- tor_socket_strerror(errno));
+#ifdef HAVE_SYS_UN_H
+ if (listensockaddr->sa_family == AF_UNIX &&
+ type != CONN_TYPE_CONTROL_LISTENER) {
+ tor_assert(listensockaddr->sa_family == AF_UNIX);
+
+ if (check_location_for_socks_unix_socket(options, address) < 0)
+ goto err;
+
+ log_notice(LD_NET, "Opening SocksSocket %s on %s",
+ conn_type_to_string(type), address);
+
+ tor_addr_make_unspec(&addr);
+
+ if (unlink(address) < 0 && errno != ENOENT) {
+ log_warn(LD_NET, "Could not unlink %s: %s", address,
+ strerror(errno));
+ goto err;
+ }
+
+ s = tor_open_socket_nonblocking(AF_UNIX, SOCK_STREAM, 0);
+ if (! SOCKET_OK(s)) {
+ log_warn(LD_NET, "SocksSocket socket creation failed: %s.",
+ strerror(errno));
+ goto err;
+ }
+
+ if (bind(s, listensockaddr,
+ (socklen_t)sizeof(struct sockaddr_un)) == -1) {
+ log_warn(LD_NET, "Bind to %s failed: %s.", address,
+ tor_socket_strerror(tor_socket_errno(s)));
+ goto err;
+ }
+#ifdef HAVE_PWD_H
+ if (options->User) {
+ pw = getpwnam(options->User);
+ if (pw == NULL) {
+ log_warn(LD_NET,
+ "Unable to chown() %s socket: user %s not found.",
+ address, options->User);
+ goto err;
+ } else if (chown(address, pw->pw_uid, pw->pw_gid) < 0) {
+ log_warn(LD_NET, "Unable to chown() %s socket: %s.",
+ address, strerror(errno));
+ goto err;
+ }
+ }
+#endif
+
+ if (options->SocksSocketsGroupWritable) {
+ /* We need to use chmod; fchmod doesn't work on sockets on all
+ * platforms. */
+ if (chmod(address, 0660) < 0) {
+ log_warn(LD_FS, "Unable to make %s group-writable.", address);
+ goto err;
+ }
+ }
+
+ if (listen(s, SOMAXCONN) < 0) {
+ log_warn(LD_NET, "Could not listen on %s: %s", address,
+ tor_socket_strerror(tor_socket_errno(s)));
+ goto err;
+ }
}
+#else
+ (void)options;
+#endif /* HAVE_SYS_UN_H */
#if defined USE_TRANSPARENT && defined(IP_TRANSPARENT)
if (options->TransProxyType_parsed == TPT_TPROXY &&
@@ -1090,48 +1207,53 @@ connection_listener_new(const struct sockaddr *listensockaddr,
}
#endif
- if (bind(s,listensockaddr,socklen) < 0) {
- const char *helpfulhint = "";
- int e = tor_socket_errno(s);
- if (ERRNO_IS_EADDRINUSE(e))
- helpfulhint = ". Is Tor already running?";
- log_warn(LD_NET, "Could not bind to %s:%u: %s%s", address, usePort,
- tor_socket_strerror(e), helpfulhint);
- goto err;
- }
-
- if (is_tcp) {
- if (tor_listen(s) < 0) {
- log_warn(LD_NET, "Could not listen on %s:%u: %s", address, usePort,
- tor_socket_strerror(tor_socket_errno(s)));
+ if (listensockaddr->sa_family != AF_UNIX) {
+ if (bind(s,listensockaddr,socklen) < 0) {
+ const char *helpfulhint = "";
+ int e = tor_socket_errno(s);
+ if (ERRNO_IS_EADDRINUSE(e))
+ helpfulhint = ". Is Tor already running?";
+ log_warn(LD_NET, "Could not bind to %s:%u: %s%s", address, usePort,
+ tor_socket_strerror(e), helpfulhint);
goto err;
}
- }
- if (usePort != 0) {
- gotPort = usePort;
- } else {
- tor_addr_t addr2;
- struct sockaddr_storage ss;
- socklen_t ss_len=sizeof(ss);
- if (getsockname(s, (struct sockaddr*)&ss, &ss_len)<0) {
- log_warn(LD_NET, "getsockname() couldn't learn address for %s: %s",
- conn_type_to_string(type),
- tor_socket_strerror(tor_socket_errno(s)));
- gotPort = 0;
+ if (is_tcp) {
+ if (tor_listen(s) < 0) {
+ log_warn(LD_NET, "Could not listen on %s:%u: %s", address, usePort,
+ tor_socket_strerror(tor_socket_errno(s)));
+ goto err;
+ }
+ }
+
+ if (usePort != 0) {
+ gotPort = usePort;
+ } else {
+ tor_addr_t addr2;
+ struct sockaddr_storage ss;
+ socklen_t ss_len=sizeof(ss);
+ if (getsockname(s, (struct sockaddr*)&ss, &ss_len)<0) {
+ log_warn(LD_NET, "getsockname() couldn't learn address for %s: %s",
+ conn_type_to_string(type),
+ tor_socket_strerror(tor_socket_errno(s)));
+ gotPort = 0;
+ }
+ tor_addr_from_sockaddr(&addr2, (struct sockaddr*)&ss, &gotPort);
}
- tor_addr_from_sockaddr(&addr2, (struct sockaddr*)&ss, &gotPort);
}
#ifdef HAVE_SYS_UN_H
- } else if (listensockaddr->sa_family == AF_UNIX) {
+ } else if (listensockaddr->sa_family == AF_UNIX &&
+ type != CONN_TYPE_AP_LISTENER) {
start_reading = 1;
/* For now only control ports can be Unix domain sockets
* and listeners at the same time */
tor_assert(type == CONN_TYPE_CONTROL_LISTENER);
- if (check_location_for_unix_socket(options, address) < 0)
- goto err;
+ if ( type == CONN_TYPE_CONTROL_LISTENER ) {
+ if (check_location_for_unix_socket(options, address) < 0)
+ goto err;
+ }
log_notice(LD_NET, "Opening %s on %s",
conn_type_to_string(type), address);
@@ -1177,6 +1299,15 @@ connection_listener_new(const struct sockaddr *listensockaddr,
}
}
+ if (options->SocksSocketsGroupWritable) {
+ /* We need to use chmod; fchmod doesn't work on sockets on all
+ * platforms. */
+ if (chmod(address, 0660) < 0) {
+ log_warn(LD_FS,"Unable to make %s group-writable.", address);
+ goto err;
+ }
+ }
+
if (listen(s, SOMAXCONN) < 0) {
log_warn(LD_NET, "Could not listen on %s: %s", address,
tor_socket_strerror(tor_socket_errno(s)));
@@ -1294,6 +1425,8 @@ check_sockaddr(const struct sockaddr *sa, int len, int level)
"Address for new connection has address/port equal to zero.");
ok = 0;
}
+ } else if (sa->sa_family == AF_UNIX) {
+ ok = 1;
} else {
ok = 0;
}
@@ -1378,7 +1511,8 @@ connection_handle_listener_read(connection_t *conn, int new_type)
return 0;
}
- if (conn->socket_family == AF_INET || conn->socket_family == AF_INET6) {
+ if (conn->socket_family == AF_INET || conn->socket_family == AF_INET6 ||
+ (conn->socket_family == AF_UNIX && new_type == CONN_TYPE_AP)) {
tor_addr_t addr;
uint16_t port;
if (check_sockaddr(remote, remotelen, LOG_INFO)<0) {
@@ -1419,7 +1553,16 @@ connection_handle_listener_read(connection_t *conn, int new_type)
newconn->port = port;
newconn->address = tor_dup_addr(&addr);
- if (new_type == CONN_TYPE_AP) {
+ if (new_type == CONN_TYPE_AP && conn->socket_family != AF_UNIX) {
+ log_notice(LD_NET, "New SOCKS connection opened from %s.",
+ fmt_and_decorate_addr(&addr));
+ TO_ENTRY_CONN(newconn)->socks_request->socks_prefer_no_auth =
+ TO_LISTENER_CONN(conn)->socks_prefer_no_auth;
+ }
+ if (new_type == CONN_TYPE_AP && conn->socket_family == AF_UNIX) {
+ newconn->port = 0;
+ newconn->address = tor_strdup(conn->address);
+ log_notice(LD_NET, "New SOCKS SocksSocket connection opened");
TO_ENTRY_CONN(newconn)->socks_request->socks_prefer_no_auth =
TO_LISTENER_CONN(conn)->socks_prefer_no_auth;
}
@@ -1428,7 +1571,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
fmt_and_decorate_addr(&addr));
}
- } else if (conn->socket_family == AF_UNIX) {
+ } else if (conn->socket_family == AF_UNIX && conn->type != CONN_TYPE_AP) {
/* For now only control ports can be Unix domain sockets
* and listeners at the same time */
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
@@ -2392,6 +2535,7 @@ connection_is_rate_limited(connection_t *conn)
return 0; /* Internal connection */
else if (! options->CountPrivateBandwidth &&
(tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */
+ tor_addr_family(&conn->addr) == AF_UNIX || /* no address */
tor_addr_is_internal(&conn->addr, 0)))
return 0; /* Internal address */
else
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index d8f397b..390ad07 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1233,7 +1233,8 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
{
tor_addr_t addr;
/* XXX Duplicate call to tor_addr_parse. */
- if (tor_addr_parse(&addr, socks->address) >= 0) {
+ if (tor_addr_parse(&addr, socks->address) >= 0 &&
+ !conn->is_socks_socket) {
sa_family_t family = tor_addr_family(&addr);
if ((family == AF_INET && ! conn->ipv4_traffic_ok) ||
(family == AF_INET6 && ! conn->ipv4_traffic_ok)) {
@@ -1836,6 +1837,9 @@ connection_ap_get_begincell_flags(entry_connection_t *ap_conn)
if (!ap_conn->ipv4_traffic_ok)
flags |= BEGIN_FLAG_IPV4_NOT_OK;
+ if (ap_conn->is_socks_socket)
+ return 0;
+
exitnode = node_get_by_id(cpath_layer->extend_info->identity_digest);
if (ap_conn->ipv6_traffic_ok && exitnode) {
diff --git a/src/or/main.c b/src/or/main.c
index c925b7d..0c49b40 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -385,6 +385,10 @@ connection_remove(connection_t *conn)
(int)conn->s, conn_type_to_string(conn->type),
smartlist_len(connection_array));
+ if (conn->type == CONN_TYPE_AP && conn->socket_family == AF_UNIX) {
+ log_notice(LD_NET, "Closing SOCKS SocksSocket connection");
+ }
+
control_event_conn_bandwidth(conn);
tor_assert(conn->conn_array_index >= 0);
diff --git a/src/or/or.h b/src/or/or.h
index 58e2164..5bb5f5b 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1702,6 +1702,9 @@ typedef struct entry_connection_t {
* do we prefer IPv6? */
unsigned int prefer_ipv6_virtaddr : 1;
+ /** Are we a socks SocksSocket listener? */
+ unsigned int is_socks_socket:1;
+
} entry_connection_t;
typedef enum {
@@ -3528,6 +3531,10 @@ typedef struct {
* for control connections. */
int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
+ config_line_t *SocksSocket; /**< List of Unix Domain Sockets to listen on
+ * for SOCKS connections. */
+
+ int SocksSocketsGroupWritable; /**< Boolean: Are SOCKS sockets g+rw? */
/** Ports to listen on for directory connections. */
config_line_t *DirPort_lines;
config_line_t *DNSPort_lines; /**< Ports to listen on for DNS requests. */
@@ -3550,6 +3557,7 @@ typedef struct {
*/
unsigned int ORPort_set : 1;
unsigned int SocksPort_set : 1;
+ unsigned int SocksSocket_set : 1;
unsigned int TransPort_set : 1;
unsigned int NATDPort_set : 1;
unsigned int ControlPort_set : 1;
diff --git a/src/or/relay.c b/src/or/relay.c
index 2d11096..b7ab808 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1327,8 +1327,9 @@ connection_edge_process_relay_cell_not_open(
return 0;
}
- if ((family == AF_INET && ! entry_conn->ipv4_traffic_ok) ||
- (family == AF_INET6 && ! entry_conn->ipv6_traffic_ok)) {
+ if (((family == AF_INET && ! entry_conn->ipv4_traffic_ok) ||
+ (family == AF_INET6 && ! entry_conn->ipv6_traffic_ok)) &&
+ (!entry_conn->is_socks_socket)) {
log_fn(LOG_PROTOCOL_WARN, LD_APP,
"Got a connected cell to %s with unsupported address family."
" Closing.", fmt_addr(&addr));
More information about the tor-commits
mailing list