Bladeren bron

Merge remote-tracking branch 'sysrqb/bug15220_026_sysrqb'

Nick Mathewson 9 jaren geleden
bovenliggende
commit
2ba6542517
5 gewijzigde bestanden met toevoegingen van 116 en 46 verwijderingen
  1. 5 0
      changes/feature15220
  2. 15 1
      doc/tor.1.txt
  3. 69 23
      src/or/config.c
  4. 24 22
      src/or/connection.c
  5. 3 0
      src/or/or.h

+ 5 - 0
changes/feature15220

@@ -0,0 +1,5 @@
+  o Minor features (client, unix sockets):
+    - Add GroupWritable and WorldWritable options to unix-socket based
+      SocksPort and ControlPort options. These options apply to a single
+      socket, and override {Control,Socks}SocketsGroupWritable. Closes
+      ticket 15220.

+ 15 - 1
doc/tor.1.txt

@@ -274,7 +274,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__|**unix:**__path__|**auto**::
+[[ControlPort]] **ControlPort** __PORT__|**unix:**__path__|**auto** [__flags__]::
     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
@@ -284,6 +284,14 @@ GENERAL OPTIONS
     method is sufficient to authenticate to Tor.) This
     method is sufficient to authenticate to Tor.) This
     option is required for many Tor controllers; most use the value of 9051.
     option is required for many Tor controllers; most use the value of 9051.
     Set it to "auto" to have Tor pick a port for you. (Default: 0)
     Set it to "auto" to have Tor pick a port for you. (Default: 0)
+ +
+    Recognized flags are::
+    **GroupWritable**;;
+        Unix domain sockets only: makes the socket get created as
+        group-writable.
+    **WorldWritable**;;
+        Unix domain sockets only: makes the socket get created as
+        world-writable.
 
 
 [[ControlListenAddress]] **ControlListenAddress** __IP__[:__PORT__]::
 [[ControlListenAddress]] **ControlListenAddress** __IP__[:__PORT__]::
     Bind the controller listener to this address. If you specify a port, bind
     Bind the controller listener to this address. If you specify a port, bind
@@ -1009,6 +1017,12 @@ The following options are useful only for clients (that is, if
     **CacheIPv6DNS**;;
     **CacheIPv6DNS**;;
         Tells the client to remember IPv6 DNS answers we receive from exit
         Tells the client to remember IPv6 DNS answers we receive from exit
         nodes via this connection.
         nodes via this connection.
+    **GroupWritable**;;
+        Unix domain sockets only: makes the socket get created as
+        group-writable.
+    **WorldWritable**;;
+        Unix domain sockets only: makes the socket get created as
+        world-writable.
     **CacheDNS**;;
     **CacheDNS**;;
         Tells the client to remember all DNS answers we receive from exit
         Tells the client to remember all DNS answers we receive from exit
         nodes via this connection.
         nodes via this connection.

+ 69 - 23
src/or/config.c

@@ -558,7 +558,8 @@ static int parse_dir_authority_line(const char *line,
                                  int validate_only);
                                  int validate_only);
 static void port_cfg_free(port_cfg_t *port);
 static void port_cfg_free(port_cfg_t *port);
 static int parse_ports(or_options_t *options, int validate_only,
 static int parse_ports(or_options_t *options, int validate_only,
-                              char **msg_out, int *n_ports_out);
+                              char **msg_out, int *n_ports_out,
+                              int *world_writable_control_socket);
 static int check_server_ports(const smartlist_t *ports,
 static int check_server_ports(const smartlist_t *ports,
                               const or_options_t *options);
                               const or_options_t *options);
 
 
@@ -1115,7 +1116,7 @@ options_act_reversible(const or_options_t *old_options, char **msg)
     }
     }
 
 
     /* Adjust the port configuration so we can launch listeners. */
     /* Adjust the port configuration so we can launch listeners. */
-    if (parse_ports(options, 0, msg, &n_ports)) {
+    if (parse_ports(options, 0, msg, &n_ports, NULL)) {
       if (!*msg)
       if (!*msg)
         *msg = tor_strdup("Unexpected problem parsing port config");
         *msg = tor_strdup("Unexpected problem parsing port config");
       goto rollback;
       goto rollback;
@@ -2662,6 +2663,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
   config_line_t *cl;
   config_line_t *cl;
   const char *uname = get_uname();
   const char *uname = get_uname();
   int n_ports=0;
   int n_ports=0;
+  int world_writable_control_socket=0;
 
 
   tor_assert(msg);
   tor_assert(msg);
   *msg = NULL;
   *msg = NULL;
@@ -2678,7 +2680,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
         "for details.", uname);
         "for details.", uname);
   }
   }
 
 
-  if (parse_ports(options, 1, msg, &n_ports) < 0)
+  if (parse_ports(options, 1, msg, &n_ports,
+                  &world_writable_control_socket) < 0)
     return -1;
     return -1;
 
 
   if (parse_outbound_addresses(options, 1, msg) < 0)
   if (parse_outbound_addresses(options, 1, msg) < 0)
@@ -3459,13 +3462,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
     }
     }
   }
   }
 
 
-  if (options->ControlPort_set && !options->HashedControlPassword &&
+  if ((options->ControlPort_set || world_writable_control_socket) &&
+      !options->HashedControlPassword &&
       !options->HashedControlSessionPassword &&
       !options->HashedControlSessionPassword &&
       !options->CookieAuthentication) {
       !options->CookieAuthentication) {
-    log_warn(LD_CONFIG, "ControlPort is open, but no authentication method "
+    log_warn(LD_CONFIG, "Control%s is %s, but no authentication method "
              "has been configured.  This means that any program on your "
              "has been configured.  This means that any program on your "
              "computer can reconfigure your Tor.  That's bad!  You should "
              "computer can reconfigure your Tor.  That's bad!  You should "
-             "upgrade your Tor controller as soon as possible.");
+             "upgrade your Tor controller as soon as possible.",
+             options->ControlPort_set ? "Port" : "Socket",
+             options->ControlPort_set ? "open" : "world writable");
   }
   }
 
 
   if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) {
   if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) {
@@ -5700,11 +5706,11 @@ warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname)
 }
 }
 
 
 /** Given a list of port_cfg_t in <b>ports</b>, warn any controller port there
 /** Given a list of port_cfg_t in <b>ports</b>, warn any controller port there
- * is listening on any non-loopback address.  If <b>forbid</b> is true,
+ * is listening on any non-loopback address.  If <b>forbid_nonlocal</b> is true,
  * then emit a stronger warning and remove the port from the list.
  * then emit a stronger warning and remove the port from the list.
  */
  */
 static void
 static void
-warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid)
+warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid_nonlocal)
 {
 {
   int warned = 0;
   int warned = 0;
   SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
   SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
@@ -5713,7 +5719,7 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid)
     if (port->is_unix_addr)
     if (port->is_unix_addr)
       continue;
       continue;
     if (!tor_addr_is_loopback(&port->addr)) {
     if (!tor_addr_is_loopback(&port->addr)) {
-      if (forbid) {
+      if (forbid_nonlocal) {
         if (!warned)
         if (!warned)
           log_warn(LD_CONFIG,
           log_warn(LD_CONFIG,
                  "You have a ControlPort set to accept "
                  "You have a ControlPort set to accept "
@@ -5741,13 +5747,14 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid)
   } SMARTLIST_FOREACH_END(port);
   } SMARTLIST_FOREACH_END(port);
 }
 }
 
 
-#define CL_PORT_NO_OPTIONS (1u<<0)
+#define CL_PORT_NO_STREAM_OPTIONS (1u<<0)
 #define CL_PORT_WARN_NONLOCAL (1u<<1)
 #define CL_PORT_WARN_NONLOCAL (1u<<1)
 #define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2)
 #define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2)
 #define CL_PORT_SERVER_OPTIONS (1u<<3)
 #define CL_PORT_SERVER_OPTIONS (1u<<3)
 #define CL_PORT_FORBID_NONLOCAL (1u<<4)
 #define CL_PORT_FORBID_NONLOCAL (1u<<4)
 #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)
+#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7)
 
 
 #ifdef HAVE_SYS_UN_H
 #ifdef HAVE_SYS_UN_H
 
 
@@ -5815,12 +5822,12 @@ config_parse_unix_port(const char *addrport, char **path_out)
  * If no address is specified, default to <b>defaultaddr</b>.  If no
  * If no address is specified, default to <b>defaultaddr</b>.  If no
  * FooPort is given, default to defaultport (if 0, there is no default).
  * FooPort is given, default to defaultport (if 0, there is no default).
  *
  *
- * If CL_PORT_NO_OPTIONS is set in <b>flags</b>, do not allow stream
+ * If CL_PORT_NO_STREAM_OPTIONS is set in <b>flags</b>, do not allow stream
  * isolation options in the FooPort entries.
  * isolation options in the FooPort entries.
  *
  *
  * If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the
  * If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the
  * ports are not on a local address.  If CL_PORT_FORBID_NONLOCAL is set,
  * ports are not on a local address.  If CL_PORT_FORBID_NONLOCAL is set,
- * this is a contrl port with no password set: don't even allow it.
+ * this is a control port with no password set: don't even allow it.
  *
  *
  * Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn
  * Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn
  * if FooListenAddress is set but FooPort is 0.
  * if FooListenAddress is set but FooPort is 0.
@@ -5850,10 +5857,12 @@ parse_port_config(smartlist_t *out,
   int retval = -1;
   int retval = -1;
   const unsigned is_control = (listener_type == CONN_TYPE_CONTROL_LISTENER);
   const unsigned is_control = (listener_type == CONN_TYPE_CONTROL_LISTENER);
   const unsigned is_ext_orport = (listener_type == CONN_TYPE_EXT_OR_LISTENER);
   const unsigned is_ext_orport = (listener_type == CONN_TYPE_EXT_OR_LISTENER);
-  const unsigned allow_no_options = flags & CL_PORT_NO_OPTIONS;
+  const unsigned allow_no_stream_options = flags & CL_PORT_NO_STREAM_OPTIONS;
   const unsigned use_server_options = flags & CL_PORT_SERVER_OPTIONS;
   const unsigned use_server_options = flags & CL_PORT_SERVER_OPTIONS;
   const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
   const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
   const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL;
   const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL;
+  const unsigned default_to_group_writable =
+    flags & CL_PORT_DFLT_GROUP_WRITABLE;
   const unsigned allow_spurious_listenaddr =
   const unsigned allow_spurious_listenaddr =
     flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
     flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
   const unsigned takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES;
   const unsigned takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES;
@@ -5977,7 +5986,7 @@ parse_port_config(smartlist_t *out,
       ipv4_traffic = 1, ipv6_traffic = 0, prefer_ipv6 = 0,
       ipv4_traffic = 1, ipv6_traffic = 0, prefer_ipv6 = 0,
       cache_ipv4 = 1, use_cached_ipv4 = 0,
       cache_ipv4 = 1, use_cached_ipv4 = 0,
       cache_ipv6 = 0, use_cached_ipv6 = 0,
       cache_ipv6 = 0, use_cached_ipv6 = 0,
-      prefer_ipv6_automap = 1;
+      prefer_ipv6_automap = 1, world_writable = 0, group_writable = 0;
 
 
     smartlist_split_string(elts, ports->value, NULL,
     smartlist_split_string(elts, ports->value, NULL,
                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
@@ -5986,11 +5995,6 @@ parse_port_config(smartlist_t *out,
       goto err;
       goto err;
     }
     }
 
 
-    if (allow_no_options && smartlist_len(elts) > 1) {
-      log_warn(LD_CONFIG, "Too many options on %sPort line", portname);
-      goto err;
-    }
-
     /* Now parse the addr/port value */
     /* Now parse the addr/port value */
     addrport = smartlist_get(elts, 0);
     addrport = smartlist_get(elts, 0);
 
 
@@ -6050,6 +6054,9 @@ parse_port_config(smartlist_t *out,
       }
       }
     }
     }
 
 
+    if (unix_socket_path && default_to_group_writable)
+      group_writable = 1;
+
     /* Now parse the rest of the options, if any. */
     /* Now parse the rest of the options, if any. */
     if (use_server_options) {
     if (use_server_options) {
       /* This is a server port; parse advertising options */
       /* This is a server port; parse advertising options */
@@ -6106,10 +6113,11 @@ parse_port_config(smartlist_t *out,
         const char *elt_orig = elt;
         const char *elt_orig = elt;
         if (elt_sl_idx == 0)
         if (elt_sl_idx == 0)
           continue; /* Skip addr:port */
           continue; /* Skip addr:port */
+
         if (!strcasecmpstart(elt, "SessionGroup=")) {
         if (!strcasecmpstart(elt, "SessionGroup=")) {
           int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
           int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
                                           10, 0, INT_MAX, &ok, NULL);
                                           10, 0, INT_MAX, &ok, NULL);
-          if (!ok) {
+          if (!ok || !allow_no_stream_options) {
             log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
             log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
                      portname, escaped(elt));
                      portname, escaped(elt));
             goto err;
             goto err;
@@ -6128,6 +6136,20 @@ parse_port_config(smartlist_t *out,
           elt += 2;
           elt += 2;
         }
         }
 
 
+        if (!strcasecmp(elt, "GroupWritable")) {
+          group_writable = !no;
+          continue;
+        } else if (!strcasecmp(elt, "WorldWritable")) {
+          world_writable = !no;
+          continue;
+        }
+
+        if (allow_no_stream_options) {
+          log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
+                   portname, escaped(elt));
+          continue;
+        }
+
         if (takes_hostnames) {
         if (takes_hostnames) {
           if (!strcasecmp(elt, "IPv4Traffic")) {
           if (!strcasecmp(elt, "IPv4Traffic")) {
             ipv4_traffic = ! no;
             ipv4_traffic = ! no;
@@ -6203,6 +6225,12 @@ parse_port_config(smartlist_t *out,
       goto err;
       goto err;
     }
     }
 
 
+    if ( (world_writable || group_writable) && ! unix_socket_path) {
+      log_warn(LD_CONFIG, "You have a %sPort entry with GroupWritable "
+               "or WorldWritable set, but it is not a unix socket.", portname);
+      goto err;
+    }
+
     if (out && port) {
     if (out && port) {
       size_t namelen = unix_socket_path ? strlen(unix_socket_path) : 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);
@@ -6216,6 +6244,8 @@ parse_port_config(smartlist_t *out,
         cfg->port = port;
         cfg->port = port;
       }
       }
       cfg->type = listener_type;
       cfg->type = listener_type;
+      cfg->is_world_writable = world_writable;
+      cfg->is_group_writable = group_writable;
       cfg->entry_cfg.isolation_flags = isolation;
       cfg->entry_cfg.isolation_flags = isolation;
       cfg->entry_cfg.session_group = sessiongroup;
       cfg->entry_cfg.session_group = sessiongroup;
       cfg->server_cfg.no_advertise = no_advertise;
       cfg->server_cfg.no_advertise = no_advertise;
@@ -6293,7 +6323,8 @@ count_real_listeners(const smartlist_t *ports, int listenertype)
  **/
  **/
 static int
 static int
 parse_ports(or_options_t *options, int validate_only,
 parse_ports(or_options_t *options, int validate_only,
-            char **msg, int *n_ports_out)
+            char **msg, int *n_ports_out,
+            int *world_writable_control_socket)
 {
 {
   smartlist_t *ports;
   smartlist_t *ports;
   int retval = -1;
   int retval = -1;
@@ -6302,12 +6333,14 @@ parse_ports(or_options_t *options, int validate_only,
 
 
   *n_ports_out = 0;
   *n_ports_out = 0;
 
 
+  const unsigned gw_flag = options->SocksSocketsGroupWritable ?
+    CL_PORT_DFLT_GROUP_WRITABLE : 0;
   if (parse_port_config(ports,
   if (parse_port_config(ports,
              options->SocksPort_lines, options->SocksListenAddress,
              options->SocksPort_lines, options->SocksListenAddress,
              "Socks", CONN_TYPE_AP_LISTENER,
              "Socks", CONN_TYPE_AP_LISTENER,
              "127.0.0.1", 9050,
              "127.0.0.1", 9050,
              CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR|
              CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR|
-             CL_PORT_TAKES_HOSTNAMES) < 0) {
+             CL_PORT_TAKES_HOSTNAMES|gw_flag) < 0) {
     *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
     *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
     goto err;
     goto err;
   }
   }
@@ -6336,12 +6369,15 @@ parse_ports(or_options_t *options, int validate_only,
     goto err;
     goto err;
   }
   }
   {
   {
-    unsigned control_port_flags = CL_PORT_NO_OPTIONS | CL_PORT_WARN_NONLOCAL;
+    unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS |
+      CL_PORT_WARN_NONLOCAL;
     const int any_passwords = (options->HashedControlPassword ||
     const int any_passwords = (options->HashedControlPassword ||
                                options->HashedControlSessionPassword ||
                                options->HashedControlSessionPassword ||
                                options->CookieAuthentication);
                                options->CookieAuthentication);
     if (! any_passwords)
     if (! any_passwords)
       control_port_flags |= CL_PORT_FORBID_NONLOCAL;
       control_port_flags |= CL_PORT_FORBID_NONLOCAL;
+    if (options->ControlSocketsGroupWritable)
+      control_port_flags |= CL_PORT_DFLT_GROUP_WRITABLE;
 
 
     if (parse_port_config(ports,
     if (parse_port_config(ports,
                           options->ControlPort_lines,
                           options->ControlPort_lines,
@@ -6417,6 +6453,16 @@ parse_ports(or_options_t *options, int validate_only,
   options->ExtORPort_set =
   options->ExtORPort_set =
     !! count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER);
     !! count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER);
 
 
+  if (world_writable_control_socket) {
+    SMARTLIST_FOREACH(ports, port_cfg_t *, p,
+      if (p->type == CONN_TYPE_CONTROL_LISTENER &&
+          p->is_unix_addr &&
+          p->is_world_writable) {
+        *world_writable_control_socket = 1;
+        break;
+      });
+  }
+
   if (!validate_only) {
   if (!validate_only) {
     if (configured_ports) {
     if (configured_ports) {
       SMARTLIST_FOREACH(configured_ports,
       SMARTLIST_FOREACH(configured_ports,

+ 24 - 22
src/or/connection.c

@@ -979,7 +979,7 @@ unix_socket_purpose_to_string(int purpose)
  * <b>path</b>.  Return 0 if we should go ahead and -1 if we shouldn't. */
  * <b>path</b>.  Return 0 if we should go ahead and -1 if we shouldn't. */
 static int
 static int
 check_location_for_unix_socket(const or_options_t *options, const char *path,
 check_location_for_unix_socket(const or_options_t *options, const char *path,
-                               int purpose)
+                               int purpose, const port_cfg_t *port)
 {
 {
   int r = -1;
   int r = -1;
   char *p = NULL;
   char *p = NULL;
@@ -994,10 +994,13 @@ check_location_for_unix_socket(const or_options_t *options, const char *path,
     goto done;
     goto done;
   }
   }
 
 
-  if ((purpose == UNIX_SOCKET_PURPOSE_CONTROL_SOCKET &&
-       options->ControlSocketsGroupWritable) ||
-      (purpose == UNIX_SOCKET_PURPOSE_SOCKS_SOCKET &&
-       options->SocksSocketsGroupWritable)) {
+  if (port->is_world_writable) {
+    /* World-writable sockets can go anywhere. */
+    r = 0;
+    goto done;
+  }
+
+  if (port->is_group_writable) {
     flags |= CPD_GROUP_OK;
     flags |= CPD_GROUP_OK;
   }
   }
 
 
@@ -1011,7 +1014,7 @@ check_location_for_unix_socket(const or_options_t *options, const char *path,
              "who can list a socket can connect to it, so Tor is being "
              "who can list a socket can connect to it, so Tor is being "
              "careful.)",
              "careful.)",
              unix_socket_purpose_to_string(purpose), escpath, escdir,
              unix_socket_purpose_to_string(purpose), escpath, escdir,
-             options->ControlSocketsGroupWritable ? " and group" : "");
+             port->is_group_writable ? " and group" : "");
     tor_free(escpath);
     tor_free(escpath);
     tor_free(escdir);
     tor_free(escdir);
     goto done;
     goto done;
@@ -1206,7 +1209,7 @@ connection_listener_new(const struct sockaddr *listensockaddr,
     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) ?
            UNIX_SOCKET_PURPOSE_CONTROL_SOCKET :
            UNIX_SOCKET_PURPOSE_CONTROL_SOCKET :
-           UNIX_SOCKET_PURPOSE_SOCKS_SOCKET) < 0) {
+           UNIX_SOCKET_PURPOSE_SOCKS_SOCKET, port_cfg) < 0) {
         goto err;
         goto err;
     }
     }
 
 
@@ -1254,24 +1257,23 @@ connection_listener_new(const struct sockaddr *listensockaddr,
     }
     }
 #endif
 #endif
 
 
-    if ((type == CONN_TYPE_CONTROL_LISTENER &&
-         options->ControlSocketsGroupWritable) ||
-        (type == CONN_TYPE_AP_LISTENER &&
-         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;
+    {
+      unsigned mode;
+      const char *status;
+      if (port_cfg->is_world_writable) {
+        mode = 0666;
+        status = "world-writable";
+      } else if (port_cfg->is_group_writable) {
+        mode = 0660;
+        status = "group-writable";
+      } else {
+        mode = 0600;
+        status = "private";
       }
       }
-    } else if ((type == CONN_TYPE_CONTROL_LISTENER &&
-                !(options->ControlSocketsGroupWritable)) ||
-               (type == CONN_TYPE_AP_LISTENER &&
-                !(options->SocksSocketsGroupWritable))) {
       /* We need to use chmod; fchmod doesn't work on sockets on all
       /* We need to use chmod; fchmod doesn't work on sockets on all
        * platforms. */
        * platforms. */
-      if (chmod(address, 0600) < 0) {
-        log_warn(LD_FS,"Unable to make %s group-writable.", address);
+      if (chmod(address, mode) < 0) {
+        log_warn(LD_FS,"Unable to make %s %s.", address, status);
         goto err;
         goto err;
       }
       }
     }
     }

+ 3 - 0
src/or/or.h

@@ -3356,6 +3356,9 @@ typedef struct port_cfg_t {
   uint8_t type; /**< One of CONN_TYPE_*_LISTENER */
   uint8_t type; /**< One of CONN_TYPE_*_LISTENER */
   unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */
   unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */
 
 
+  unsigned is_group_writable : 1;
+  unsigned is_world_writable : 1;
+
   entry_port_cfg_t entry_cfg;
   entry_port_cfg_t entry_cfg;
 
 
   server_port_cfg_t server_cfg;
   server_port_cfg_t server_cfg;