Loading src/or/control.c +192 −18 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ #include "nodelist.h" #include "policies.h" #include "reasons.h" #include "rendclient.h" #include "rendcommon.h" #include "rephist.h" #include "router.h" #include "routerlist.h" Loading Loading @@ -159,6 +161,8 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len, static int handle_control_usefeature(control_connection_t *conn, uint32_t len, const char *body); static int handle_control_hsfetch(control_connection_t *conn, uint32_t len, const char *body); static int write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len); static void orconn_target_get_name(char *buf, size_t len, Loading Loading @@ -943,6 +947,7 @@ static const struct control_event_t control_event_table[] = { { EVENT_CIRC_BANDWIDTH_USED, "CIRC_BW" }, { EVENT_TRANSPORT_LAUNCHED, "TRANSPORT_LAUNCHED" }, { EVENT_HS_DESC, "HS_DESC" }, { EVENT_HS_DESC_CONTENT, "HS_DESC_CONTENT" }, { 0, NULL }, }; Loading Loading @@ -3276,6 +3281,113 @@ handle_control_dropguards(control_connection_t *conn, return 0; } /** Implementation for the HSFETCH command. */ static int handle_control_hsfetch(control_connection_t *conn, uint32_t len, const char *body) { int i; char digest[DIGEST_LEN], *hsaddress = NULL, *arg1 = NULL, *desc_id = NULL; smartlist_t *args = NULL, *hsdirs = NULL; (void) len; /* body is nul-terminated; it's safe to ignore the length */ static const char *hsfetch_command = "HSFETCH"; static const char *v2_str = "v2-"; const size_t v2_str_len = strlen(v2_str); rend_data_t *rend_query = NULL; /* Make sure we have at least one argument, the HSAddress. */ args = getargs_helper(hsfetch_command, conn, body, 1, -1); if (!args) { goto exit; } /* Extract the first argument (either HSAddress or DescID). */ arg1 = smartlist_get(args, 0); /* Test if it's an HS address without the .onion part. */ if (rend_valid_service_id(arg1)) { hsaddress = arg1; } else if (strcmpstart(arg1, v2_str) == 0 && rend_valid_descriptor_id(arg1 + v2_str_len) && base32_decode(digest, sizeof(digest), arg1 + v2_str_len, REND_DESC_ID_V2_LEN_BASE32) == 0) { /* We have a well formed version 2 descriptor ID. Keep the decoded value * of the id. */ desc_id = digest; } else { connection_printf_to_buf(conn, "513 Unrecognized \"%s\"\r\n", arg1); goto done; } static const char *opt_server = "SERVER="; /* Skip first argument because it's the HSAddress or DescID. */ for (i = 1; i < smartlist_len(args); ++i) { const char *arg = smartlist_get(args, i); const node_t *node; if (!strcasecmpstart(arg, opt_server)) { const char *server; server = arg + strlen(opt_server); node = node_get_by_hex_id(server); if (!node) { connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n", server); goto done; } if (!hsdirs) { /* Stores routerstatus_t object for each specified server. */ hsdirs = smartlist_new(); } /* Valid server, add it to our local list. */ smartlist_add(hsdirs, node->rs); } else { connection_printf_to_buf(conn, "513 Unexpected argument \"%s\"\r\n", arg); goto done; } } rend_query = tor_malloc_zero(sizeof(*rend_query)); if (hsaddress) { strncpy(rend_query->onion_address, hsaddress, sizeof(rend_query->onion_address)); } else if (desc_id) { /* Using a descriptor ID, we force the user to provide at least one * hsdir server using the SERVER= option. */ if (!hsdirs || !smartlist_len(hsdirs)) { connection_printf_to_buf(conn, "512 %s option is required\r\n", opt_server); goto done; } memcpy(rend_query->descriptor_id, desc_id, sizeof(rend_query->descriptor_id)); } else { /* We can't get in here because of the first argument check. */ tor_assert(0); } /* We are about to trigger HSDir fetch so send the OK now because after * that 650 event(s) are possible so better to have the 250 OK before them * to avoid out of order replies. */ send_control_done(conn); /* Trigger the fetch using the built rend query and possibly a list of HS * directory to use. This function ignores the client cache thus this will * always send a fetch command. */ rend_client_fetch_v2_desc(rend_query, hsdirs); done: SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); smartlist_free(args); /* Contains data pointer that we don't own thus no cleanup. */ smartlist_free(hsdirs); tor_free(rend_query); exit: return 0; } /** Called when <b>conn</b> has no more bytes left on its outbuf. */ int connection_control_finished_flushing(control_connection_t *conn) Loading Loading @@ -3573,6 +3685,9 @@ connection_control_process_inbuf(control_connection_t *conn) } else if (!strcasecmp(conn->incoming_cmd, "DROPGUARDS")) { if (handle_control_dropguards(conn, cmd_data_len, args)) return -1; } else if (!strcasecmp(conn->incoming_cmd, "HSFETCH")) { if (handle_control_hsfetch(conn, cmd_data_len, args)) return -1; } else { connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n", conn->incoming_cmd); Loading Loading @@ -5241,6 +5356,31 @@ node_describe_longname_by_id,(const char *id_digest)) return longname; } /** Return either the onion address if the given pointer is a non empty * string else the unknown string. */ static const char * rend_hsaddress_str_or_unknown(const char *onion_address) { static const char *str_unknown = "UNKNOWN"; const char *str_ret = str_unknown; /* No valid pointer, unknown it is. */ if (!onion_address) { goto end; } /* Empty onion address thus we don't know, unknown it is. */ if (onion_address[0] == '\0') { goto end; } /* All checks are good so return the given onion address. */ str_ret = onion_address; end: return str_ret; } /** send HS_DESC requested event. * * <b>rend_query</b> is used to fetch requested onion address and auth type. Loading @@ -5261,7 +5401,7 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query, send_control_event(EVENT_HS_DESC, ALL_FORMATS, "650 HS_DESC REQUESTED %s %s %s %s\r\n", rend_query->onion_address, rend_hsaddress_str_or_unknown(rend_query->onion_address), rend_auth_type_to_string(rend_query->auth_type), node_describe_longname_by_id(id_digest), desc_id_base32); Loading @@ -5277,15 +5417,16 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query, */ void control_event_hs_descriptor_receive_end(const char *action, const rend_data_t *rend_query, const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason) { char *reason_field = NULL; if (!action || !rend_query || !id_digest) { log_warn(LD_BUG, "Called with action==%p, rend_query==%p, " "id_digest==%p", action, rend_query, id_digest); if (!action || !id_digest || !onion_address) { log_warn(LD_BUG, "Called with action==%p, id_digest==%p " "onion_address==%p", action, id_digest, onion_address); return; } Loading @@ -5296,8 +5437,8 @@ control_event_hs_descriptor_receive_end(const char *action, send_control_event(EVENT_HS_DESC, ALL_FORMATS, "650 HS_DESC %s %s %s %s%s\r\n", action, rend_query->onion_address, rend_auth_type_to_string(rend_query->auth_type), rend_hsaddress_str_or_unknown(onion_address), rend_auth_type_to_string(auth_type), node_describe_longname_by_id(id_digest), reason_field ? reason_field : ""); Loading @@ -5309,16 +5450,16 @@ control_event_hs_descriptor_receive_end(const char *action, * called when a we successfully received a hidden service descriptor. */ void control_event_hs_descriptor_received(const rend_data_t *rend_query, control_event_hs_descriptor_received(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest) { if (!rend_query || !id_digest) { log_warn(LD_BUG, "Called with rend_query==%p, id_digest==%p", rend_query, id_digest); if (!id_digest) { log_warn(LD_BUG, "Called with id_digest==%p", id_digest); return; } control_event_hs_descriptor_receive_end("RECEIVED", rend_query, id_digest, NULL); control_event_hs_descriptor_receive_end("RECEIVED", onion_address, auth_type, id_digest, NULL); } /** Send HS_DESC event to inform controller that query <b>rend_query</b> Loading @@ -5327,19 +5468,52 @@ control_event_hs_descriptor_received(const rend_data_t *rend_query, * field. */ void control_event_hs_descriptor_failed(const rend_data_t *rend_query, control_event_hs_descriptor_failed(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason) { if (!rend_query || !id_digest) { log_warn(LD_BUG, "Called with rend_query==%p, id_digest==%p", rend_query, id_digest); if (!id_digest) { log_warn(LD_BUG, "Called with id_digest==%p", id_digest); return; } control_event_hs_descriptor_receive_end("FAILED", rend_query, control_event_hs_descriptor_receive_end("FAILED", onion_address, auth_type, id_digest, reason); } /** send HS_DESC_CONTENT event after completion of a successful fetch from * hs directory. */ void control_event_hs_descriptor_content(const char *onion_address, const char *desc_id, const char *hsdir_id_digest, const char *content) { static const char *event_name = "HS_DESC_CONTENT"; char *esc_content = NULL; if (!onion_address || !desc_id || !hsdir_id_digest) { log_warn(LD_BUG, "Called with onion_address==%p, desc_id==%p, " "hsdir_id_digest==%p", onion_address, desc_id, hsdir_id_digest); return; } if (content == NULL) { /* Point it to empty content so it can still be escaped. */ content = ""; } write_escaped_data(content, strlen(content), &esc_content); send_control_event(EVENT_HS_DESC_CONTENT, ALL_FORMATS, "650+%s %s %s %s\r\n%s650 OK\r\n", event_name, rend_hsaddress_str_or_unknown(onion_address), desc_id, node_describe_longname_by_id(hsdir_id_digest), esc_content); tor_free(esc_content); } /** Free any leftover allocated memory of the control.c subsystem. */ void control_free_all(void) Loading src/or/control.h +16 −8 Original line number Diff line number Diff line Loading @@ -107,14 +107,21 @@ void control_event_hs_descriptor_requested(const rend_data_t *rend_query, const char *desc_id_base32, const char *hs_dir); void control_event_hs_descriptor_receive_end(const char *action, const rend_data_t *rend_query, const char *hs_dir, const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason); void control_event_hs_descriptor_received(const rend_data_t *rend_query, const char *hs_dir); void control_event_hs_descriptor_failed(const rend_data_t *rend_query, const char *hs_dir, void control_event_hs_descriptor_received(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest); void control_event_hs_descriptor_failed(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason); void control_event_hs_descriptor_content(const char *onion_address, const char *desc_id, const char *hsdir_fp, const char *content); void control_free_all(void); Loading Loading @@ -158,7 +165,8 @@ void control_free_all(void); #define EVENT_CIRC_BANDWIDTH_USED 0x001D #define EVENT_TRANSPORT_LAUNCHED 0x0020 #define EVENT_HS_DESC 0x0021 #define EVENT_MAX_ 0x0021 #define EVENT_HS_DESC_CONTENT 0x0022 #define EVENT_MAX_ 0x0022 /* sizeof(control_connection_t.event_mask) in bits, currently a uint64_t */ #define EVENT_CAPACITY_ 0x0040 Loading src/or/directory.c +33 −5 Original line number Diff line number Diff line Loading @@ -2099,17 +2099,27 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { #define SEND_HS_DESC_FAILED_EVENT(reason) ( \ control_event_hs_descriptor_failed(conn->rend_data, \ control_event_hs_descriptor_failed(conn->rend_data->onion_address, \ conn->rend_data->auth_type, \ 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) ) tor_assert(conn->rend_data); log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d " "(%s))", (int)body_len, status_code, escaped(reason)); switch (status_code) { case 200: { rend_cache_entry_t *entry = NULL; switch (rend_cache_store_v2_desc_as_client(body, conn->requested_resource, conn->rend_data)) { conn->requested_resource, conn->rend_data, &entry)) { case RCS_BADDESC: case RCS_NOTDIR: /* Impossible */ log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. " Loading @@ -2117,25 +2127,41 @@ connection_dir_client_reached_eof(dir_connection_t *conn) /* We'll retry when connection_about_to_close_connection() * cleans this dir conn up. */ SEND_HS_DESC_FAILED_EVENT("BAD_DESC"); SEND_HS_DESC_FAILED_CONTENT(); break; case RCS_OKAY: default: { char service_id[REND_SERVICE_ID_LEN_BASE32 + 1]; /* Should never be NULL here for an OKAY returned code. */ tor_assert(entry); rend_get_service_id(entry->parsed->pk, service_id); /* success. notify pending connections about this. */ log_info(LD_REND, "Successfully fetched v2 rendezvous " "descriptor."); control_event_hs_descriptor_received(conn->rend_data, control_event_hs_descriptor_received(service_id, conn->rend_data->auth_type, conn->identity_digest); control_event_hs_descriptor_content(service_id, conn->requested_resource, conn->identity_digest, body); conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2; rend_client_desc_trynow(conn->rend_data->onion_address); rend_client_desc_trynow(service_id); memwipe(service_id, 0, sizeof(service_id)); break; } } break; } case 404: /* Not there. We'll retry when * connection_about_to_close_connection() cleans this conn up. */ log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: " "Retrying at another directory."); SEND_HS_DESC_FAILED_EVENT("NOT_FOUND"); SEND_HS_DESC_FAILED_CONTENT(); break; case 400: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " Loading @@ -2143,6 +2169,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "v2 rendezvous query? Retrying at another directory.", escaped(reason)); SEND_HS_DESC_FAILED_EVENT("QUERY_REJECTED"); SEND_HS_DESC_FAILED_CONTENT(); break; default: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " Loading @@ -2152,6 +2179,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) status_code, escaped(reason), conn->base_.address, conn->base_.port); SEND_HS_DESC_FAILED_EVENT("UNEXPECTED"); SEND_HS_DESC_FAILED_CONTENT(); break; } } Loading Loading @@ -3066,7 +3094,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, /* Handle v2 rendezvous descriptor fetch request. */ const char *descp; const char *query = url + strlen("/tor/rendezvous2/"); if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) { if (rend_valid_descriptor_id(query)) { log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'", safe_str(escaped(query))); switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) { Loading src/or/or.h +4 −0 Original line number Diff line number Diff line Loading @@ -799,6 +799,10 @@ typedef struct rend_data_t { /** Authorization type for accessing a service used by a client. */ rend_auth_type_t auth_type; /** Descriptor ID for a client request. The control port command HSFETCH * can use this. */ char descriptor_id[DIGEST_LEN]; /** Hash of the hidden service's PK used by a service. */ char rend_pk_digest[DIGEST_LEN]; Loading src/or/rendclient.c +204 −92 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
src/or/control.c +192 −18 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ #include "nodelist.h" #include "policies.h" #include "reasons.h" #include "rendclient.h" #include "rendcommon.h" #include "rephist.h" #include "router.h" #include "routerlist.h" Loading Loading @@ -159,6 +161,8 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len, static int handle_control_usefeature(control_connection_t *conn, uint32_t len, const char *body); static int handle_control_hsfetch(control_connection_t *conn, uint32_t len, const char *body); static int write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len); static void orconn_target_get_name(char *buf, size_t len, Loading Loading @@ -943,6 +947,7 @@ static const struct control_event_t control_event_table[] = { { EVENT_CIRC_BANDWIDTH_USED, "CIRC_BW" }, { EVENT_TRANSPORT_LAUNCHED, "TRANSPORT_LAUNCHED" }, { EVENT_HS_DESC, "HS_DESC" }, { EVENT_HS_DESC_CONTENT, "HS_DESC_CONTENT" }, { 0, NULL }, }; Loading Loading @@ -3276,6 +3281,113 @@ handle_control_dropguards(control_connection_t *conn, return 0; } /** Implementation for the HSFETCH command. */ static int handle_control_hsfetch(control_connection_t *conn, uint32_t len, const char *body) { int i; char digest[DIGEST_LEN], *hsaddress = NULL, *arg1 = NULL, *desc_id = NULL; smartlist_t *args = NULL, *hsdirs = NULL; (void) len; /* body is nul-terminated; it's safe to ignore the length */ static const char *hsfetch_command = "HSFETCH"; static const char *v2_str = "v2-"; const size_t v2_str_len = strlen(v2_str); rend_data_t *rend_query = NULL; /* Make sure we have at least one argument, the HSAddress. */ args = getargs_helper(hsfetch_command, conn, body, 1, -1); if (!args) { goto exit; } /* Extract the first argument (either HSAddress or DescID). */ arg1 = smartlist_get(args, 0); /* Test if it's an HS address without the .onion part. */ if (rend_valid_service_id(arg1)) { hsaddress = arg1; } else if (strcmpstart(arg1, v2_str) == 0 && rend_valid_descriptor_id(arg1 + v2_str_len) && base32_decode(digest, sizeof(digest), arg1 + v2_str_len, REND_DESC_ID_V2_LEN_BASE32) == 0) { /* We have a well formed version 2 descriptor ID. Keep the decoded value * of the id. */ desc_id = digest; } else { connection_printf_to_buf(conn, "513 Unrecognized \"%s\"\r\n", arg1); goto done; } static const char *opt_server = "SERVER="; /* Skip first argument because it's the HSAddress or DescID. */ for (i = 1; i < smartlist_len(args); ++i) { const char *arg = smartlist_get(args, i); const node_t *node; if (!strcasecmpstart(arg, opt_server)) { const char *server; server = arg + strlen(opt_server); node = node_get_by_hex_id(server); if (!node) { connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n", server); goto done; } if (!hsdirs) { /* Stores routerstatus_t object for each specified server. */ hsdirs = smartlist_new(); } /* Valid server, add it to our local list. */ smartlist_add(hsdirs, node->rs); } else { connection_printf_to_buf(conn, "513 Unexpected argument \"%s\"\r\n", arg); goto done; } } rend_query = tor_malloc_zero(sizeof(*rend_query)); if (hsaddress) { strncpy(rend_query->onion_address, hsaddress, sizeof(rend_query->onion_address)); } else if (desc_id) { /* Using a descriptor ID, we force the user to provide at least one * hsdir server using the SERVER= option. */ if (!hsdirs || !smartlist_len(hsdirs)) { connection_printf_to_buf(conn, "512 %s option is required\r\n", opt_server); goto done; } memcpy(rend_query->descriptor_id, desc_id, sizeof(rend_query->descriptor_id)); } else { /* We can't get in here because of the first argument check. */ tor_assert(0); } /* We are about to trigger HSDir fetch so send the OK now because after * that 650 event(s) are possible so better to have the 250 OK before them * to avoid out of order replies. */ send_control_done(conn); /* Trigger the fetch using the built rend query and possibly a list of HS * directory to use. This function ignores the client cache thus this will * always send a fetch command. */ rend_client_fetch_v2_desc(rend_query, hsdirs); done: SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); smartlist_free(args); /* Contains data pointer that we don't own thus no cleanup. */ smartlist_free(hsdirs); tor_free(rend_query); exit: return 0; } /** Called when <b>conn</b> has no more bytes left on its outbuf. */ int connection_control_finished_flushing(control_connection_t *conn) Loading Loading @@ -3573,6 +3685,9 @@ connection_control_process_inbuf(control_connection_t *conn) } else if (!strcasecmp(conn->incoming_cmd, "DROPGUARDS")) { if (handle_control_dropguards(conn, cmd_data_len, args)) return -1; } else if (!strcasecmp(conn->incoming_cmd, "HSFETCH")) { if (handle_control_hsfetch(conn, cmd_data_len, args)) return -1; } else { connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n", conn->incoming_cmd); Loading Loading @@ -5241,6 +5356,31 @@ node_describe_longname_by_id,(const char *id_digest)) return longname; } /** Return either the onion address if the given pointer is a non empty * string else the unknown string. */ static const char * rend_hsaddress_str_or_unknown(const char *onion_address) { static const char *str_unknown = "UNKNOWN"; const char *str_ret = str_unknown; /* No valid pointer, unknown it is. */ if (!onion_address) { goto end; } /* Empty onion address thus we don't know, unknown it is. */ if (onion_address[0] == '\0') { goto end; } /* All checks are good so return the given onion address. */ str_ret = onion_address; end: return str_ret; } /** send HS_DESC requested event. * * <b>rend_query</b> is used to fetch requested onion address and auth type. Loading @@ -5261,7 +5401,7 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query, send_control_event(EVENT_HS_DESC, ALL_FORMATS, "650 HS_DESC REQUESTED %s %s %s %s\r\n", rend_query->onion_address, rend_hsaddress_str_or_unknown(rend_query->onion_address), rend_auth_type_to_string(rend_query->auth_type), node_describe_longname_by_id(id_digest), desc_id_base32); Loading @@ -5277,15 +5417,16 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query, */ void control_event_hs_descriptor_receive_end(const char *action, const rend_data_t *rend_query, const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason) { char *reason_field = NULL; if (!action || !rend_query || !id_digest) { log_warn(LD_BUG, "Called with action==%p, rend_query==%p, " "id_digest==%p", action, rend_query, id_digest); if (!action || !id_digest || !onion_address) { log_warn(LD_BUG, "Called with action==%p, id_digest==%p " "onion_address==%p", action, id_digest, onion_address); return; } Loading @@ -5296,8 +5437,8 @@ control_event_hs_descriptor_receive_end(const char *action, send_control_event(EVENT_HS_DESC, ALL_FORMATS, "650 HS_DESC %s %s %s %s%s\r\n", action, rend_query->onion_address, rend_auth_type_to_string(rend_query->auth_type), rend_hsaddress_str_or_unknown(onion_address), rend_auth_type_to_string(auth_type), node_describe_longname_by_id(id_digest), reason_field ? reason_field : ""); Loading @@ -5309,16 +5450,16 @@ control_event_hs_descriptor_receive_end(const char *action, * called when a we successfully received a hidden service descriptor. */ void control_event_hs_descriptor_received(const rend_data_t *rend_query, control_event_hs_descriptor_received(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest) { if (!rend_query || !id_digest) { log_warn(LD_BUG, "Called with rend_query==%p, id_digest==%p", rend_query, id_digest); if (!id_digest) { log_warn(LD_BUG, "Called with id_digest==%p", id_digest); return; } control_event_hs_descriptor_receive_end("RECEIVED", rend_query, id_digest, NULL); control_event_hs_descriptor_receive_end("RECEIVED", onion_address, auth_type, id_digest, NULL); } /** Send HS_DESC event to inform controller that query <b>rend_query</b> Loading @@ -5327,19 +5468,52 @@ control_event_hs_descriptor_received(const rend_data_t *rend_query, * field. */ void control_event_hs_descriptor_failed(const rend_data_t *rend_query, control_event_hs_descriptor_failed(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason) { if (!rend_query || !id_digest) { log_warn(LD_BUG, "Called with rend_query==%p, id_digest==%p", rend_query, id_digest); if (!id_digest) { log_warn(LD_BUG, "Called with id_digest==%p", id_digest); return; } control_event_hs_descriptor_receive_end("FAILED", rend_query, control_event_hs_descriptor_receive_end("FAILED", onion_address, auth_type, id_digest, reason); } /** send HS_DESC_CONTENT event after completion of a successful fetch from * hs directory. */ void control_event_hs_descriptor_content(const char *onion_address, const char *desc_id, const char *hsdir_id_digest, const char *content) { static const char *event_name = "HS_DESC_CONTENT"; char *esc_content = NULL; if (!onion_address || !desc_id || !hsdir_id_digest) { log_warn(LD_BUG, "Called with onion_address==%p, desc_id==%p, " "hsdir_id_digest==%p", onion_address, desc_id, hsdir_id_digest); return; } if (content == NULL) { /* Point it to empty content so it can still be escaped. */ content = ""; } write_escaped_data(content, strlen(content), &esc_content); send_control_event(EVENT_HS_DESC_CONTENT, ALL_FORMATS, "650+%s %s %s %s\r\n%s650 OK\r\n", event_name, rend_hsaddress_str_or_unknown(onion_address), desc_id, node_describe_longname_by_id(hsdir_id_digest), esc_content); tor_free(esc_content); } /** Free any leftover allocated memory of the control.c subsystem. */ void control_free_all(void) Loading
src/or/control.h +16 −8 Original line number Diff line number Diff line Loading @@ -107,14 +107,21 @@ void control_event_hs_descriptor_requested(const rend_data_t *rend_query, const char *desc_id_base32, const char *hs_dir); void control_event_hs_descriptor_receive_end(const char *action, const rend_data_t *rend_query, const char *hs_dir, const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason); void control_event_hs_descriptor_received(const rend_data_t *rend_query, const char *hs_dir); void control_event_hs_descriptor_failed(const rend_data_t *rend_query, const char *hs_dir, void control_event_hs_descriptor_received(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest); void control_event_hs_descriptor_failed(const char *onion_address, rend_auth_type_t auth_type, const char *id_digest, const char *reason); void control_event_hs_descriptor_content(const char *onion_address, const char *desc_id, const char *hsdir_fp, const char *content); void control_free_all(void); Loading Loading @@ -158,7 +165,8 @@ void control_free_all(void); #define EVENT_CIRC_BANDWIDTH_USED 0x001D #define EVENT_TRANSPORT_LAUNCHED 0x0020 #define EVENT_HS_DESC 0x0021 #define EVENT_MAX_ 0x0021 #define EVENT_HS_DESC_CONTENT 0x0022 #define EVENT_MAX_ 0x0022 /* sizeof(control_connection_t.event_mask) in bits, currently a uint64_t */ #define EVENT_CAPACITY_ 0x0040 Loading
src/or/directory.c +33 −5 Original line number Diff line number Diff line Loading @@ -2099,17 +2099,27 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { #define SEND_HS_DESC_FAILED_EVENT(reason) ( \ control_event_hs_descriptor_failed(conn->rend_data, \ control_event_hs_descriptor_failed(conn->rend_data->onion_address, \ conn->rend_data->auth_type, \ 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) ) tor_assert(conn->rend_data); log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d " "(%s))", (int)body_len, status_code, escaped(reason)); switch (status_code) { case 200: { rend_cache_entry_t *entry = NULL; switch (rend_cache_store_v2_desc_as_client(body, conn->requested_resource, conn->rend_data)) { conn->requested_resource, conn->rend_data, &entry)) { case RCS_BADDESC: case RCS_NOTDIR: /* Impossible */ log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. " Loading @@ -2117,25 +2127,41 @@ connection_dir_client_reached_eof(dir_connection_t *conn) /* We'll retry when connection_about_to_close_connection() * cleans this dir conn up. */ SEND_HS_DESC_FAILED_EVENT("BAD_DESC"); SEND_HS_DESC_FAILED_CONTENT(); break; case RCS_OKAY: default: { char service_id[REND_SERVICE_ID_LEN_BASE32 + 1]; /* Should never be NULL here for an OKAY returned code. */ tor_assert(entry); rend_get_service_id(entry->parsed->pk, service_id); /* success. notify pending connections about this. */ log_info(LD_REND, "Successfully fetched v2 rendezvous " "descriptor."); control_event_hs_descriptor_received(conn->rend_data, control_event_hs_descriptor_received(service_id, conn->rend_data->auth_type, conn->identity_digest); control_event_hs_descriptor_content(service_id, conn->requested_resource, conn->identity_digest, body); conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2; rend_client_desc_trynow(conn->rend_data->onion_address); rend_client_desc_trynow(service_id); memwipe(service_id, 0, sizeof(service_id)); break; } } break; } case 404: /* Not there. We'll retry when * connection_about_to_close_connection() cleans this conn up. */ log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: " "Retrying at another directory."); SEND_HS_DESC_FAILED_EVENT("NOT_FOUND"); SEND_HS_DESC_FAILED_CONTENT(); break; case 400: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " Loading @@ -2143,6 +2169,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) "v2 rendezvous query? Retrying at another directory.", escaped(reason)); SEND_HS_DESC_FAILED_EVENT("QUERY_REJECTED"); SEND_HS_DESC_FAILED_CONTENT(); break; default: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " Loading @@ -2152,6 +2179,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) status_code, escaped(reason), conn->base_.address, conn->base_.port); SEND_HS_DESC_FAILED_EVENT("UNEXPECTED"); SEND_HS_DESC_FAILED_CONTENT(); break; } } Loading Loading @@ -3066,7 +3094,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, /* Handle v2 rendezvous descriptor fetch request. */ const char *descp; const char *query = url + strlen("/tor/rendezvous2/"); if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) { if (rend_valid_descriptor_id(query)) { log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'", safe_str(escaped(query))); switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) { Loading
src/or/or.h +4 −0 Original line number Diff line number Diff line Loading @@ -799,6 +799,10 @@ typedef struct rend_data_t { /** Authorization type for accessing a service used by a client. */ rend_auth_type_t auth_type; /** Descriptor ID for a client request. The control port command HSFETCH * can use this. */ char descriptor_id[DIGEST_LEN]; /** Hash of the hidden service's PK used by a service. */ char rend_pk_digest[DIGEST_LEN]; Loading
src/or/rendclient.c +204 −92 File changed.Preview size limit exceeded, changes collapsed. Show changes