diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/directory.c | 116 | ||||
-rw-r--r-- | src/or/or.h | 7 |
2 files changed, 82 insertions, 41 deletions
diff --git a/src/or/directory.c b/src/or/directory.c index c505d9252..d013b0f3c 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -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); /********* START VARIABLES **********/ @@ -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); /* set up conn so it's got all the data we need to remember */ - 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, /* fall through */ case 0: /* queue the command on the outbuf */ - directory_send_command(conn, purpose, payload, payload_len); + directory_send_command(conn, router, purpose, payload, payload_len); connection_watch_events(conn, POLLIN | POLLOUT | POLLERR); /* writable indicates finish, readable indicates broken link, @@ -201,7 +206,7 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose, conn->state = DIR_CONN_STATE_CLIENT_SENDING; connection_add(conn); /* queue the command on the outbuf */ - 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"; /* deprecated */ - 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); /* the func that calls us found it, so we should too */ + 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); - /* could include nuls, need to write it separately */ - 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) { + /* then send the payload afterwards too */ + connection_write_to_buf(payload, payload_len, conn); + } } -/** Parse an HTTP request string <b>headers</b> of the form "\%s \%s HTTP/1..." +/** Parse an HTTP request string <b>headers</b> of the form + * "\%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; /* this is it, assuming it's valid */ s = (char *)find_whitespace(start); if (!*s) return -1; + + /* tolerate the http[s] proxy style of putting the hostname in the url */ + 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/")) { /* need to rewrite it */ *url = tor_malloc(s - start + 5); strcpy(*url,"/tor"); diff --git a/src/or/or.h b/src/or/or.h index 5c14e4d69..e8a4355ed 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -894,7 +894,12 @@ typedef struct { allowed to sign directories. */ struct config_line_t *RendConfigLines; /**< List of configuration lines * for rendezvous services. */ - char *ContactInfo; /** Contact info to be published in the directory */ + char *ContactInfo; /**< Contact info to be published in the directory */ + + char *HttpProxy; /**< hostname[:port] to use as http proxy, if any */ + uint32_t HttpProxyAddr; /**< Parsed IPv4 addr for http proxy, if any */ + uint16_t HttpProxyPort; /**< Parsed port for http proxy, if any */ + } or_options_t; /* XXX are these good enough defaults? */ |