Allow clients to connect to the instance even with OB enabled.

We do this by including the instance's subcredentials to the list of
subcredentials that are used during INTRO2 decryption.
This commit is contained in:
George Kadianakis 2020-01-27 17:03:38 +02:00
parent c731988cb2
commit 0133169481
2 changed files with 61 additions and 13 deletions

View File

@ -284,16 +284,20 @@ compute_subcredentials(const hs_service_t *service,
const unsigned int num_steps = ARRAY_LENGTH(steps); const unsigned int num_steps = ARRAY_LENGTH(steps);
const uint64_t tp = hs_get_time_period_num(0); const uint64_t tp = hs_get_time_period_num(0);
tor_assert(config); tor_assert(service);
tor_assert(subcredentials); tor_assert(subcredentials);
/* Our caller has checked these too */
tor_assert(service->desc_current);
tor_assert(service->desc_next);
/* Our caller made sure that we are an OB instance */ /* Our caller made sure that we are an OB instance */
num_pkeys = smartlist_len(config->ob_master_pubkeys); num_pkeys = smartlist_len(service->config.ob_master_pubkeys);
tor_assert(num_pkeys > 0); tor_assert(num_pkeys > 0);
/* Time to build all the subcredentials for each time period: the previous /* Time to build all the subcredentials for each time period: two for each
* one (-1), the current one (0) and the next one (1) for each configured * instance descriptor plus three for the onionbalance frontend service: the
* key in order to accomodate client and service consensus skew. * previous one (-1), the current one (0) and the next one (1) for each
* configured key in order to accomodate client and service consensus skew.
* *
* If the client consensus after_time is at 23:00 but the service one is at * If the client consensus after_time is at 23:00 but the service one is at
* 01:00, the client will be using the previous time period where the * 01:00, the client will be using the previous time period where the
@ -315,18 +319,30 @@ compute_subcredentials(const hs_service_t *service,
* Size of array is: length of a single subcredential multiplied by the * Size of array is: length of a single subcredential multiplied by the
* number of time period we need to compute and finally multiplied by the * number of time period we need to compute and finally multiplied by the
* total number of keys we are about to process. In other words, for each * total number of keys we are about to process. In other words, for each
* key, we allocate 3 subcredential slots. */ * key, we allocate 3 subcredential slots. Then in the end we also add two
subcreds = tor_calloc(num_steps * num_pkeys, sizeof(hs_subcredential_t)); * subcredentials for this instance's active descriptors. */
subcreds =
tor_calloc((num_steps * num_pkeys) + 2, sizeof(hs_subcredential_t));
/* For each time period step. */ /* For each master pubkey we add 3 subcredentials: */
for (unsigned int i = 0; i < num_steps; i++) { for (unsigned int i = 0; i < num_steps; i++) {
SMARTLIST_FOREACH_BEGIN(config->ob_master_pubkeys, SMARTLIST_FOREACH_BEGIN(service->config.ob_master_pubkeys,
const ed25519_public_key_t *, pkey) { const ed25519_public_key_t *, pkey) {
build_subcredential(pkey, tp + steps[i], &subcreds[idx]); build_subcredential(pkey, tp + steps[i], &subcreds[idx]);
idx++; idx++;
} SMARTLIST_FOREACH_END(pkey); } SMARTLIST_FOREACH_END(pkey);
} }
/* And then in the end we add the two subcredentials of the current active
* instance descriptors */
memcpy(&subcreds[idx++],
service->desc_current->desc->subcredential.subcred, SUBCRED_LEN);
memcpy(&subcreds[idx++],
service->desc_next->desc->subcredential.subcred, SUBCRED_LEN);
log_info(LD_REND, "Refreshing %u onionbalance keys (TP #%d).",
idx, (int)tp);
*subcredentials = subcreds; *subcredentials = subcreds;
return idx; return idx;
} }
@ -344,7 +360,6 @@ compute_subcredentials(const hs_service_t *service,
void void
hs_ob_refresh_keys(hs_service_t *service) hs_ob_refresh_keys(hs_service_t *service)
{ {
const networkstatus_t *ns;
hs_subcredential_t *ob_subcreds = NULL; hs_subcredential_t *ob_subcreds = NULL;
size_t num_subcreds; size_t num_subcreds;
@ -355,6 +370,18 @@ hs_ob_refresh_keys(hs_service_t *service)
return; return;
} }
/* We need both service descriptors created to make onionbalance keys.
*
* That's because we fetch our own (the instance's) subcredentials from our
* own descriptors which should always include the latest subcredentials that
* clients would use.
*
* This function is called with each descriptor build, so we will be
* eventually be called when both descriptors are created. */
if (!service->desc_current || !service->desc_next) {
return;
}
/* Get a new set of subcreds */ /* Get a new set of subcreds */
num_subcreds = compute_subcredentials(service, &ob_subcreds); num_subcreds = compute_subcredentials(service, &ob_subcreds);
tor_assert(num_subcreds > 0); tor_assert(num_subcreds > 0);

View File

@ -191,16 +191,34 @@ test_get_subcredentials(void *arg)
ed25519_keypair_generate(&onion_addr_kp_1, 0); ed25519_keypair_generate(&onion_addr_kp_1, 0);
smartlist_add(config.ob_master_pubkeys, &onion_addr_kp_1.pubkey); smartlist_add(config.ob_master_pubkeys, &onion_addr_kp_1.pubkey);
/* Set up an instance */
hs_service_t *service = tor_malloc_zero(sizeof(hs_service_t));
service->config = config;
service->desc_current = service_descriptor_new();
service->desc_next = service_descriptor_new();
/* Set up the instance subcredentials */
char current_subcred[SUBCRED_LEN];
char next_subcred[SUBCRED_LEN];
memset(current_subcred, 'C', SUBCRED_LEN);
memset(next_subcred, 'N', SUBCRED_LEN);
memcpy(service->desc_current->desc->subcredential.subcred, current_subcred,
SUBCRED_LEN);
memcpy(service->desc_next->desc->subcredential.subcred, next_subcred,
SUBCRED_LEN);
hs_subcredential_t *subcreds = NULL; hs_subcredential_t *subcreds = NULL;
size_t num = compute_subcredentials(&config, &subcreds); size_t num = compute_subcredentials(service, &subcreds);
tt_uint_op(num, OP_EQ, 3); /* 5 subcredentials: 3 for the frontend, 2 for the instance */
tt_uint_op(num, OP_EQ, 5);
/* Validate the subcredentials we just got. We'll build them oursevles with /* Validate the subcredentials we just got. We'll build them oursevles with
* the right time period steps and compare. */ * the right time period steps and compare. */
const uint64_t tp = hs_get_time_period_num(0); const uint64_t tp = hs_get_time_period_num(0);
const int steps[3] = {0, -1, 1}; const int steps[3] = {0, -1, 1};
for (unsigned int i = 0; i < num; i++) { unsigned int i;
for (i = 0; i < 3; i++) {
hs_subcredential_t subcredential; hs_subcredential_t subcredential;
ed25519_public_key_t blinded_pubkey; ed25519_public_key_t blinded_pubkey;
hs_build_blinded_pubkey(&onion_addr_kp_1.pubkey, NULL, 0, tp + steps[i], hs_build_blinded_pubkey(&onion_addr_kp_1.pubkey, NULL, 0, tp + steps[i],
@ -211,6 +229,9 @@ test_get_subcredentials(void *arg)
SUBCRED_LEN); SUBCRED_LEN);
} }
tt_mem_op(subcreds[i++].subcred, OP_EQ, current_subcred, SUBCRED_LEN);
tt_mem_op(subcreds[i++].subcred, OP_EQ, next_subcred, SUBCRED_LEN);
done: done:
tor_free(subcreds); tor_free(subcreds);
smartlist_free(config.ob_master_pubkeys); smartlist_free(config.ob_master_pubkeys);