|
@@ -29,8 +29,9 @@
|
|
|
static void
|
|
|
directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
|
|
const char *payload, int payload_len);
|
|
|
-static void directory_send_command(connection_t *conn, int purpose,
|
|
|
- const char *payload, int payload_len);
|
|
|
+static void
|
|
|
+directory_send_command(connection_t *conn, routerinfo_t *router, int purpose,
|
|
|
+ const char *payload, int payload_len);
|
|
|
static int directory_handle_command(connection_t *conn);
|
|
|
|
|
|
|
|
@@ -128,8 +129,7 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
|
|
tor_assert(router);
|
|
|
tor_assert(router->dir_port);
|
|
|
|
|
|
- switch (purpose)
|
|
|
- {
|
|
|
+ switch (purpose) {
|
|
|
case DIR_PURPOSE_FETCH_DIR:
|
|
|
log_fn(LOG_DEBUG,"initiating directory fetch");
|
|
|
break;
|
|
@@ -145,13 +145,18 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
|
|
default:
|
|
|
log_fn(LOG_ERR, "Unrecognized directory connection purpose.");
|
|
|
tor_assert(0);
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
conn = connection_new(CONN_TYPE_DIR);
|
|
|
|
|
|
|
|
|
- conn->addr = router->addr;
|
|
|
- conn->port = router->dir_port;
|
|
|
+ if(options.HttpProxy) {
|
|
|
+ conn->addr = options.HttpProxyAddr;
|
|
|
+ conn->port = options.HttpProxyPort;
|
|
|
+ } else {
|
|
|
+ conn->addr = router->addr;
|
|
|
+ conn->port = router->dir_port;
|
|
|
+ }
|
|
|
conn->address = tor_strdup(router->address);
|
|
|
conn->nickname = tor_strdup(router->nickname);
|
|
|
tor_assert(router->identity_pkey);
|
|
@@ -180,7 +185,7 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
- directory_send_command(conn, purpose, payload, payload_len);
|
|
|
+ directory_send_command(conn, router, purpose, payload, payload_len);
|
|
|
|
|
|
connection_watch_events(conn, POLLIN | POLLOUT | POLLERR);
|
|
|
|
|
@@ -201,7 +206,7 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
|
|
conn->state = DIR_CONN_STATE_CLIENT_SENDING;
|
|
|
connection_add(conn);
|
|
|
|
|
|
- directory_send_command(conn, purpose, payload, payload_len);
|
|
|
+ directory_send_command(conn, router, purpose, payload, payload_len);
|
|
|
connection_watch_events(conn, POLLIN | POLLOUT | POLLERR);
|
|
|
}
|
|
|
}
|
|
@@ -210,44 +215,49 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
|
|
* <b>purpose</b>, <b>payload</b>, and <b>payload_len</b> are as in
|
|
|
* directory_initiate_command.
|
|
|
*/
|
|
|
-static void directory_send_command(connection_t *conn, int purpose,
|
|
|
- const char *payload, int payload_len) {
|
|
|
- char fetchwholedir[] = "GET / HTTP/1.0\r\n\r\n";
|
|
|
- char fetchwholedir_z[] = "GET /tor/dir.z HTTP/1.0\r\n\r\n";
|
|
|
- char fetchrunninglist[] = "GET /tor/running-routers HTTP/1.0\r\n\r\n";
|
|
|
+static void
|
|
|
+directory_send_command(connection_t *conn, routerinfo_t *router, int purpose,
|
|
|
+ const char *payload, int payload_len) {
|
|
|
char tmp[8192];
|
|
|
- routerinfo_t *router;
|
|
|
+ char proxystring[128];
|
|
|
+ char hoststring[128];
|
|
|
+ char url[128];
|
|
|
int use_newer = 0;
|
|
|
+ char *httpcommand = NULL;
|
|
|
|
|
|
tor_assert(conn && conn->type == CONN_TYPE_DIR);
|
|
|
-
|
|
|
- router = router_get_by_digest(conn->identity_digest);
|
|
|
- tor_assert(router);
|
|
|
+ tor_assert(router);
|
|
|
|
|
|
use_newer = tor_version_as_new_as(router->platform, "0.0.9pre1");
|
|
|
|
|
|
+ if(router->dir_port == 80) {
|
|
|
+ strlcpy(hoststring, router->address, sizeof(hoststring));
|
|
|
+ } else {
|
|
|
+ sprintf(hoststring, "%s:%d", router->address, router->dir_port);
|
|
|
+ }
|
|
|
+ if(options.HttpProxy) {
|
|
|
+ sprintf(proxystring, "http://%s", hoststring);
|
|
|
+ } else {
|
|
|
+ proxystring[0] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
switch(purpose) {
|
|
|
case DIR_PURPOSE_FETCH_DIR:
|
|
|
tor_assert(payload == NULL);
|
|
|
- if(use_newer) {
|
|
|
- log_fn(LOG_DEBUG, "Asking for compressed directory from server running %s", router->platform);
|
|
|
- connection_write_to_buf(fetchwholedir_z, strlen(fetchwholedir_z), conn);
|
|
|
- } else {
|
|
|
- log_fn(LOG_DEBUG, "Asking for uncompressed directory from server running %s", router->platform);
|
|
|
- connection_write_to_buf(fetchwholedir, strlen(fetchwholedir), conn);
|
|
|
- }
|
|
|
+ log_fn(LOG_DEBUG, "Asking for %scompressed directory from server running %s",
|
|
|
+ use_newer?"":"un", router->platform);
|
|
|
+ httpcommand = "GET";
|
|
|
+ strlcpy(url, use_newer ? "/tor/dir.z" : "/", sizeof(url));
|
|
|
break;
|
|
|
case DIR_PURPOSE_FETCH_RUNNING_LIST:
|
|
|
tor_assert(payload == NULL);
|
|
|
- connection_write_to_buf(fetchrunninglist, strlen(fetchrunninglist), conn);
|
|
|
+ httpcommand = "GET";
|
|
|
+ strlcpy(url, use_newer ? "/tor/running-routers" : "/running-routers", sizeof(url));
|
|
|
break;
|
|
|
case DIR_PURPOSE_UPLOAD_DIR:
|
|
|
tor_assert(payload);
|
|
|
- snprintf(tmp, sizeof(tmp), "POST %s/ HTTP/1.0\r\nContent-Length: %d\r\n\r\n",
|
|
|
- use_newer ? "/tor" : "",
|
|
|
- payload_len);
|
|
|
- connection_write_to_buf(tmp, strlen(tmp), conn);
|
|
|
- connection_write_to_buf(payload, payload_len, conn);
|
|
|
+ httpcommand = "POST";
|
|
|
+ strlcpy(url, use_newer ? "/tor/" : "/", sizeof(url));
|
|
|
break;
|
|
|
case DIR_PURPOSE_FETCH_RENDDESC:
|
|
|
tor_assert(payload);
|
|
@@ -258,21 +268,32 @@ static void directory_send_command(connection_t *conn, int purpose,
|
|
|
memcpy(conn->rend_query, payload, payload_len);
|
|
|
conn->rend_query[payload_len] = 0;
|
|
|
|
|
|
- snprintf(tmp, sizeof(tmp), "GET %s%s HTTP/1.0\r\n\r\n", "/rendezvous/", payload);
|
|
|
- connection_write_to_buf(tmp, strlen(tmp), conn);
|
|
|
+ httpcommand = "GET";
|
|
|
+ sprintf(url, "%s/rendezvous/%s", use_newer ? "/tor" : "", payload);
|
|
|
break;
|
|
|
case DIR_PURPOSE_UPLOAD_RENDDESC:
|
|
|
tor_assert(payload);
|
|
|
- snprintf(tmp, sizeof(tmp),
|
|
|
- "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n", "/rendezvous/publish", payload_len);
|
|
|
- connection_write_to_buf(tmp, strlen(tmp), conn);
|
|
|
-
|
|
|
- connection_write_to_buf(payload, payload_len, conn);
|
|
|
+ httpcommand = "POST";
|
|
|
+ sprintf(url, "%s/rendezvous/publish", use_newer ? "/tor" : "");
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ snprintf(tmp, sizeof(tmp), "%s %s%s HTTP/1.0\r\nContent-Length: %d\r\nHost: %s\r\n\r\n",
|
|
|
+ httpcommand,
|
|
|
+ proxystring,
|
|
|
+ url,
|
|
|
+ payload_len,
|
|
|
+ hoststring);
|
|
|
+ connection_write_to_buf(tmp, strlen(tmp), conn);
|
|
|
+
|
|
|
+ if(purpose == DIR_PURPOSE_UPLOAD_DIR || purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
|
|
|
+
|
|
|
+ connection_write_to_buf(payload, payload_len, conn);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * "\%s [http[s]://]\%s HTTP/1..."
|
|
|
* If it's well-formed, strdup the second \%s into *<b>url</b>, and
|
|
|
* null-terminate it. If the url doesn't start with "/tor/", rewrite it
|
|
|
* so it does. Return 0.
|
|
@@ -281,7 +302,7 @@ static void directory_send_command(connection_t *conn, int purpose,
|
|
|
static int
|
|
|
parse_http_url(char *headers, char **url)
|
|
|
{
|
|
|
- char *s, *start;
|
|
|
+ char *s, *start, *tmp;
|
|
|
|
|
|
s = (char *)eat_whitespace_no_nl(headers);
|
|
|
if (!*s) return -1;
|
|
@@ -292,6 +313,21 @@ parse_http_url(char *headers, char **url)
|
|
|
start = s;
|
|
|
s = (char *)find_whitespace(start);
|
|
|
if (!*s) return -1;
|
|
|
+
|
|
|
+
|
|
|
+ if(s-start >= 4 && !strcmpstart(start,"http")) {
|
|
|
+ tmp = start + 4;
|
|
|
+ if(*tmp == 's')
|
|
|
+ tmp++;
|
|
|
+ if(s-tmp >= 3 && !strcmpstart(tmp,"://")) {
|
|
|
+ tmp = strchr(tmp+3, '/');
|
|
|
+ if(tmp && tmp < s) {
|
|
|
+ log_fn(LOG_DEBUG,"Skipping over 'http[s]://hostname' string");
|
|
|
+ start = tmp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if(s-start < 5 || strcmpstart(start,"/tor/")) {
|
|
|
*url = tor_malloc(s - start + 5);
|
|
|
strcpy(*url,"/tor");
|