diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/or/buffers.c | 17 | ||||
-rw-r--r-- | src/or/config.c | 7 | ||||
-rw-r--r-- | src/or/connection.c | 6 | ||||
-rw-r--r-- | src/or/or.h | 12 |
4 files changed, 35 insertions, 7 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c index b54584fb4a..47fa31dc07 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1781,6 +1781,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, if (req->socks_version != 5) { /* we need to negotiate a method */ unsigned char nummethods = (unsigned char)*(data+1); + int have_user_pass, have_no_auth; int r=0; tor_assert(!req->socks_version); if (datalen < 2u+nummethods) { @@ -1791,19 +1792,21 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, return -1; req->replylen = 2; /* 2 bytes of response */ req->reply[0] = 5; /* socks5 reply */ - if (memchr(data+2, SOCKS_NO_AUTH, nummethods)) { - req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth - method */ - req->socks_version = 5; /* remember we've already negotiated auth */ - log_debug(LD_APP,"socks5: accepted method 0 (no authentication)"); - r=0; - } else if (memchr(data+2, SOCKS_USER_PASS, nummethods)) { + have_user_pass = (memchr(data+2, SOCKS_USER_PASS, nummethods) !=NULL); + have_no_auth = (memchr(data+2, SOCKS_NO_AUTH, nummethods) !=NULL); + if (have_user_pass && !(have_no_auth && req->socks_prefer_no_auth)) { req->auth_type = SOCKS_USER_PASS; req->reply[1] = SOCKS_USER_PASS; /* tell client to use "user/pass" auth method */ req->socks_version = 5; /* remember we've already negotiated auth */ log_debug(LD_APP,"socks5: accepted method 2 (username/password)"); r=0; + } else if (have_no_auth) { + req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth + method */ + req->socks_version = 5; /* remember we've already negotiated auth */ + log_debug(LD_APP,"socks5: accepted method 0 (no authentication)"); + r=0; } else { log_warn(LD_APP, "socks5: offered methods don't include 'no auth' or " diff --git a/src/or/config.c b/src/or/config.c index ffa984bcda..20a3c20fb9 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -5009,6 +5009,7 @@ parse_port_config(smartlist_t *out, int port; int sessiongroup = SESSION_GROUP_UNSET; unsigned isolation = ISO_DEFAULT; + int prefer_no_auth = 0; char *addrport; uint16_t ptmp=0; @@ -5176,6 +5177,9 @@ parse_port_config(smartlist_t *out, } else if (!strcasecmp(elt, "PreferIPv6Automap")) { prefer_ipv6_automap = ! no; continue; + } else if (!strcasecmp(elt, "PreferSOCKSNoAuth")) { + prefer_no_auth = ! no; + continue; } if (!strcasecmpend(elt, "s")) @@ -5235,6 +5239,9 @@ parse_port_config(smartlist_t *out, cfg->use_cached_ipv4_answers = use_cached_ipv4; cfg->use_cached_ipv6_answers = use_cached_ipv6; cfg->prefer_ipv6_virtaddr = prefer_ipv6_automap; + cfg->socks_prefer_no_auth = prefer_no_auth; + if (! (isolation & ISO_SOCKSAUTH)) + cfg->socks_prefer_no_auth = 1; smartlist_add(out, cfg); } diff --git a/src/or/connection.c b/src/or/connection.c index 2cc3d7486b..358a4eed13 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1145,6 +1145,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, lis_conn->use_cached_ipv4_answers = port_cfg->use_cached_ipv4_answers; lis_conn->use_cached_ipv6_answers = port_cfg->use_cached_ipv6_answers; lis_conn->prefer_ipv6_virtaddr = port_cfg->prefer_ipv6_virtaddr; + lis_conn->socks_prefer_no_auth = port_cfg->socks_prefer_no_auth; if (connection_add(conn) < 0) { /* no space, forget it */ log_warn(LD_NET,"connection_add for listener failed. Giving up."); @@ -1325,6 +1326,11 @@ 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) { + TO_ENTRY_CONN(newconn)->socks_request->socks_prefer_no_auth = + TO_LISTENER_CONN(conn)->socks_prefer_no_auth; + } + } else if (conn->socket_family == AF_UNIX) { /* For now only control ports can be Unix domain sockets * and listeners at the same time */ diff --git a/src/or/or.h b/src/or/or.h index 4e19140b4b..ece2bc7b19 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1247,6 +1247,10 @@ typedef struct listener_connection_t { /** One or more ISO_ flags to describe how to isolate streams. */ uint8_t isolation_flags; /**@}*/ + /** For SOCKS connections only: If this is set, we will choose "no + * authentication" instead of "username/password" authentication if both + * are offered. Used as input to parse_socks. */ + unsigned int socks_prefer_no_auth : 1; /** For a SOCKS listeners, these fields describe whether we should * allow IPv4 and IPv6 addresses from our exit nodes, respectively. @@ -3243,6 +3247,10 @@ typedef struct port_cfg_t { uint8_t isolation_flags; /**< Zero or more isolation flags */ int session_group; /**< A session group, or -1 if this port is not in a * session group. */ + /* Socks only: */ + /** When both no-auth and user/pass are advertised by a SOCKS client, select + * no-auth. */ + unsigned int socks_prefer_no_auth : 1; /* Server port types (or, dir) only: */ unsigned int no_advertise : 1; @@ -4159,6 +4167,10 @@ struct socks_request_t { * make sure we send back a socks reply for * every connection. */ unsigned int got_auth : 1; /**< Have we received any authentication data? */ + /** If this is set, we will choose "no authentication" instead of + * "username/password" authentication if both are offered. Used as input to + * parse_socks. */ + unsigned int socks_prefer_no_auth : 1; /** Number of bytes in username; 0 if username is NULL */ size_t usernamelen; |