aboutsummaryrefslogtreecommitdiff
path: root/src/or/directory.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/directory.c')
-rw-r--r--src/or/directory.c179
1 files changed, 168 insertions, 11 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index fdfb3391a8..ba6d38c426 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3,6 +3,8 @@
* Copyright (c) 2007-2016, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+#define DIRECTORY_PRIVATE
+
#include "or.h"
#include "backtrace.h"
#include "buffers.h"
@@ -16,6 +18,8 @@
#include "dirvote.h"
#include "entrynodes.h"
#include "geoip.h"
+#include "hs_cache.h"
+#include "hs_common.h"
#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
@@ -2385,10 +2389,10 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
conn->identity_digest, \
reason) )
#define SEND_HS_DESC_FAILED_CONTENT() ( \
- control_event_hs_descriptor_content(conn->rend_data->onion_address, \
- conn->requested_resource, \
- conn->identity_digest, \
- NULL) )
+ control_event_hs_descriptor_content(rend_data_get_address(conn->rend_data), \
+ conn->requested_resource, \
+ conn->identity_digest, \
+ NULL) )
tor_assert(conn->rend_data);
log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
"(%s))",
@@ -2461,7 +2465,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
#define SEND_HS_DESC_UPLOAD_FAILED_EVENT(reason) ( \
control_event_hs_descriptor_upload_failed( \
conn->identity_digest, \
- conn->rend_data->onion_address, \
+ rend_data_get_address(conn->rend_data), \
reason) )
log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
"(%s))",
@@ -2475,7 +2479,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
"Uploading rendezvous descriptor: finished with status "
"200 (%s)", escaped(reason));
control_event_hs_descriptor_uploaded(conn->identity_digest,
- conn->rend_data->onion_address);
+ rend_data_get_address(conn->rend_data));
rend_service_desc_has_uploaded(conn->rend_data);
break;
case 400:
@@ -2586,7 +2590,8 @@ connection_dir_about_to_close(dir_connection_t *dir_conn)
* refetching is unnecessary.) */
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
dir_conn->rend_data &&
- strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
+ strlen(rend_data_get_address(dir_conn->rend_data)) ==
+ REND_SERVICE_ID_LEN_BASE32)
rend_client_refetch_v2_renddesc(dir_conn->rend_data);
}
@@ -2806,8 +2811,8 @@ static int handle_get_descriptor(dir_connection_t *conn,
const get_handler_args_t *args);
static int handle_get_keys(dir_connection_t *conn,
const get_handler_args_t *args);
-static int handle_get_rendezvous2(dir_connection_t *conn,
- const get_handler_args_t *args);
+static int handle_get_hs_descriptor_v2(dir_connection_t *conn,
+ const get_handler_args_t *args);
static int handle_get_robots(dir_connection_t *conn,
const get_handler_args_t *args);
static int handle_get_networkstatus_bridges(dir_connection_t *conn,
@@ -2823,7 +2828,8 @@ static const url_table_ent_t url_table[] = {
{ "/tor/server/", 1, handle_get_descriptor },
{ "/tor/extra/", 1, handle_get_descriptor },
{ "/tor/keys/", 1, handle_get_keys },
- { "/tor/rendezvous2/", 1, handle_get_rendezvous2 },
+ { "/tor/rendezvous2/", 1, handle_get_hs_descriptor_v2 },
+ { "/tor/hs/3/", 1, handle_get_hs_descriptor_v3 },
{ "/tor/robots.txt", 0, handle_get_robots },
{ "/tor/networkstatus-bridges", 0, handle_get_networkstatus_bridges },
{ NULL, 0, NULL },
@@ -3391,7 +3397,8 @@ handle_get_keys(dir_connection_t *conn, const get_handler_args_t *args)
/** Helper function for GET /tor/rendezvous2/
*/
static int
-handle_get_rendezvous2(dir_connection_t *conn, const get_handler_args_t *args)
+handle_get_hs_descriptor_v2(dir_connection_t *conn,
+ const get_handler_args_t *args)
{
const char *url = args->url;
if (connection_dir_is_encrypted(conn)) {
@@ -3425,6 +3432,50 @@ handle_get_rendezvous2(dir_connection_t *conn, const get_handler_args_t *args)
return 0;
}
+/** Helper function for GET /tor/hs/3/<z>. Only for version 3.
+ */
+STATIC int
+handle_get_hs_descriptor_v3(dir_connection_t *conn,
+ const get_handler_args_t *args)
+{
+ int retval;
+ const char *desc_str = NULL;
+ const char *pubkey_str = NULL;
+ const char *url = args->url;
+
+ /* Don't serve v3 descriptors if next gen onion service is disabled. */
+ if (!hs_v3_protocol_is_enabled()) {
+ /* 404 is used for an unrecognized URL so send back the same. */
+ write_http_status_line(conn, 404, "Not found");
+ goto done;
+ }
+
+ /* Reject unencrypted dir connections */
+ if (!connection_dir_is_encrypted(conn)) {
+ write_http_status_line(conn, 404, "Not found");
+ goto done;
+ }
+
+ /* After the path prefix follows the base64 encoded blinded pubkey which we
+ * use to get the descriptor from the cache. Skip the prefix and get the
+ * pubkey. */
+ tor_assert(!strcmpstart(url, "/tor/hs/3/"));
+ pubkey_str = url + strlen("/tor/hs/3/");
+ retval = hs_cache_lookup_as_dir(HS_VERSION_THREE,
+ pubkey_str, &desc_str);
+ if (retval < 0) {
+ write_http_status_line(conn, 404, "Not found");
+ goto done;
+ }
+
+ /* Found requested descriptor! Pass it to this nice client. */
+ write_http_response_header(conn, strlen(desc_str), 0, 0);
+ connection_write_to_buf(desc_str, strlen(desc_str), TO_CONN(conn));
+
+ done:
+ return 0;
+}
+
/** Helper function for GET /tor/networkstatus-bridges
*/
static int
@@ -3480,6 +3531,90 @@ handle_get_robots(dir_connection_t *conn, const get_handler_args_t *args)
return 0;
}
+/* Given the <b>url</b> from a POST request, try to extract the version number
+ * using the provided <b>prefix</b>. The version should be after the prefix and
+ * ending with the seperator "/". For instance:
+ * /tor/hs/3/publish
+ *
+ * On success, <b>end_pos</b> points to the position right after the version
+ * was found. On error, it is set to NULL.
+ *
+ * Return version on success else negative value. */
+STATIC int
+parse_hs_version_from_post(const char *url, const char *prefix,
+ const char **end_pos)
+{
+ int ok;
+ unsigned long version;
+ const char *start;
+ char *end = NULL;
+
+ tor_assert(url);
+ tor_assert(prefix);
+ tor_assert(end_pos);
+
+ /* Check if the prefix does start the url. */
+ if (strcmpstart(url, prefix)) {
+ goto err;
+ }
+ /* Move pointer to the end of the prefix string. */
+ start = url + strlen(prefix);
+ /* Try this to be the HS version and if we are still at the separator, next
+ * will be move to the right value. */
+ version = tor_parse_long(start, 10, 0, INT_MAX, &ok, &end);
+ if (!ok) {
+ goto err;
+ }
+
+ *end_pos = end;
+ return (int) version;
+ err:
+ *end_pos = NULL;
+ return -1;
+}
+
+/* Handle the POST request for a hidden service descripror. The request is in
+ * <b>url</b>, the body of the request is in <b>body</b>. Return 200 on success
+ * else return 400 indicating a bad request. */
+STATIC int
+handle_post_hs_descriptor(const char *url, const char *body)
+{
+ int version;
+ const char *end_pos;
+
+ tor_assert(url);
+ tor_assert(body);
+
+ version = parse_hs_version_from_post(url, "/tor/hs/", &end_pos);
+ if (version < 0) {
+ goto err;
+ }
+
+ /* We have a valid version number, now make sure it's a publish request. Use
+ * the end position just after the version and check for the command. */
+ if (strcmpstart(end_pos, "/publish")) {
+ goto err;
+ }
+
+ switch (version) {
+ case HS_VERSION_THREE:
+ if (hs_cache_store_as_dir(body) < 0) {
+ goto err;
+ }
+ log_info(LD_REND, "Publish request for HS descriptor handled "
+ "successfully.");
+ break;
+ default:
+ /* Unsupported version, return a bad request. */
+ goto err;
+ }
+
+ return 200;
+ err:
+ /* Bad request. */
+ return 400;
+}
+
/** Helper function: called when a dirserver gets a complete HTTP POST
* request. Look for an uploaded server descriptor or rendezvous
* service descriptor. On finding one, process it and write a
@@ -3524,6 +3659,28 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
goto done;
}
+ /* Handle HS descriptor publish request. */
+ /* XXX: This should be disabled with a consensus param until we want to
+ * the prop224 be deployed and thus use. */
+ if (connection_dir_is_encrypted(conn) && !strcmpstart(url, "/tor/hs/")) {
+ const char *msg = "HS descriptor stored successfully.";
+ /* Don't accept v3 and onward publish request if next gen onion service is
+ * disabled. */
+ if (!hs_v3_protocol_is_enabled()) {
+ /* 404 is used for an unrecognized URL so send back the same. */
+ write_http_status_line(conn, 404, "Not found");
+ goto done;
+ }
+
+ /* We most probably have a publish request for an HS descriptor. */
+ int code = handle_post_hs_descriptor(url, body);
+ if (code != 200) {
+ msg = "Invalid HS descriptor. Rejected.";
+ }
+ write_http_status_line(conn, code, msg);
+ goto done;
+ }
+
if (!authdir_mode(options)) {
/* we just provide cached directories; we don't want to
* receive anything. */