diff --git a/src/or/config.c b/src/or/config.c index 62fa32e4a0..b3d2ec0ee0 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -134,6 +134,7 @@ static config_var_t config_vars[] = { VAR("HashedControlPassword",STRING, HashedControlPassword, NULL), VAR("HttpProxy", STRING, HttpProxy, NULL), VAR("HttpsProxy", STRING, HttpsProxy, NULL), + VAR("HttpsProxyAuthenticator",STRING,HttpsProxyAuthenticator,NULL), VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL), @@ -343,8 +344,6 @@ options_act(void) { set_exit_redirects(sl); } - /* Start backgrounding the process, if requested. */ - /* Finish backgrounding the process */ if (options->RunAsDaemon) { /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */ @@ -1512,6 +1511,13 @@ options_validate(or_options_t *options) } } + if (options->HttpsProxyAuthenticator) { + if (strlen(options->HttpsProxyAuthenticator) >= 48) { + log(LOG_WARN, "HttpsProxyAuthenticator is too long (>= 48 chars)."); + result = -1; + } + } + if (options->HashedControlPassword) { if (decode_hashed_password(NULL, options->HashedControlPassword)<0) { log_fn(LOG_WARN,"Bad HashedControlPassword: wrong length or bad base64"); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 461ca96922..aa8dc0abe6 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -171,11 +171,35 @@ int connection_or_finished_connecting(connection_t *conn) char buf[1024]; char addrbuf[INET_NTOA_BUF_LEN]; struct in_addr in; + const char *authenticator = get_options()->HttpsProxyAuthenticator; in.s_addr = htonl(conn->addr); tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf)); - tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n", - addrbuf, conn->port); + + if (authenticator) { + /* an authenticator in Basic authentication + * is just the string "username:password" */ + const int authenticator_length = strlen(authenticator); + /* The base64_encode function needs a minimum buffer length + * of 66 bytes. */ + const int base64_authenticator_length = (authenticator_length/48+1)*66; + char *base64_authenticator = tor_malloc(base64_authenticator_length); + if (base64_encode(base64_authenticator, base64_authenticator_length, + authenticator, authenticator_length) < 0) { + log_fn(LOG_WARN, "Encoding authenticator failed"); + base64_authenticator[0] = 0; + } else { + /* remove extra \n at end of encoding */ + base64_authenticator[strlen(base64_authenticator) - 1] = 0; + } + tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", addrbuf, + conn->port, base64_authenticator); + tor_free(base64_authenticator); + } else { + tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n", + addrbuf, conn->port); + } connection_write_to_buf(buf, strlen(buf), conn); conn->state = OR_CONN_STATE_PROXY_FLUSHING; return 0; diff --git a/src/or/or.h b/src/or/or.h index 232eeb5960..67e1ff2a80 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1059,6 +1059,7 @@ typedef struct { char *HttpsProxy; /**< hostname[:port] to use as https proxy, if any */ uint32_t HttpsProxyAddr; /**< Parsed IPv4 addr for https proxy, if any */ uint16_t HttpsProxyPort; /**< Parsed port for https proxy, if any */ + char *HttpsProxyAuthenticator; /** username:password string, if any */ struct config_line_t *DirServers; /**< List of configuration lines * for directory servers. */