router: refactor router_build_fresh_descriptor() static function interfaces

Tidy the arguments and return values of these functions, and clean up their
memory management.

Preparation for testing 29017 and 20918.
This commit is contained in:
teor 2019-01-10 19:47:24 +10:00
parent 6c5a506cdb
commit f19b64dce9
2 changed files with 112 additions and 58 deletions

View file

@ -152,6 +152,8 @@ routerinfo_err_to_string(int err)
return "Cannot generate descriptor"; return "Cannot generate descriptor";
case TOR_ROUTERINFO_ERROR_DESC_REBUILDING: case TOR_ROUTERINFO_ERROR_DESC_REBUILDING:
return "Descriptor still rebuilding - not ready yet"; return "Descriptor still rebuilding - not ready yet";
case TOR_ROUTERINFO_ERROR_INTERNAL_BUG:
return "Internal bug, see logs for details";
} }
log_warn(LD_BUG, "unknown routerinfo error %d - shouldn't happen", err); log_warn(LD_BUG, "unknown routerinfo error %d - shouldn't happen", err);
@ -1941,23 +1943,33 @@ get_my_declared_family(const or_options_t *options)
return result; return result;
} }
/** Build a fresh routerinfo for this OR, without any of the fields that depend /** Allocate a fresh, unsigned routerinfo for this OR, without any of the
* on the corresponding extrainfo. Set r to the generated routerinfo. * fields that depend on the corresponding extrainfo.
* Return 0 on success, -1 on temporary error. Caller is responsible for *
* freeing the generated routerinfo if 0 is returned. * On success, set ri_out to the new routerinfo, and return 0.
* Caller is responsible for freeing the generated routerinfo.
*
* Returns a negative value and sets ri_out to NULL on temporary error.
*/ */
static int static int
router_build_fresh_routerinfo(routerinfo_t **r) router_build_fresh_routerinfo(routerinfo_t **ri_out)
{ {
routerinfo_t *ri; routerinfo_t *ri = NULL;
uint32_t addr; uint32_t addr;
char platform[256]; char platform[256];
int hibernating = we_are_hibernating(); int hibernating = we_are_hibernating();
const or_options_t *options = get_options(); const or_options_t *options = get_options();
int result = TOR_ROUTERINFO_ERROR_INTERNAL_BUG;
if (BUG(!ri_out)) {
result = TOR_ROUTERINFO_ERROR_INTERNAL_BUG;
goto err;
}
if (router_pick_published_address(options, &addr, 0) < 0) { if (router_pick_published_address(options, &addr, 0) < 0) {
log_warn(LD_CONFIG, "Don't know my address while generating descriptor"); log_warn(LD_CONFIG, "Don't know my address while generating descriptor");
return TOR_ROUTERINFO_ERROR_NO_EXT_ADDR; result = TOR_ROUTERINFO_ERROR_NO_EXT_ADDR;
goto err;
} }
/* Log a message if the address in the descriptor doesn't match the ORPort /* Log a message if the address in the descriptor doesn't match the ORPort
@ -2014,8 +2026,8 @@ router_build_fresh_routerinfo(routerinfo_t **r)
ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key()); ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
if (BUG(crypto_pk_get_digest(ri->identity_pkey, if (BUG(crypto_pk_get_digest(ri->identity_pkey,
ri->cache_info.identity_digest) < 0)) { ri->cache_info.identity_digest) < 0)) {
routerinfo_free(ri); result = TOR_ROUTERINFO_ERROR_DIGEST_FAILED;
return TOR_ROUTERINFO_ERROR_DIGEST_FAILED; goto err;
} }
ri->cache_info.signing_key_cert = ri->cache_info.signing_key_cert =
tor_cert_dup(get_master_signing_key_cert()); tor_cert_dup(get_master_signing_key_cert());
@ -2054,20 +2066,26 @@ router_build_fresh_routerinfo(routerinfo_t **r)
ri->declared_family = get_my_declared_family(options); ri->declared_family = get_my_declared_family(options);
*r = ri; goto done;
err:
routerinfo_free(ri);
*ri_out = NULL;
return result;
done:
*ri_out = ri;
return 0; return 0;
} }
/** Build an extrainfo for this OR, based on the routerinfo ri. Set e to the /** Allocate and return an extrainfo for this OR, based on the routerinfo ri.
* generated extrainfo. Return 0 on success, -1 on temporary error. Failure to *
* generate an extrainfo is not an error and is indicated by setting e to * Caller is responsible for freeing the generated extrainfo.
* NULL. Caller is responsible for freeing the generated extrainfo if 0 is
* returned.
*/ */
static int static extrainfo_t *
router_build_fresh_extrainfo(const routerinfo_t *ri, extrainfo_t **e) router_build_fresh_extrainfo(const routerinfo_t *ri)
{ {
extrainfo_t *ei; extrainfo_t *ei = NULL;
/* Now generate the extrainfo. */ /* Now generate the extrainfo. */
ei = tor_malloc_zero(sizeof(extrainfo_t)); ei = tor_malloc_zero(sizeof(extrainfo_t));
@ -2079,24 +2097,23 @@ router_build_fresh_extrainfo(const routerinfo_t *ri, extrainfo_t **e)
memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest, memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest,
DIGEST_LEN); DIGEST_LEN);
*e = ei;
return 0; return ei;
} }
/** Create a signed descriptor for ei, and add it to ei->cache_info. /** Create a signed descriptor for ei, and add it to ei->cache_info.
* Return ei on success, free ei and return NULL on temporary error. *
* Caller is responsible for freeing the returned extrainfo * Return 0 on success, -1 on temporary error.
* (if it is not NULL), including any extra fields set in ei->cache_info. * On error, ei->cache_info is not modified.
*/ */
static extrainfo_t * static int
router_update_extrainfo_descriptor_body(extrainfo_t *ei) router_update_extrainfo_descriptor_body(extrainfo_t *ei)
{ {
if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body, if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body,
ei, get_server_identity_key(), ei, get_server_identity_key(),
get_master_signing_keypair()) < 0) { get_master_signing_keypair()) < 0) {
log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); log_warn(LD_BUG, "Couldn't generate extra-info descriptor.");
extrainfo_free(ei); return -1;
ei = NULL;
} else { } else {
ei->cache_info.signed_descriptor_len = ei->cache_info.signed_descriptor_len =
strlen(ei->cache_info.signed_descriptor_body); strlen(ei->cache_info.signed_descriptor_body);
@ -2107,12 +2124,11 @@ router_update_extrainfo_descriptor_body(extrainfo_t *ei)
ei->cache_info.signed_descriptor_body, ei->cache_info.signed_descriptor_body,
ei->cache_info.signed_descriptor_len, ei->cache_info.signed_descriptor_len,
DIGEST_SHA256); DIGEST_SHA256);
return 0;
} }
return ei;
} }
/** If ei is not NULL, set the fields in ri that depend on ei. /** Set the fields in ri that depend on ei.
*/ */
static void static void
router_update_routerinfo_from_extrainfo(routerinfo_t *ri, router_update_routerinfo_from_extrainfo(routerinfo_t *ri,
@ -2133,24 +2149,26 @@ router_update_routerinfo_from_extrainfo(routerinfo_t *ri,
} }
/** Create a signed descriptor for ri, and add it to ri->cache_info. /** Create a signed descriptor for ri, and add it to ri->cache_info.
* Return 0 on success, free ri and ei and return -1 on temporary error. *
* TODO: freeing ri and ei, but leaving dangling pointers, is a bad interface. * Return 0 on success, and a negative value on temporary error.
* Caller is responsible for freeing the generated ri and ei if 0 is returned, * If ri is NULL, logs a BUG() warning and returns a negative value.
* including any extra fields set in ri->cache_info. * On error, ri->cache_info is not modified.
*/ */
static int static int
router_update_routerinfo_descriptor_body(routerinfo_t *ri, extrainfo_t *ei) router_update_routerinfo_descriptor_body(routerinfo_t *ri)
{ {
if (BUG(!ri))
return TOR_ROUTERINFO_ERROR_INTERNAL_BUG;
if (! (ri->cache_info.signed_descriptor_body = if (! (ri->cache_info.signed_descriptor_body =
router_dump_router_to_string(ri, get_server_identity_key(), router_dump_router_to_string(ri, get_server_identity_key(),
get_onion_key(), get_onion_key(),
get_current_curve25519_keypair(), get_current_curve25519_keypair(),
get_master_signing_keypair())) ) { get_master_signing_keypair())) ) {
log_warn(LD_BUG, "Couldn't generate router descriptor."); log_warn(LD_BUG, "Couldn't generate router descriptor.");
routerinfo_free(ri);
extrainfo_free(ei);
return TOR_ROUTERINFO_ERROR_CANNOT_GENERATE; return TOR_ROUTERINFO_ERROR_CANNOT_GENERATE;
} }
ri->cache_info.signed_descriptor_len = ri->cache_info.signed_descriptor_len =
strlen(ri->cache_info.signed_descriptor_body); strlen(ri->cache_info.signed_descriptor_body);
@ -2200,40 +2218,63 @@ router_update_routerinfo_digest(routerinfo_t *ri)
ri->cache_info.signed_descriptor_digest); ri->cache_info.signed_descriptor_digest);
} }
/** Build a fresh routerinfo, signed server descriptor, and extra-info document /** Build a fresh routerinfo, signed server descriptor, and signed extra-info
* for this OR. Set r to the generated routerinfo, e to the generated * document for this OR.
* extra-info document. Return 0 on success, -1 on temporary error. Failure to *
* generate an extra-info document is not an error and is indicated by setting * Set r to the generated routerinfo, e to the generated extra-info document.
* e to NULL. Caller is responsible for freeing generated documents if 0 is * Failure to generate an extra-info document is not an error and is indicated
* returned. * by setting e to NULL.
* Return 0 on success, and a negative value on temporary error.
* Caller is responsible for freeing generated documents on success.
*/ */
int int
router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
{ {
int result = -1; int result = TOR_ROUTERINFO_ERROR_INTERNAL_BUG;
routerinfo_t *ri = NULL; routerinfo_t *ri = NULL;
extrainfo_t *ei = NULL; extrainfo_t *ei = NULL;
/* TODO: return ri */ if (BUG(!r))
goto err;
if (BUG(!e))
goto err;
result = router_build_fresh_routerinfo(&ri); result = router_build_fresh_routerinfo(&ri);
if (result < 0) if (result < 0) {
return result; goto err;
}
/* If ri is NULL, then result should be negative. So this check should be
* unreachable. */
if (BUG(!ri)) {
result = TOR_ROUTERINFO_ERROR_INTERNAL_BUG;
goto err;
}
/* TODO: return ei */ ei = router_build_fresh_extrainfo(ri);
result = router_build_fresh_extrainfo(ri, &ei); /* Failing to create an ei is not an error, but at this stage,
if (result < 0) * router_build_fresh_extrainfo() should not fail. */
return result; if (BUG(!ei))
goto skip_ei;
/* TODO: this function frees ei on failure, instead, goto err */ result = router_update_extrainfo_descriptor_body(ei);
ei = router_update_extrainfo_descriptor_body(ei); if (result < 0)
goto skip_ei;
/* TODO: don't rely on tor_malloc_zero */ /* TODO: don't rely on tor_malloc_zero */
router_update_routerinfo_from_extrainfo(ri, ei); router_update_routerinfo_from_extrainfo(ri, ei);
/* TODO: this function frees ri and ei on failure, instead, goto err */ /* TODO: disentangle these GOTOs, or split into another function. */
result = router_update_routerinfo_descriptor_body(ri, ei); goto ei_ok;
skip_ei:
extrainfo_free(ei);
ei = NULL;
ei_ok:
result = router_update_routerinfo_descriptor_body(ri);
if (result < 0) if (result < 0)
return result; goto err;
/* TODO: fold into router_build_fresh_routerinfo() */ /* TODO: fold into router_build_fresh_routerinfo() */
router_update_routerinfo_purpose(ri); router_update_routerinfo_purpose(ri);
@ -2246,11 +2287,23 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
router_update_routerinfo_digest(ri); router_update_routerinfo_digest(ri);
if (ei) { if (ei) {
tor_assert(! if (BUG(routerinfo_incompatible_with_extrainfo(ri->identity_pkey, ei,
routerinfo_incompatible_with_extrainfo(ri->identity_pkey, ei, &ri->cache_info, NULL))) {
&ri->cache_info, NULL)); result = TOR_ROUTERINFO_ERROR_INTERNAL_BUG;
goto err;
}
} }
goto done;
err:
routerinfo_free(ri);
extrainfo_free(ei);
*r = NULL;
*e = NULL;
return result;
done:
*r = ri; *r = ri;
*e = ei; *e = ei;
return 0; return 0;

View file

@ -23,6 +23,7 @@ struct ed25519_keypair_t;
#define TOR_ROUTERINFO_ERROR_DIGEST_FAILED (-4) #define TOR_ROUTERINFO_ERROR_DIGEST_FAILED (-4)
#define TOR_ROUTERINFO_ERROR_CANNOT_GENERATE (-5) #define TOR_ROUTERINFO_ERROR_CANNOT_GENERATE (-5)
#define TOR_ROUTERINFO_ERROR_DESC_REBUILDING (-6) #define TOR_ROUTERINFO_ERROR_DESC_REBUILDING (-6)
#define TOR_ROUTERINFO_ERROR_INTERNAL_BUG (-7)
crypto_pk_t *get_onion_key(void); crypto_pk_t *get_onion_key(void);
time_t get_onion_key_set_at(void); time_t get_onion_key_set_at(void);