aboutsummaryrefslogtreecommitdiff
path: root/src/or/control.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2017-12-05 19:43:23 -0500
committerNick Mathewson <nickm@torproject.org>2017-12-05 19:43:23 -0500
commite8a6a6635b26c327beca4f2a91c7ec2b2ff03cd8 (patch)
treea68dabedc8625fdb97863599df76d7705e271f26 /src/or/control.c
parent1969d573637ee6f9c539733db8405c72f0e2e4ab (diff)
parent5d4fc193f911d669151f102e5597438e8219ea81 (diff)
downloadtor-e8a6a6635b26c327beca4f2a91c7ec2b2ff03cd8.tar.gz
tor-e8a6a6635b26c327beca4f2a91c7ec2b2ff03cd8.zip
Merge branch 'dgoulet_ticket20699_033_01'
Diffstat (limited to 'src/or/control.c')
-rw-r--r--src/or/control.c539
1 files changed, 403 insertions, 136 deletions
diff --git a/src/or/control.c b/src/or/control.c
index 0d462b2d7d..f1960b8849 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -58,7 +58,9 @@
#include "entrynodes.h"
#include "geoip.h"
#include "hibernate.h"
+#include "hs_cache.h"
#include "hs_common.h"
+#include "hs_control.h"
#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
@@ -2014,36 +2016,89 @@ getinfo_helper_dir(control_connection_t *control_conn,
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
} else if (!strcmpstart(question, "hs/client/desc/id/")) {
- rend_cache_entry_t *e = NULL;
+ hostname_type_t addr_type;
question += strlen("hs/client/desc/id/");
- if (strlen(question) != REND_SERVICE_ID_LEN_BASE32) {
+ if (rend_valid_v2_service_id(question)) {
+ addr_type = ONION_V2_HOSTNAME;
+ } else if (hs_address_is_valid(question)) {
+ addr_type = ONION_V3_HOSTNAME;
+ } else {
*errmsg = "Invalid address";
return -1;
}
- if (!rend_cache_lookup_entry(question, -1, &e)) {
- /* Descriptor found in cache */
- *answer = tor_strdup(e->desc);
+ if (addr_type == ONION_V2_HOSTNAME) {
+ rend_cache_entry_t *e = NULL;
+ if (!rend_cache_lookup_entry(question, -1, &e)) {
+ /* Descriptor found in cache */
+ *answer = tor_strdup(e->desc);
+ } else {
+ *errmsg = "Not found in cache";
+ return -1;
+ }
} else {
- *errmsg = "Not found in cache";
- return -1;
+ ed25519_public_key_t service_pk;
+ const char *desc;
+
+ /* The check before this if/else makes sure of this. */
+ tor_assert(addr_type == ONION_V3_HOSTNAME);
+
+ if (hs_parse_address(question, &service_pk, NULL, NULL) < 0) {
+ *errmsg = "Invalid v3 address";
+ return -1;
+ }
+
+ desc = hs_cache_lookup_encoded_as_client(&service_pk);
+ if (desc) {
+ *answer = tor_strdup(desc);
+ } else {
+ *errmsg = "Not found in cache";
+ return -1;
+ }
}
} else if (!strcmpstart(question, "hs/service/desc/id/")) {
- rend_cache_entry_t *e = NULL;
+ hostname_type_t addr_type;
question += strlen("hs/service/desc/id/");
- if (strlen(question) != REND_SERVICE_ID_LEN_BASE32) {
+ if (rend_valid_v2_service_id(question)) {
+ addr_type = ONION_V2_HOSTNAME;
+ } else if (hs_address_is_valid(question)) {
+ addr_type = ONION_V3_HOSTNAME;
+ } else {
*errmsg = "Invalid address";
return -1;
}
+ rend_cache_entry_t *e = NULL;
- if (!rend_cache_lookup_v2_desc_as_service(question, &e)) {
- /* Descriptor found in cache */
- *answer = tor_strdup(e->desc);
+ if (addr_type == ONION_V2_HOSTNAME) {
+ if (!rend_cache_lookup_v2_desc_as_service(question, &e)) {
+ /* Descriptor found in cache */
+ *answer = tor_strdup(e->desc);
+ } else {
+ *errmsg = "Not found in cache";
+ return -1;
+ }
} else {
- *errmsg = "Not found in cache";
- return -1;
+ ed25519_public_key_t service_pk;
+ char *desc;
+
+ /* The check before this if/else makes sure of this. */
+ tor_assert(addr_type == ONION_V3_HOSTNAME);
+
+ if (hs_parse_address(question, &service_pk, NULL, NULL) < 0) {
+ *errmsg = "Invalid v3 address";
+ return -1;
+ }
+
+ desc = hs_service_lookup_current_desc(&service_pk);
+ if (desc) {
+ /* Newly allocated string, we have ownership. */
+ *answer = desc;
+ } else {
+ *errmsg = "Not found in cache";
+ return -1;
+ }
}
} else if (!strcmpstart(question, "md/id/")) {
const node_t *node = node_get_by_hex_id(question+strlen("md/id/"), 0);
@@ -2624,9 +2679,16 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
}
}
- if (circ->rend_data != NULL) {
- smartlist_add_asprintf(descparts, "REND_QUERY=%s",
- rend_data_get_address(circ->rend_data));
+ if (circ->rend_data != NULL || circ->hs_ident != NULL) {
+ char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
+ const char *onion_address;
+ if (circ->rend_data) {
+ onion_address = rend_data_get_address(circ->rend_data);
+ } else {
+ hs_build_address(&circ->hs_ident->identity_pk, HS_VERSION_THREE, addr);
+ onion_address = addr;
+ }
+ smartlist_add_asprintf(descparts, "REND_QUERY=%s", onion_address);
}
{
@@ -4277,9 +4339,11 @@ handle_control_hspost(control_connection_t *conn,
const char *body)
{
static const char *opt_server = "SERVER=";
+ static const char *opt_hsaddress = "HSADDRESS=";
smartlist_t *hs_dirs = NULL;
const char *encoded_desc = body;
size_t encoded_desc_len = len;
+ const char *onion_address = NULL;
char *cp = memchr(body, '\n', len);
if (cp == NULL) {
@@ -4309,15 +4373,16 @@ handle_control_hspost(control_connection_t *conn,
server);
goto done;
}
- if (!node->rs->is_hs_dir) {
- connection_printf_to_buf(conn, "552 Server \"%s\" is not a HSDir"
- "\r\n", server);
- goto done;
- }
/* Valid server, add it to our local list. */
if (!hs_dirs)
hs_dirs = smartlist_new();
smartlist_add(hs_dirs, node->rs);
+ } else if (!strcasecmpstart(arg, opt_hsaddress)) {
+ if (!hs_address_is_valid(arg)) {
+ connection_printf_to_buf(conn, "512 Malformed onion address\r\n");
+ goto done;
+ }
+ onion_address = arg;
} else {
connection_printf_to_buf(conn, "512 Unexpected argument \"%s\"\r\n",
arg);
@@ -4326,6 +4391,19 @@ handle_control_hspost(control_connection_t *conn,
} SMARTLIST_FOREACH_END(arg);
}
+ /* Handle the v3 case. */
+ if (onion_address) {
+ char *desc_str = NULL;
+ read_escaped_data(encoded_desc, encoded_desc_len, &desc_str);
+ if (hs_control_hspost_command(desc_str, onion_address, hs_dirs) < 0) {
+ connection_printf_to_buf(conn, "554 Invalid descriptor\r\n");
+ }
+ tor_free(desc_str);
+ goto done;
+ }
+
+ /* From this point on, it is only v2. */
+
/* Read the dot encoded descriptor, and parse it. */
rend_encoded_v2_service_descriptor_t *desc =
tor_malloc_zero(sizeof(rend_encoded_v2_service_descriptor_t));
@@ -4370,6 +4448,52 @@ handle_control_hspost(control_connection_t *conn,
return 0;
}
+/* Helper function for ADD_ONION that adds an ephemeral service depending on
+ * the given hs_version.
+ *
+ * The secret key in pk depends on the hs_version. The ownership of the key
+ * used in pk is given to the HS subsystem so the caller must stop accessing
+ * it after.
+ *
+ * The port_cfgs is a list of service port. Ownership transfered to service.
+ * The max_streams refers to the MaxStreams= key.
+ * The max_streams_close_circuit refers to the MaxStreamsCloseCircuit key.
+ * The auth_type is the authentication type of the clients in auth_clients.
+ * The ownership of that list is transfered to the service.
+ *
+ * On success (RSAE_OKAY), the address_out points to a newly allocated string
+ * containing the onion address without the .onion part. On error, address_out
+ * is untouched. */
+static hs_service_add_ephemeral_status_t
+add_onion_helper_add_service(int hs_version,
+ add_onion_secret_key_t *pk,
+ smartlist_t *port_cfgs, int max_streams,
+ int max_streams_close_circuit, int auth_type,
+ smartlist_t *auth_clients, char **address_out)
+{
+ hs_service_add_ephemeral_status_t ret;
+
+ tor_assert(pk);
+ tor_assert(port_cfgs);
+ tor_assert(address_out);
+
+ switch (hs_version) {
+ case HS_VERSION_TWO:
+ ret = rend_service_add_ephemeral(pk->v2, port_cfgs, max_streams,
+ max_streams_close_circuit, auth_type,
+ auth_clients, address_out);
+ break;
+ case HS_VERSION_THREE:
+ ret = hs_service_add_ephemeral(pk->v3, port_cfgs, max_streams,
+ max_streams_close_circuit, address_out);
+ break;
+ default:
+ tor_assert_unreached();
+ }
+
+ return ret;
+}
+
/** Called when we get a ADD_ONION command; parse the body, and set up
* the new ephemeral Onion Service. */
static int
@@ -4551,15 +4675,15 @@ handle_control_add_onion(control_connection_t *conn,
}
/* Parse the "keytype:keyblob" argument. */
- crypto_pk_t *pk = NULL;
+ int hs_version = 0;
+ add_onion_secret_key_t pk;
const char *key_new_alg = NULL;
char *key_new_blob = NULL;
char *err_msg = NULL;
- pk = add_onion_helper_keyarg(smartlist_get(args, 0), discard_pk,
- &key_new_alg, &key_new_blob,
- &err_msg);
- if (!pk) {
+ if (add_onion_helper_keyarg(smartlist_get(args, 0), discard_pk,
+ &key_new_alg, &key_new_blob, &pk, &hs_version,
+ &err_msg) < 0) {
if (err_msg) {
connection_write_str_to_buf(err_msg, conn);
tor_free(err_msg);
@@ -4568,16 +4692,23 @@ handle_control_add_onion(control_connection_t *conn,
}
tor_assert(!err_msg);
+ /* Hidden service version 3 don't have client authentication support so if
+ * ClientAuth was given, send back an error. */
+ if (hs_version == HS_VERSION_THREE && auth_clients) {
+ connection_printf_to_buf(conn, "513 ClientAuth not supported\r\n");
+ goto out;
+ }
+
/* Create the HS, using private key pk, client authentication auth_type,
* the list of auth_clients, and port config port_cfg.
* rend_service_add_ephemeral() will take ownership of pk and port_cfg,
* regardless of success/failure.
*/
char *service_id = NULL;
- int ret = rend_service_add_ephemeral(pk, port_cfgs, max_streams,
- max_streams_close_circuit,
- auth_type, auth_clients,
- &service_id);
+ int ret = add_onion_helper_add_service(hs_version, &pk, port_cfgs,
+ max_streams,
+ max_streams_close_circuit, auth_type,
+ auth_clients, &service_id);
port_cfgs = NULL; /* port_cfgs is now owned by the rendservice code. */
auth_clients = NULL; /* so is auth_clients */
switch (ret) {
@@ -4670,9 +4801,10 @@ handle_control_add_onion(control_connection_t *conn,
* Note: The error messages returned are deliberately vague to avoid echoing
* key material.
*/
-STATIC crypto_pk_t *
+STATIC int
add_onion_helper_keyarg(const char *arg, int discard_pk,
const char **key_new_alg_out, char **key_new_blob_out,
+ add_onion_secret_key_t *decoded_key, int *hs_version,
char **err_msg_out)
{
smartlist_t *key_args = smartlist_new();
@@ -4680,7 +4812,7 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
const char *key_new_alg = NULL;
char *key_new_blob = NULL;
char *err_msg = NULL;
- int ok = 0;
+ int ret = -1;
smartlist_split_string(key_args, arg, ":", SPLIT_IGNORE_BLANK, 0);
if (smartlist_len(key_args) != 2) {
@@ -4692,6 +4824,7 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
static const char *key_type_new = "NEW";
static const char *key_type_best = "BEST";
static const char *key_type_rsa1024 = "RSA1024";
+ static const char *key_type_ed25519_v3 = "ED25519-V3";
const char *key_type = smartlist_get(key_args, 0);
const char *key_blob = smartlist_get(key_args, 1);
@@ -4704,9 +4837,23 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
goto err;
}
if (crypto_pk_num_bits(pk) != PK_BYTES*8) {
+ crypto_pk_free(pk);
err_msg = tor_strdup("512 Invalid RSA key size\r\n");
goto err;
}
+ decoded_key->v2 = pk;
+ *hs_version = HS_VERSION_TWO;
+ } else if (!strcasecmp(key_type_ed25519_v3, key_type)) {
+ /* "ED25519-V3:<Base64 Blob>" - Loading a pre-existing ed25519 key. */
+ ed25519_secret_key_t *sk = tor_malloc_zero(sizeof(*sk));
+ if (base64_decode((char *) sk->seckey, sizeof(sk->seckey), key_blob,
+ strlen(key_blob)) != sizeof(sk->seckey)) {
+ tor_free(sk);
+ err_msg = tor_strdup("512 Failed to decode ED25519-V3 key\r\n");
+ goto err;
+ }
+ decoded_key->v3 = sk;
+ *hs_version = HS_VERSION_THREE;
} else if (!strcasecmp(key_type_new, key_type)) {
/* "NEW:<Algorithm>" - Generating a new key, blob as algorithm. */
if (!strcasecmp(key_type_rsa1024, key_blob) ||
@@ -4720,12 +4867,38 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
}
if (!discard_pk) {
if (crypto_pk_base64_encode(pk, &key_new_blob)) {
+ crypto_pk_free(pk);
tor_asprintf(&err_msg, "551 Failed to encode %s key\r\n",
key_type_rsa1024);
goto err;
}
key_new_alg = key_type_rsa1024;
}
+ decoded_key->v2 = pk;
+ *hs_version = HS_VERSION_TWO;
+ } else if (!strcasecmp(key_type_ed25519_v3, key_blob)) {
+ ed25519_secret_key_t *sk = tor_malloc_zero(sizeof(*sk));
+ if (ed25519_secret_key_generate(sk, 1) < 0) {
+ tor_free(sk);
+ tor_asprintf(&err_msg, "551 Failed to generate %s key\r\n",
+ key_type_ed25519_v3);
+ goto err;
+ }
+ if (!discard_pk) {
+ ssize_t len = base64_encode_size(sizeof(sk->seckey), 0) + 1;
+ key_new_blob = tor_malloc_zero(len);
+ if (base64_encode(key_new_blob, len, (const char *) sk->seckey,
+ sizeof(sk->seckey), 0) != (len - 1)) {
+ tor_free(sk);
+ tor_free(key_new_blob);
+ tor_asprintf(&err_msg, "551 Failed to encode %s key\r\n",
+ key_type_ed25519_v3);
+ goto err;
+ }
+ key_new_alg = key_type_ed25519_v3;
+ }
+ decoded_key->v3 = sk;
+ *hs_version = HS_VERSION_THREE;
} else {
err_msg = tor_strdup("513 Invalid key type\r\n");
goto err;
@@ -4736,8 +4909,7 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
}
/* Succeded in loading or generating a private key. */
- tor_assert(pk);
- ok = 1;
+ ret = 0;
err:
SMARTLIST_FOREACH(key_args, char *, cp, {
@@ -4746,10 +4918,6 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
});
smartlist_free(key_args);
- if (!ok) {
- crypto_pk_free(pk);
- pk = NULL;
- }
if (err_msg_out) {
*err_msg_out = err_msg;
} else {
@@ -4758,7 +4926,7 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
*key_new_alg_out = key_new_alg;
*key_new_blob_out = key_new_blob;
- return pk;
+ return ret;
}
/** Helper function to handle parsing a ClientAuth argument to the
@@ -4827,6 +4995,7 @@ handle_control_del_onion(control_connection_t *conn,
uint32_t len,
const char *body)
{
+ int hs_version = 0;
smartlist_t *args;
(void) len; /* body is nul-terminated; it's safe to ignore the length */
args = getargs_helper("DEL_ONION", conn, body, 1, 1);
@@ -4834,7 +5003,11 @@ handle_control_del_onion(control_connection_t *conn,
return 0;
const char *service_id = smartlist_get(args, 0);
- if (!rend_valid_v2_service_id(service_id)) {
+ if (rend_valid_v2_service_id(service_id)) {
+ hs_version = HS_VERSION_TWO;
+ } else if (hs_address_is_valid(service_id)) {
+ hs_version = HS_VERSION_THREE;
+ } else {
connection_printf_to_buf(conn, "512 Malformed Onion Service id\r\n");
goto out;
}
@@ -4861,8 +5034,20 @@ handle_control_del_onion(control_connection_t *conn,
if (onion_services == NULL) {
connection_printf_to_buf(conn, "552 Unknown Onion Service id\r\n");
} else {
- int ret = rend_service_del_ephemeral(service_id);
- if (ret) {
+ int ret = -1;
+ switch (hs_version) {
+ case HS_VERSION_TWO:
+ ret = rend_service_del_ephemeral(service_id);
+ break;
+ case HS_VERSION_THREE:
+ ret = hs_service_del_ephemeral(service_id);
+ break;
+ default:
+ /* The ret value will be -1 thus hitting the warning below. This should
+ * never happen because of the check at the start of the function. */
+ break;
+ }
+ if (ret < 0) {
/* This should *NEVER* fail, since the service is on either the
* per-control connection list, or the global one.
*/
@@ -4932,9 +5117,16 @@ connection_control_closed(control_connection_t *conn)
* The list and it's contents are scrubbed/freed in connection_free_.
*/
if (conn->ephemeral_onion_services) {
- SMARTLIST_FOREACH(conn->ephemeral_onion_services, char *, cp, {
- rend_service_del_ephemeral(cp);
- });
+ SMARTLIST_FOREACH_BEGIN(conn->ephemeral_onion_services, char *, cp) {
+ if (rend_valid_v2_service_id(cp)) {
+ rend_service_del_ephemeral(cp);
+ } else if (hs_address_is_valid(cp)) {
+ hs_service_del_ephemeral(cp);
+ } else {
+ /* An invalid .onion in our list should NEVER happen */
+ tor_fragile_assert();
+ }
+ } SMARTLIST_FOREACH_END(cp);
}
if (conn->is_owning_control_connection) {
@@ -7012,27 +7204,33 @@ rend_hsaddress_str_or_unknown(const char *onion_address)
* <b>rend_query</b> is used to fetch requested onion address and auth type.
* <b>hs_dir</b> is the description of contacting hs directory.
* <b>desc_id_base32</b> is the ID of requested hs descriptor.
+ * <b>hsdir_index</b> is the HSDir fetch index value for v3, an hex string.
*/
void
-control_event_hs_descriptor_requested(const rend_data_t *rend_query,
+control_event_hs_descriptor_requested(const char *onion_address,
+ rend_auth_type_t auth_type,
const char *id_digest,
- const char *desc_id_base32)
+ const char *desc_id,
+ const char *hsdir_index)
{
- if (!id_digest || !rend_query || !desc_id_base32) {
- log_warn(LD_BUG, "Called with rend_query==%p, "
- "id_digest==%p, desc_id_base32==%p",
- rend_query, id_digest, desc_id_base32);
+ char *hsdir_index_field = NULL;
+
+ if (BUG(!id_digest || !desc_id)) {
return;
}
+ if (hsdir_index) {
+ tor_asprintf(&hsdir_index_field, " HSDIR_INDEX=%s", hsdir_index);
+ }
+
send_control_event(EVENT_HS_DESC,
- "650 HS_DESC REQUESTED %s %s %s %s\r\n",
- rend_hsaddress_str_or_unknown(
- rend_data_get_address(rend_query)),
- rend_auth_type_to_string(
- TO_REND_DATA_V2(rend_query)->auth_type),
+ "650 HS_DESC REQUESTED %s %s %s %s%s\r\n",
+ rend_hsaddress_str_or_unknown(onion_address),
+ rend_auth_type_to_string(auth_type),
node_describe_longname_by_id(id_digest),
- desc_id_base32);
+ desc_id,
+ hsdir_index_field ? hsdir_index_field : "");
+ tor_free(hsdir_index_field);
}
/** For an HS descriptor query <b>rend_data</b>, using the
@@ -7081,89 +7279,87 @@ get_desc_id_from_query(const rend_data_t *rend_data, const char *hsdir_fp)
/** send HS_DESC CREATED event when a local service generates a descriptor.
*
- * <b>service_id</b> is the descriptor onion address.
- * <b>desc_id_base32</b> is the descriptor ID.
- * <b>replica</b> is the the descriptor replica number.
+ * <b>onion_address</b> is service address.
+ * <b>desc_id</b> is the descriptor ID.
+ * <b>replica</b> is the the descriptor replica number. If it is negative, it
+ * is ignored.
*/
void
-control_event_hs_descriptor_created(const char *service_id,
- const char *desc_id_base32,
+control_event_hs_descriptor_created(const char *onion_address,
+ const char *desc_id,
int replica)
{
- if (!service_id || !desc_id_base32) {
- log_warn(LD_BUG, "Called with service_digest==%p, "
- "desc_id_base32==%p", service_id, desc_id_base32);
+ char *replica_field = NULL;
+
+ if (BUG(!onion_address || !desc_id)) {
return;
}
+ if (replica >= 0) {
+ tor_asprintf(&replica_field, " REPLICA=%d", replica);
+ }
+
send_control_event(EVENT_HS_DESC,
- "650 HS_DESC CREATED %s UNKNOWN UNKNOWN %s "
- "REPLICA=%d\r\n",
- service_id,
- desc_id_base32,
- replica);
+ "650 HS_DESC CREATED %s UNKNOWN UNKNOWN %s%s\r\n",
+ onion_address, desc_id,
+ replica_field ? replica_field : "");
+ tor_free(replica_field);
}
/** send HS_DESC upload event.
*
- * <b>service_id</b> is the descriptor onion address.
+ * <b>onion_address</b> is service address.
* <b>hs_dir</b> is the description of contacting hs directory.
- * <b>desc_id_base32</b> is the ID of requested hs descriptor.
+ * <b>desc_id</b> is the ID of requested hs descriptor.
*/
void
-control_event_hs_descriptor_upload(const char *service_id,
+control_event_hs_descriptor_upload(const char *onion_address,
const char *id_digest,
- const char *desc_id_base32)
+ const char *desc_id,
+ const char *hsdir_index)
{
- if (!service_id || !id_digest || !desc_id_base32) {
- log_warn(LD_BUG, "Called with service_digest==%p, "
- "desc_id_base32==%p, id_digest==%p", service_id,
- desc_id_base32, id_digest);
+ char *hsdir_index_field = NULL;
+
+ if (BUG(!onion_address || !id_digest || !desc_id)) {
return;
}
+ if (hsdir_index) {
+ tor_asprintf(&hsdir_index_field, " HSDIR_INDEX=%s", hsdir_index);
+ }
+
send_control_event(EVENT_HS_DESC,
- "650 HS_DESC UPLOAD %s UNKNOWN %s %s\r\n",
- service_id,
+ "650 HS_DESC UPLOAD %s UNKNOWN %s %s%s\r\n",
+ onion_address,
node_describe_longname_by_id(id_digest),
- desc_id_base32);
+ desc_id,
+ hsdir_index_field ? hsdir_index_field : "");
+ tor_free(hsdir_index_field);
}
/** send HS_DESC event after got response from hs directory.
*
* NOTE: this is an internal function used by following functions:
- * control_event_hs_descriptor_received
- * control_event_hs_descriptor_failed
+ * control_event_hsv2_descriptor_received
+ * control_event_hsv2_descriptor_failed
+ * control_event_hsv3_descriptor_failed
*
* So do not call this function directly.
*/
-void
-control_event_hs_descriptor_receive_end(const char *action,
- const char *onion_address,
- const rend_data_t *rend_data,
- const char *id_digest,
- const char *reason)
+static void
+event_hs_descriptor_receive_end(const char *action,
+ const char *onion_address,
+ const char *desc_id,
+ rend_auth_type_t auth_type,
+ const char *hsdir_id_digest,
+ const char *reason)
{
- char *desc_id_field = NULL;
char *reason_field = NULL;
- char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
- const char *desc_id = NULL;
- if (!action || !rend_data || !onion_address) {
- log_warn(LD_BUG, "Called with action==%p, rend_data==%p, "
- "onion_address==%p", action, rend_data, onion_address);
+ if (BUG(!action || !onion_address)) {
return;
}
- desc_id = get_desc_id_from_query(rend_data, id_digest);
- if (desc_id != NULL) {
- /* Set the descriptor ID digest to base32 so we can send it. */
- base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id,
- DIGEST_LEN);
- /* Extra whitespace is needed before the value. */
- tor_asprintf(&desc_id_field, " %s", desc_id_base32);
- }
-
if (reason) {
tor_asprintf(&reason_field, " REASON=%s", reason);
}
@@ -7172,14 +7368,13 @@ control_event_hs_descriptor_receive_end(const char *action,
"650 HS_DESC %s %s %s %s%s%s\r\n",
action,
rend_hsaddress_str_or_unknown(onion_address),
- rend_auth_type_to_string(
- TO_REND_DATA_V2(rend_data)->auth_type),
- id_digest ?
- node_describe_longname_by_id(id_digest) : "UNKNOWN",
- desc_id_field ? desc_id_field : "",
+ rend_auth_type_to_string(auth_type),
+ hsdir_id_digest ?
+ node_describe_longname_by_id(hsdir_id_digest) :
+ "UNKNOWN",
+ desc_id ? desc_id : "",
reason_field ? reason_field : "");
- tor_free(desc_id_field);
tor_free(reason_field);
}
@@ -7199,9 +7394,7 @@ control_event_hs_descriptor_upload_end(const char *action,
{
char *reason_field = NULL;
- if (!action || !id_digest) {
- log_warn(LD_BUG, "Called with action==%p, id_digest==%p", action,
- id_digest);
+ if (BUG(!action || !id_digest)) {
return;
}
@@ -7224,17 +7417,54 @@ control_event_hs_descriptor_upload_end(const char *action,
* called when we successfully received a hidden service descriptor.
*/
void
-control_event_hs_descriptor_received(const char *onion_address,
- const rend_data_t *rend_data,
- const char *id_digest)
+control_event_hsv2_descriptor_received(const char *onion_address,
+ const rend_data_t *rend_data,
+ const char *hsdir_id_digest)
{
- if (!rend_data || !id_digest || !onion_address) {
- log_warn(LD_BUG, "Called with rend_data==%p, id_digest==%p, "
- "onion_address==%p", rend_data, id_digest, onion_address);
+ char *desc_id_field = NULL;
+ const char *desc_id;
+
+ if (BUG(!rend_data || !hsdir_id_digest || !onion_address)) {
return;
}
- control_event_hs_descriptor_receive_end("RECEIVED", onion_address,
- rend_data, id_digest, NULL);
+
+ desc_id = get_desc_id_from_query(rend_data, hsdir_id_digest);
+ if (desc_id != NULL) {
+ char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
+ /* Set the descriptor ID digest to base32 so we can send it. */
+ base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id,
+ DIGEST_LEN);
+ /* Extra whitespace is needed before the value. */
+ tor_asprintf(&desc_id_field, " %s", desc_id_base32);
+ }
+
+ event_hs_descriptor_receive_end("RECEIVED", onion_address, desc_id_field,
+ TO_REND_DATA_V2(rend_data)->auth_type,
+ hsdir_id_digest, NULL);
+ tor_free(desc_id_field);
+}
+
+/* Send HS_DESC RECEIVED event
+ *
+ * Called when we successfully received a hidden service descriptor. */
+void
+control_event_hsv3_descriptor_received(const char *onion_address,
+ const char *desc_id,
+ const char *hsdir_id_digest)
+{
+ char *desc_id_field = NULL;
+
+ if (BUG(!onion_address || !desc_id || !hsdir_id_digest)) {
+ return;
+ }
+
+ /* Because DescriptorID is an optional positional value, we need to add a
+ * whitespace before in order to not be next to the HsDir value. */
+ tor_asprintf(&desc_id_field, " %s", desc_id);
+
+ event_hs_descriptor_receive_end("RECEIVED", onion_address, desc_id_field,
+ REND_NO_AUTH, hsdir_id_digest, NULL);
+ tor_free(desc_id_field);
}
/** send HS_DESC UPLOADED event
@@ -7245,9 +7475,7 @@ void
control_event_hs_descriptor_uploaded(const char *id_digest,
const char *onion_address)
{
- if (!id_digest) {
- log_warn(LD_BUG, "Called with id_digest==%p",
- id_digest);
+ if (BUG(!id_digest)) {
return;
}
@@ -7261,17 +7489,58 @@ control_event_hs_descriptor_uploaded(const char *id_digest,
* add it to REASON= field.
*/
void
-control_event_hs_descriptor_failed(const rend_data_t *rend_data,
- const char *id_digest,
- const char *reason)
+control_event_hsv2_descriptor_failed(const rend_data_t *rend_data,
+ const char *hsdir_id_digest,
+ const char *reason)
{
- if (!rend_data) {
- log_warn(LD_BUG, "Called with rend_data==%p", rend_data);
+ char *desc_id_field = NULL;
+ const char *desc_id;
+
+ if (BUG(!rend_data)) {
return;
}
- control_event_hs_descriptor_receive_end("FAILED",
- rend_data_get_address(rend_data),
- rend_data, id_digest, reason);
+
+ desc_id = get_desc_id_from_query(rend_data, hsdir_id_digest);
+ if (desc_id != NULL) {
+ char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
+ /* Set the descriptor ID digest to base32 so we can send it. */
+ base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id,
+ DIGEST_LEN);
+ /* Extra whitespace is needed before the value. */
+ tor_asprintf(&desc_id_field, " %s", desc_id_base32);
+ }
+
+ event_hs_descriptor_receive_end("FAILED", rend_data_get_address(rend_data),
+ desc_id_field,
+ TO_REND_DATA_V2(rend_data)->auth_type,
+ hsdir_id_digest, reason);
+ tor_free(desc_id_field);
+}
+
+/** Send HS_DESC event to inform controller that the query to
+ * <b>onion_address</b> failed to retrieve hidden service descriptor
+ * <b>desc_id</b> from directory identified by <b>hsdir_id_digest</b>. If
+ * NULL, "UNKNOWN" is used. If <b>reason</b> is not NULL, add it to REASON=
+ * field. */
+void
+control_event_hsv3_descriptor_failed(const char *onion_address,
+ const char *desc_id,
+ const char *hsdir_id_digest,
+ const char *reason)
+{
+ char *desc_id_field = NULL;
+
+ if (BUG(!onion_address || !desc_id || !reason)) {
+ return;
+ }
+
+ /* Because DescriptorID is an optional positional value, we need to add a
+ * whitespace before in order to not be next to the HsDir value. */
+ tor_asprintf(&desc_id_field, " %s", desc_id);
+
+ event_hs_descriptor_receive_end("FAILED", onion_address, desc_id_field,
+ REND_NO_AUTH, hsdir_id_digest, reason);
+ tor_free(desc_id_field);
}
/** Send HS_DESC_CONTENT event after completion of a successful fetch from hs
@@ -7321,9 +7590,7 @@ control_event_hs_descriptor_upload_failed(const char *id_digest,
const char *onion_address,
const char *reason)
{
- if (!id_digest) {
- log_warn(LD_BUG, "Called with id_digest==%p",
- id_digest);
+ if (BUG(!id_digest)) {
return;
}
control_event_hs_descriptor_upload_end("FAILED", onion_address,