summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/buffers.c7
-rw-r--r--src/or/config.c9
-rw-r--r--src/or/connection.c6
-rw-r--r--src/or/or.h12
4 files changed, 32 insertions, 2 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 4554a02d69..c0868f479f 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1773,6 +1773,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) {
@@ -1783,14 +1784,16 @@ 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_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 (memchr(data+2, SOCKS_NO_AUTH, nummethods)) {
+ } 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 */
diff --git a/src/or/config.c b/src/or/config.c
index 90a5dfbda1..a80576e20a 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -5787,6 +5787,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;
@@ -5916,6 +5917,11 @@ parse_port_config(smartlist_t *out,
no = 1;
elt += 2;
}
+ if (!strcasecmp(elt, "PreferSOCKSNoAuth")) {
+ prefer_no_auth = ! no;
+ continue;
+ }
+
if (!strcasecmpend(elt, "s"))
elt[strlen(elt)-1] = '\0'; /* kill plurals. */
@@ -5959,6 +5965,9 @@ parse_port_config(smartlist_t *out,
cfg->all_addrs = all_addrs;
cfg->ipv4_only = ipv4_only;
cfg->ipv6_only = ipv6_only;
+ 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 eac9c4f32b..aeb4949e0a 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1056,6 +1056,7 @@ connection_listener_new(const struct sockaddr *listensockaddr,
lis_conn->session_group = global_next_session_group--;
}
}
+ 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.");
@@ -1238,6 +1239,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 51c23d305d..ca28c0e7b5 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1085,6 +1085,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;
} listener_connection_t;
@@ -2910,6 +2914,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;
@@ -3729,6 +3737,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;