diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-01-29 15:16:15 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-01-29 15:16:15 -0500 |
commit | a87ea9b1c6a61acebc670f54a62e8c443329c34c (patch) | |
tree | 22eb6cbc3f8fc34757f42afc60829364ff808751 | |
parent | f6afb04abbf46d04c718fa3506000f4fb41e2510 (diff) | |
parent | 4c5133e42d731a79480b6d54fbe81f440a9f4429 (diff) | |
download | tor-a87ea9b1c6a61acebc670f54a62e8c443329c34c.tar.gz tor-a87ea9b1c6a61acebc670f54a62e8c443329c34c.zip |
Merge branch 'bug14451_026_v1'
-rw-r--r-- | changes/bug12585 | 7 | ||||
-rw-r--r-- | changes/bug14451 | 7 | ||||
-rw-r--r-- | doc/tor.1.txt | 8 | ||||
-rw-r--r-- | src/or/config.c | 108 | ||||
-rw-r--r-- | src/or/config.h | 1 | ||||
-rw-r--r-- | src/or/connection.c | 29 | ||||
-rw-r--r-- | src/or/connection.h | 1 | ||||
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/rendservice.c | 25 |
9 files changed, 123 insertions, 67 deletions
diff --git a/changes/bug12585 b/changes/bug12585 index 495a2f0d71..ac03993916 100644 --- a/changes/bug12585 +++ b/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. + diff --git a/changes/bug14451 b/changes/bug14451 new file mode 100644 index 0000000000..7949a78070 --- /dev/null +++ b/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. + diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 5302b33bd1..90dad545c7 100644 --- a/doc/tor.1.txt +++ b/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 diff --git a/src/or/config.c b/src/or/config.c index 568baec703..05b4d14337 100644 --- a/src/or/config.c +++ b/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 = diff --git a/src/or/config.h b/src/or/config.h index 6bd3eb5734..b064f05321 100644 --- a/src/or/config.h +++ b/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 { diff --git a/src/or/connection.c b/src/or/connection.c index f26ada096b..b7dfb1de02 100644 --- a/src/or/connection.c +++ b/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.", diff --git a/src/or/connection.h b/src/or/connection.h index 50bea51e5b..d0a34ece5c 100644 --- a/src/or/connection.h +++ b/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); diff --git a/src/or/or.h b/src/or/or.h index 49068784f9..4207f3d7b3 100644 --- a/src/or/or.h +++ b/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; diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 8d3f041759..69ea6a9857 100644 --- a/src/or/rendservice.c +++ b/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) { |