[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