Forráskód Böngészése

Merge branch 'bug14451_026_v1'

Nick Mathewson 9 éve
szülő
commit
a87ea9b1c6
9 módosított fájl, 123 hozzáadás és 67 törlés
  1. 5 2
      changes/bug12585
  2. 7 0
      changes/bug14451
  3. 2 6
      doc/tor.1.txt
  4. 78 30
      src/or/config.c
  5. 1 0
      src/or/config.h
  6. 20 9
      src/or/connection.c
  7. 1 0
      src/or/connection.h
  8. 0 4
      src/or/or.h
  9. 9 16
      src/or/rendservice.c

+ 5 - 2
changes/bug12585

@@ -1,9 +1,12 @@
   o Major features (security)
-    - Implementation of SocksSocket option - SocksSocket implements a SOCKS
+    - Implementation of an AF_UNIX socket  option to implement 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.  Closes ticket 12585.
+      internet through AF_UNIX and only through Tor.
+      To create a socket of this type, use the syntax "unix:/path/to/socket".
+      Closes ticket 12585.
+

+ 7 - 0
changes/bug14451

@@ -0,0 +1,7 @@
+
+
+  o Minor features:
+    - ControlPort now supports the unix:/path/to/dir syntax as an alternative
+      to the ControlSocket option, for consistency with SocksPort and
+      hidden services.  Closes ticket 14451.
+

+ 2 - 6
doc/tor.1.txt

@@ -273,7 +273,7 @@ GENERAL OPTIONS
     all sockets will be set to this limit. Must be a value between 2048 and
     262144, in 1024 byte increments. Default of 8192 is recommended.
 
-[[ControlPort]] **ControlPort** __PORT__|**auto**::
+[[ControlPort]] **ControlPort** __PORT__|**unix:**__path__|**auto**::
     If set, Tor will accept connections on this port and allow those
     connections to control the Tor process using the Tor Control Protocol
     (described in control-spec.txt). Note: unless you also specify one or
@@ -483,10 +483,6 @@ GENERAL OPTIONS
     in accordance to RFC 1929. Both username and password must be between 1 and
     255 characters.
 
-[[SocksSocket]] **SocksSocket** __Path__ [_flags_] [_isolation flags_]::
-    Like SocksPort, but listens on a Unix domain socket, rather than a TCP
-    socket.  '0' disables SocksSocket (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
@@ -957,7 +953,7 @@ The following options are useful only for clients (that is, if
     the same circuit. Currently, two addresses are "too close" if they lie in
     the same /16 range. (Default: 1)
 
-[[SOCKSPort]] **SOCKSPort** \['address':]__port__|**auto** [_flags_] [_isolation flags_]::
+[[SOCKSPort]] **SOCKSPort** \['address':]__port__|**unix:**__path__|**auto** [_flags_] [_isolation flags_]::
     Open this port to listen for connections from SOCKS-speaking
     applications. Set this to 0 if you don't want to allow application
     connections via SOCKS. Set it to "auto" to have Tor pick a port for

+ 78 - 30
src/or/config.c

@@ -68,6 +68,9 @@
 /* From main.c */
 extern int quiet_level;
 
+/* Prefix used to indicate a Unix socket in a FooPort configuration. */
+static const char unix_socket_prefix[] = "unix:";
+
 /** A list of abbreviations and aliases to map command-line options, obsolete
  * option names, or alternative option names, to their current values. */
 static config_abbrev_t option_abbrevs_[] = {
@@ -200,7 +203,6 @@ 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"),
@@ -1050,20 +1052,6 @@ 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. */
@@ -5620,6 +5608,55 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid)
 #define CL_PORT_TAKES_HOSTNAMES (1u<<5)
 #define CL_PORT_IS_UNIXSOCKET (1u<<6)
 
+#ifdef HAVE_SYS_UN_H
+
+/** Parse the given <b>addrport</b> and set <b>path_out</b> if a Unix socket
+ * path is found. Return 0 on success. On error, a negative value is
+ * returned, -ENOENT if no Unix statement found, -EINVAL if the socket path
+ * is empty and -ENOSYS if AF_UNIX is not supported (see function in the
+ * #else statement below). */
+
+int
+config_parse_unix_port(const char *addrport, char **path_out)
+{
+  tor_assert(path_out);
+  tor_assert(addrport);
+
+  if (strcmpstart(addrport, unix_socket_prefix)) {
+    /* Not a Unix socket path. */
+    return -ENOENT;
+  }
+
+  if (strlen(addrport + strlen(unix_socket_prefix)) == 0) {
+    /* Empty socket path, not very usable. */
+    return -EINVAL;
+  }
+
+  *path_out = tor_strdup(addrport + strlen(unix_socket_prefix));
+  return 0;
+}
+
+#else /* defined(HAVE_SYS_UN_H) */
+
+int
+config_parse_unix_port(const char *addrport, char **path_out)
+{
+  tor_assert(path_out);
+  tor_assert(addrport);
+
+  if (strcmpstart(addrport, unix_socket_prefix)) {
+    /* Not a Unix socket path. */
+    return -ENOENT;
+  }
+
+  log_warn(LD_CONFIG,
+           "Port configuration %s is for an AF_UNIX socket, but we have no"
+           "support available on this platform",
+           escaped(addrport));
+  return -ENOSYS;
+}
+#endif /* defined(HAVE_SYS_UN_H) */
+
 /**
  * Parse port configuration for a single port type.
  *
@@ -5681,6 +5718,7 @@ parse_port_config(smartlist_t *out,
   const unsigned takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES;
   const unsigned is_unix_socket = flags & CL_PORT_IS_UNIXSOCKET;
   int got_zero_port=0, got_nonzero_port=0;
+  char *unix_socket_path = NULL;
 
   /* FooListenAddress is deprecated; let's make it work like it used to work,
    * though. */
@@ -5785,7 +5823,7 @@ parse_port_config(smartlist_t *out,
 
   for (; ports; ports = ports->next) {
     tor_addr_t addr;
-    int port;
+    int port, ret;
     int sessiongroup = SESSION_GROUP_UNSET;
     unsigned isolation = ISO_DEFAULT;
     int prefer_no_auth = 0;
@@ -5814,8 +5852,26 @@ parse_port_config(smartlist_t *out,
 
     /* Now parse the addr/port value */
     addrport = smartlist_get(elts, 0);
-    if (is_unix_socket) {
-      /* leave it as it is. */
+
+    /* Let's start to check if it's a Unix socket path. */
+    ret = config_parse_unix_port(addrport, &unix_socket_path);
+    if (ret < 0 && ret != -ENOENT) {
+      if (ret == -EINVAL) {
+        log_warn(LD_CONFIG, "Empty Unix socket path.");
+      }
+      goto err;
+    }
+
+    if (unix_socket_path &&
+        ! conn_listener_type_supports_af_unix(listener_type)) {
+      log_warn(LD_CONFIG, "%sPort does not support unix sockets", portname);
+      goto err;
+    }
+
+    if (unix_socket_path) {
+      port = 1;
+    } else if (is_unix_socket) {
+      unix_socket_path = tor_strdup(addrport);
       if (!strcmp(addrport, "0"))
         port = 0;
       else
@@ -6005,12 +6061,13 @@ parse_port_config(smartlist_t *out,
     }
 
     if (out && port) {
-      size_t namelen = is_unix_socket ? strlen(addrport) : 0;
+      size_t namelen = unix_socket_path ? strlen(unix_socket_path) : 0;
       port_cfg_t *cfg = port_cfg_new(namelen);
-      if (is_unix_socket) {
+      if (unix_socket_path) {
         tor_addr_make_unspec(&cfg->addr);
-        memcpy(cfg->unix_addr, addrport, strlen(addrport) + 1);
+        memcpy(cfg->unix_addr, unix_socket_path, namelen + 1);
         cfg->is_unix_addr = 1;
+        tor_free(unix_socket_path);
       } else {
         tor_addr_copy(&cfg->addr, &addr);
         cfg->port = port;
@@ -6160,13 +6217,6 @@ parse_ports(or_options_t *options, int validate_only,
       *msg = tor_strdup("Invalid ControlSocket configuration");
       goto err;
     }
-    if (parse_port_config(ports, options->SocksSocket, NULL,
-                          "SocksSocket",
-                          CONN_TYPE_AP_LISTENER, NULL, 0,
-                          CL_PORT_IS_UNIXSOCKET) < 0) {
-      *msg = tor_strdup("Invalid SocksSocket configuration");
-      goto err;
-    }
   }
   if (! options->ClientOnly) {
     if (parse_port_config(ports,
@@ -6210,8 +6260,6 @@ 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 =

+ 1 - 0
src/or/config.h

@@ -113,6 +113,7 @@ int addressmap_register_auto(const char *from, const char *to,
                              time_t expires,
                              addressmap_entry_source_t addrmap_source,
                              const char **msg);
+int config_parse_unix_port(const char *addrport, char **path_out);
 
 /** Represents the information stored in a torrc Bridge line. */
 typedef struct bridge_line_t {

+ 20 - 9
src/or/connection.c

@@ -449,6 +449,22 @@ connection_link_connections(connection_t *conn_a, connection_t *conn_b)
   conn_b->linked_conn = conn_a;
 }
 
+/** Return true iff the provided connection listener type supports AF_UNIX
+ * sockets. */
+int
+conn_listener_type_supports_af_unix(int type)
+{
+  /* For now only control ports or SOCKS ports can be Unix domain sockets
+   * and listeners at the same time */
+  switch (type) {
+    case CONN_TYPE_CONTROL_LISTENER:
+    case CONN_TYPE_AP_LISTENER:
+      return 1;
+    default:
+      return 0;
+  }
+}
+
 /** Deallocate memory used by <b>conn</b>. Deallocate its buffers if
  * necessary, close its socket if necessary, and mark the directory as dirty
  * if <b>conn</b> is an OR or OP connection.
@@ -516,8 +532,7 @@ connection_free_(connection_t *conn)
     if (conn->socket_family == AF_UNIX) {
       /* 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 ||
-                 conn->type == CONN_TYPE_AP_LISTENER);
+      tor_assert(conn_listener_type_supports_af_unix(conn->type));
 
       if (unlink(conn->address) < 0 && errno != ENOENT) {
         log_warn(LD_NET, "Could not unlink %s: %s", conn->address,
@@ -1172,17 +1187,13 @@ connection_listener_new(const struct sockaddr *listensockaddr,
     }
 #ifdef HAVE_SYS_UN_H
   /*
-   * AF_UNIX generic setup stuff (this covers both CONN_TYPE_CONTROL_LISTENER
-   * and CONN_TYPE_AP_LISTENER cases)
+   * AF_UNIX generic setup stuff
    */
   } else if (listensockaddr->sa_family == AF_UNIX) {
     /* We want to start reading for both AF_UNIX cases */
     start_reading = 1;
 
-    /* For now only control ports or SOCKS ports can be Unix domain sockets
-     * and listeners at the same time */
-    tor_assert(type == CONN_TYPE_CONTROL_LISTENER ||
-               type == CONN_TYPE_AP_LISTENER);
+    tor_assert(conn_listener_type_supports_af_unix(type));
 
     if (check_location_for_unix_socket(options, address,
           (type == CONN_TYPE_CONTROL_LISTENER) ?
@@ -1496,7 +1507,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
     if (new_type == CONN_TYPE_AP && conn->socket_family == AF_UNIX) {
       newconn->port = 0;
       newconn->address = tor_strdup(conn->address);
-      log_info(LD_NET, "New SOCKS SocksSocket connection opened");
+      log_info(LD_NET, "New SOCKS AF_UNIX connection opened");
     }
     if (new_type == CONN_TYPE_CONTROL) {
       log_notice(LD_CONTROL, "New control connection opened from %s.",

+ 1 - 0
src/or/connection.h

@@ -17,6 +17,7 @@
 
 const char *conn_type_to_string(int type);
 const char *conn_state_to_string(int type, int state);
+int conn_listener_type_supports_af_unix(int type);
 
 dir_connection_t *dir_connection_new(int socket_family);
 or_connection_t *or_connection_new(int type, int socket_family);

+ 0 - 4
src/or/or.h

@@ -3463,9 +3463,6 @@ 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;
@@ -3489,7 +3486,6 @@ 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;

+ 9 - 16
src/or/rendservice.c

@@ -341,7 +341,6 @@ parse_port_config(const char *string)
   tor_addr_t addr;
   const char *addrport;
   rend_service_port_config_t *result = NULL;
-  const char *socket_prefix = "socket:";
   unsigned int is_unix_addr = 0;
   char *socket_path = NULL;
 
@@ -365,25 +364,19 @@ parse_port_config(const char *string)
     realport = virtport;
     tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
   } else {
+    int ret;
+
     addrport = smartlist_get(sl,1);
-    /* If it starts with socket:, try to parse it as a socket path */
-    if (!strcmpstart(addrport, socket_prefix)) {
-      if (strlen(addrport + strlen(socket_prefix)) > 0) {
-#ifdef HAVE_SYS_UN_H
-        is_unix_addr = 1;
-        socket_path = tor_strdup(addrport + strlen(socket_prefix));
-#else
-        log_warn(LD_CONFIG,
-                 "Hidden service port configuration %s is for an AF_UNIX "
-                 "socket, but we have no support available on this platform",
-                 escaped(addrport));
-        goto err;
-#endif /* defined(HAVE_SYS_UN_H) */
-      } else {
+    ret = config_parse_unix_port(addrport, &socket_path);
+    if (ret < 0 && ret != ENOENT) {
+      if (ret == -EINVAL) {
         log_warn(LD_CONFIG,
                  "Empty socket path in hidden service port configuration.");
-        goto err;
       }
+      goto err;
+    }
+    if (socket_path) {
+      is_unix_addr = 1;
     } else if (strchr(addrport, ':') || strchr(addrport, '.')) {
       /* else try it as an IP:port pair if it has a : or . in it */
       if (tor_addr_port_lookup(addrport, &addr, &p)<0) {