Procházet zdrojové kódy

Merge branch 'bug14451_026_v1'

Nick Mathewson před 11 roky
rodič
revize
a87ea9b1c6
9 změnil soubory, kde provedl 123 přidání a 67 odebrání
  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)
   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
       proxy reachable by Unix Domain Socket. This allows client applications to
       communicate with Tor without having the ability to create AF_INET or
       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
       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
       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
       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
       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
     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.
     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
     If set, Tor will accept connections on this port and allow those
     connections to control the Tor process using the Tor Control Protocol
     connections to control the Tor process using the Tor Control Protocol
     (described in control-spec.txt). Note: unless you also specify one or
     (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
     in accordance to RFC 1929. Both username and password must be between 1 and
     255 characters.
     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**::
 [[SocksSocketsGroupWritable]] **SocksSocketsGroupWritable** **0**|**1**::
     If this option is set to 0, don't allow the filesystem group to read and
     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
     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 circuit. Currently, two addresses are "too close" if they lie in
     the same /16 range. (Default: 1)
     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
     Open this port to listen for connections from SOCKS-speaking
     applications. Set this to 0 if you don't want to allow application
     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
     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 */
 /* From main.c */
 extern int quiet_level;
 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
 /** A list of abbreviations and aliases to map command-line options, obsolete
  * option names, or alternative option names, to their current values. */
  * option names, or alternative option names, to their current values. */
 static config_abbrev_t option_abbrevs_[] = {
 static config_abbrev_t option_abbrevs_[] = {
@@ -200,7 +203,6 @@ static config_var_t option_vars_[] = {
   V(ControlPortWriteToFile,      FILENAME, NULL),
   V(ControlPortWriteToFile,      FILENAME, NULL),
   V(ControlSocket,               LINELIST, NULL),
   V(ControlSocket,               LINELIST, NULL),
   V(ControlSocketsGroupWritable, BOOL,     "0"),
   V(ControlSocketsGroupWritable, BOOL,     "0"),
-  V(SocksSocket,                 LINELIST, NULL),
   V(SocksSocketsGroupWritable,   BOOL,     "0"),
   V(SocksSocketsGroupWritable,   BOOL,     "0"),
   V(CookieAuthentication,        BOOL,     "0"),
   V(CookieAuthentication,        BOOL,     "0"),
   V(CookieAuthFileGroupReadable, BOOL,     "0"),
   V(CookieAuthFileGroupReadable, BOOL,     "0"),
@@ -1050,20 +1052,6 @@ options_act_reversible(const or_options_t *old_options, char **msg)
   }
   }
 #endif
 #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) {
   if (running_tor) {
     int n_ports=0;
     int n_ports=0;
     /* We need to set the connection limit before we can open the listeners. */
     /* 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_TAKES_HOSTNAMES (1u<<5)
 #define CL_PORT_IS_UNIXSOCKET (1u<<6)
 #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.
  * 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 takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES;
   const unsigned is_unix_socket = flags & CL_PORT_IS_UNIXSOCKET;
   const unsigned is_unix_socket = flags & CL_PORT_IS_UNIXSOCKET;
   int got_zero_port=0, got_nonzero_port=0;
   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,
   /* FooListenAddress is deprecated; let's make it work like it used to work,
    * though. */
    * though. */
@@ -5785,7 +5823,7 @@ parse_port_config(smartlist_t *out,
 
 
   for (; ports; ports = ports->next) {
   for (; ports; ports = ports->next) {
     tor_addr_t addr;
     tor_addr_t addr;
-    int port;
+    int port, ret;
     int sessiongroup = SESSION_GROUP_UNSET;
     int sessiongroup = SESSION_GROUP_UNSET;
     unsigned isolation = ISO_DEFAULT;
     unsigned isolation = ISO_DEFAULT;
     int prefer_no_auth = 0;
     int prefer_no_auth = 0;
@@ -5814,8 +5852,26 @@ parse_port_config(smartlist_t *out,
 
 
     /* Now parse the addr/port value */
     /* Now parse the addr/port value */
     addrport = smartlist_get(elts, 0);
     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"))
       if (!strcmp(addrport, "0"))
         port = 0;
         port = 0;
       else
       else
@@ -6005,12 +6061,13 @@ parse_port_config(smartlist_t *out,
     }
     }
 
 
     if (out && port) {
     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);
       port_cfg_t *cfg = port_cfg_new(namelen);
-      if (is_unix_socket) {
+      if (unix_socket_path) {
         tor_addr_make_unspec(&cfg->addr);
         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;
         cfg->is_unix_addr = 1;
+        tor_free(unix_socket_path);
       } else {
       } else {
         tor_addr_copy(&cfg->addr, &addr);
         tor_addr_copy(&cfg->addr, &addr);
         cfg->port = port;
         cfg->port = port;
@@ -6160,13 +6217,6 @@ parse_ports(or_options_t *options, int validate_only,
       *msg = tor_strdup("Invalid ControlSocket configuration");
       *msg = tor_strdup("Invalid ControlSocket configuration");
       goto err;
       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 (! options->ClientOnly) {
     if (parse_port_config(ports,
     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);
     !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER);
   options->SocksPort_set =
   options->SocksPort_set =
     !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER);
     !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER);
-  options->SocksSocket_set =
-    !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER);
   options->TransPort_set =
   options->TransPort_set =
     !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER);
     !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER);
   options->NATDPort_set =
   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,
                              time_t expires,
                              addressmap_entry_source_t addrmap_source,
                              addressmap_entry_source_t addrmap_source,
                              const char **msg);
                              const char **msg);
+int config_parse_unix_port(const char *addrport, char **path_out);
 
 
 /** Represents the information stored in a torrc Bridge line. */
 /** Represents the information stored in a torrc Bridge line. */
 typedef struct bridge_line_t {
 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;
   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
 /** Deallocate memory used by <b>conn</b>. Deallocate its buffers if
  * necessary, close its socket if necessary, and mark the directory as dirty
  * necessary, close its socket if necessary, and mark the directory as dirty
  * if <b>conn</b> is an OR or OP connection.
  * 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) {
     if (conn->socket_family == AF_UNIX) {
       /* For now only control and SOCKS ports can be Unix domain sockets
       /* For now only control and SOCKS ports can be Unix domain sockets
        * and listeners at the same time */
        * 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) {
       if (unlink(conn->address) < 0 && errno != ENOENT) {
         log_warn(LD_NET, "Could not unlink %s: %s", conn->address,
         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
 #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) {
   } else if (listensockaddr->sa_family == AF_UNIX) {
     /* We want to start reading for both AF_UNIX cases */
     /* We want to start reading for both AF_UNIX cases */
     start_reading = 1;
     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,
     if (check_location_for_unix_socket(options, address,
           (type == CONN_TYPE_CONTROL_LISTENER) ?
           (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) {
     if (new_type == CONN_TYPE_AP && conn->socket_family == AF_UNIX) {
       newconn->port = 0;
       newconn->port = 0;
       newconn->address = tor_strdup(conn->address);
       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) {
     if (new_type == CONN_TYPE_CONTROL) {
       log_notice(LD_CONTROL, "New control connection opened from %s.",
       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_type_to_string(int type);
 const char *conn_state_to_string(int type, int state);
 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);
 dir_connection_t *dir_connection_new(int socket_family);
 or_connection_t *or_connection_new(int type, 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. */
                                  * for control connections. */
 
 
   int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
   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? */
   int SocksSocketsGroupWritable; /**< Boolean: Are SOCKS sockets g+rw? */
   /** Ports to listen on for directory connections. */
   /** Ports to listen on for directory connections. */
   config_line_t *DirPort_lines;
   config_line_t *DirPort_lines;
@@ -3489,7 +3486,6 @@ typedef struct {
    */
    */
   unsigned int ORPort_set : 1;
   unsigned int ORPort_set : 1;
   unsigned int SocksPort_set : 1;
   unsigned int SocksPort_set : 1;
-  unsigned int SocksSocket_set : 1;
   unsigned int TransPort_set : 1;
   unsigned int TransPort_set : 1;
   unsigned int NATDPort_set : 1;
   unsigned int NATDPort_set : 1;
   unsigned int ControlPort_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;
   tor_addr_t addr;
   const char *addrport;
   const char *addrport;
   rend_service_port_config_t *result = NULL;
   rend_service_port_config_t *result = NULL;
-  const char *socket_prefix = "socket:";
   unsigned int is_unix_addr = 0;
   unsigned int is_unix_addr = 0;
   char *socket_path = NULL;
   char *socket_path = NULL;
 
 
@@ -365,25 +364,19 @@ parse_port_config(const char *string)
     realport = virtport;
     realport = virtport;
     tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
     tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
   } else {
   } else {
+    int ret;
+
     addrport = smartlist_get(sl,1);
     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,
         log_warn(LD_CONFIG,
                  "Empty socket path in hidden service port configuration.");
                  "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 if (strchr(addrport, ':') || strchr(addrport, '.')) {
       /* else try it as an IP:port pair if it has a : or . in it */
       /* else try it as an IP:port pair if it has a : or . in it */
       if (tor_addr_port_lookup(addrport, &addr, &p)<0) {
       if (tor_addr_port_lookup(addrport, &addr, &p)<0) {