Loading src/or/or.h +11 −15 Original line number Diff line number Diff line Loading @@ -3598,6 +3598,13 @@ typedef struct rend_encoded_v2_service_descriptor_t { char *desc_str; /**< Descriptor string. */ } rend_encoded_v2_service_descriptor_t; /** Introduction point information. */ typedef struct rend_intro_point_t { extend_info_t *extend_info; /**< Extend info of this introduction point. */ crypto_pk_env_t *intro_key; /**< Introduction key that replaces the service * key, if this descriptor is V2. */ } rend_intro_point_t; /** Information used to connect to a hidden service. */ typedef struct rend_service_descriptor_t { crypto_pk_env_t *pk; /**< This service's public key. */ Loading @@ -3605,21 +3612,9 @@ typedef struct rend_service_descriptor_t { time_t timestamp; /**< Time when the descriptor was generated. */ uint16_t protocols; /**< Bitmask: which rendezvous protocols are supported? * (We allow bits '0', '1', and '2' to be set.) */ int n_intro_points; /**< Number of introduction points. */ /** Array of n_intro_points elements for this service's introduction points' * nicknames. Elements are removed from this array if introduction attempts * fail. */ char **intro_points; /** Array of n_intro_points elements for this service's introduction points' * extend_infos, or NULL if this descriptor is V0. Elements are removed * from this array if introduction attempts fail. If this array is present, * its elements correspond to the elements of intro_points. */ extend_info_t **intro_point_extend_info; strmap_t *intro_keys; /**< map from intro node hexdigest to key; only * used for versioned hidden service descriptors. */ /* XXXX020 Refactor n_intro_points, intro_points, intro_point_extend_info, * and intro_keys into a list of intro points. */ /** List of the service's introduction points. Elements are removed if * introduction attempts fail. */ smartlist_t *intro_nodes; } rend_service_descriptor_t; int rend_cmp_service_ids(const char *one, const char *two); Loading @@ -3637,6 +3632,7 @@ rend_service_descriptor_t *rend_parse_service_descriptor(const char *str, int rend_get_service_id(crypto_pk_env_t *pk, char *out); void rend_encoded_v2_service_descriptor_free( rend_encoded_v2_service_descriptor_t *desc); void rend_intro_point_free(rend_intro_point_t *intro); /** A cached rendezvous descriptor. */ typedef struct rend_cache_entry_t { Loading src/or/rendclient.c +34 −48 Original line number Diff line number Diff line Loading @@ -82,12 +82,15 @@ rend_client_send_introduction(origin_circuit_t *introcirc, if (entry->parsed->version == 0) { /* unversioned descriptor */ intro_key = entry->parsed->pk; } else { /* versioned descriptor */ char hex_digest[HEX_DIGEST_LEN+2]; hex_digest[0] = '$'; base16_encode(hex_digest+1, HEX_DIGEST_LEN+1, introcirc->build_state->chosen_exit->identity_digest, DIGEST_LEN); intro_key = strmap_get(entry->parsed->intro_keys, hex_digest); intro_key = NULL; SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, { if (!memcmp(introcirc->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { intro_key = intro->intro_key; break; } }); if (!intro_key) { log_warn(LD_BUG, "Internal error: could not find intro key."); goto err; Loading Loading @@ -342,35 +345,17 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) return 0; } if (ent->parsed->intro_point_extend_info) { for (i=0; i < ent->parsed->n_intro_points; ++i) { for (i = 0; i < smartlist_len(ent->parsed->intro_nodes); i++) { rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i); if (!memcmp(failed_intro->identity_digest, ent->parsed->intro_point_extend_info[i]->identity_digest, DIGEST_LEN)) { tor_assert(!strcmp(ent->parsed->intro_points[i], ent->parsed->intro_point_extend_info[i]->nickname)); tor_free(ent->parsed->intro_points[i]); extend_info_free(ent->parsed->intro_point_extend_info[i]); --ent->parsed->n_intro_points; ent->parsed->intro_points[i] = ent->parsed->intro_points[ent->parsed->n_intro_points]; ent->parsed->intro_point_extend_info[i] = ent->parsed->intro_point_extend_info[ent->parsed->n_intro_points]; break; } } } else { for (i=0; i < ent->parsed->n_intro_points; ++i) { if (!strcasecmp(ent->parsed->intro_points[i], failed_intro->nickname)) { tor_free(ent->parsed->intro_points[i]); ent->parsed->intro_points[i] = ent->parsed->intro_points[--ent->parsed->n_intro_points]; intro->extend_info->identity_digest, DIGEST_LEN)) { rend_intro_point_free(intro); smartlist_del(ent->parsed->intro_nodes, i); break; } } } if (!ent->parsed->n_intro_points) { if (smartlist_len(ent->parsed->intro_nodes) == 0) { log_info(LD_REND, "No more intro points remain for %s. Re-fetching descriptor.", escaped_safe_str(query)); Loading @@ -388,7 +373,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) return 0; } log_info(LD_REND,"%d options left for %s.", ent->parsed->n_intro_points, escaped_safe_str(query)); smartlist_len(ent->parsed->intro_nodes), escaped_safe_str(query)); return 1; } Loading Loading @@ -503,7 +488,7 @@ rend_client_desc_here(const char *query) continue; assert_connection_ok(TO_CONN(conn), now); if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 && entry->parsed->n_intro_points > 0) { smartlist_len(entry->parsed->intro_nodes) > 0) { /* either this fetch worked, or it failed but there was a * valid entry from before which we should reuse */ log_info(LD_REND,"Rend desc is usable. Launching circuits."); Loading Loading @@ -537,6 +522,8 @@ rend_client_get_random_intro(const char *query) { int i; rend_cache_entry_t *entry; rend_intro_point_t *intro; routerinfo_t *router; if (rend_cache_lookup_entry(query, -1, &entry) < 1) { log_warn(LD_REND, Loading @@ -546,26 +533,25 @@ rend_client_get_random_intro(const char *query) } again: if (!entry->parsed->n_intro_points) if (smartlist_len(entry->parsed->intro_nodes) == 0) return NULL; i = crypto_rand_int(entry->parsed->n_intro_points); if (entry->parsed->intro_point_extend_info) { return extend_info_dup(entry->parsed->intro_point_extend_info[i]); } else { /* add the intro point nicknames */ char *choice = entry->parsed->intro_points[i]; routerinfo_t *router = router_get_by_nickname(choice, 0); i = crypto_rand_int(smartlist_len(entry->parsed->intro_nodes)); intro = smartlist_get(entry->parsed->intro_nodes, i); /* Do we need to look up the router or is the extend info complete? */ if (!intro->extend_info->onion_key) { router = router_get_by_nickname(intro->extend_info->nickname, 0); if (!router) { log_info(LD_REND, "Unknown router with nickname '%s'; trying another.", choice); tor_free(choice); entry->parsed->intro_points[i] = entry->parsed->intro_points[--entry->parsed->n_intro_points]; intro->extend_info->nickname); rend_intro_point_free(intro); smartlist_del(entry->parsed->intro_nodes, i); goto again; } return extend_info_from_router(router); extend_info_free(intro->extend_info); intro = tor_malloc_zero(sizeof(rend_intro_point_t)); intro->extend_info = extend_info_from_router(router); } return extend_info_dup(intro->extend_info); } src/or/rendcommon.c +51 −57 Original line number Diff line number Diff line Loading @@ -20,41 +20,17 @@ rend_cmp_service_ids(const char *one, const char *two) return strcasecmp(one,two); } /** Helper: Release the storage held by the intro key in <b>_ent</b>. */ /*XXXX020 there's also one of these in rendservice.c */ /* Right. But the only alternative to that (which I know) would be to * write it to or.h. Should I do that? -KL */ static void intro_key_free(void *_ent) { crypto_pk_env_t *ent = _ent; crypto_free_pk_env(ent); } /** Free the storage held by the service descriptor <b>desc</b>. */ void rend_service_descriptor_free(rend_service_descriptor_t *desc) { int i; if (desc->pk) crypto_free_pk_env(desc->pk); if (desc->intro_points) { for (i=0; i < desc->n_intro_points; ++i) { tor_free(desc->intro_points[i]); } tor_free(desc->intro_points); } if (desc->intro_point_extend_info) { for (i=0; i < desc->n_intro_points; ++i) { if (desc->intro_point_extend_info[i]) extend_info_free(desc->intro_point_extend_info[i]); } tor_free(desc->intro_point_extend_info); } if (desc->intro_keys) { strmap_free(desc->intro_keys, intro_key_free); if (desc->intro_nodes) { SMARTLIST_FOREACH(desc->intro_nodes, rend_intro_point_t *, intro, rend_intro_point_free(intro);); smartlist_free(desc->intro_nodes); } tor_free(desc); } Loading Loading @@ -191,9 +167,9 @@ rend_encode_v2_intro_points(char **ipos_base64, int r = -1; /* Assemble unencrypted list of introduction points. */ *ipos_base64 = NULL; unenc_len = desc->n_intro_points * 1000; /* too long, but ok. */ unenc_len = smartlist_len(desc->intro_nodes) * 1000; /* too long, but ok. */ unenc = tor_malloc_zero(unenc_len); for (i = 0; i < desc->n_intro_points; i++) { for (i = 0; i < smartlist_len(desc->intro_nodes); i++) { char id_base32[REND_INTRO_POINT_ID_LEN_BASE32 + 1]; char *onion_key = NULL; size_t onion_key_len; Loading @@ -202,9 +178,9 @@ rend_encode_v2_intro_points(char **ipos_base64, char *address = NULL; size_t service_key_len; int res; char hex_digest[HEX_DIGEST_LEN+2]; /* includes $ and NUL. */ rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i); /* Obtain extend info with introduction point details. */ extend_info_t *info = desc->intro_point_extend_info[i]; extend_info_t *info = intro->extend_info; /* Encode introduction point ID. */ base32_encode(id_base32, sizeof(id_base32), info->identity_digest, DIGEST_LEN); Loading @@ -215,11 +191,7 @@ rend_encode_v2_intro_points(char **ipos_base64, goto done; } /* Encode intro key. */ hex_digest[0] = '$'; base16_encode(hex_digest+1, HEX_DIGEST_LEN+1, info->identity_digest, DIGEST_LEN); intro_key = strmap_get(desc->intro_keys, hex_digest); intro_key = intro->intro_key; if (!intro_key || crypto_pk_write_public_key_to_string(intro_key, &service_key, &service_key_len) < 0) { Loading Loading @@ -324,6 +296,17 @@ rend_encoded_v2_service_descriptor_free( tor_free(desc); } /** Free the storage held by an introduction point info. */ void rend_intro_point_free(rend_intro_point_t *intro) { if (intro->extend_info) extend_info_free(intro->extend_info); if (intro->intro_key) crypto_free_pk_env(intro->intro_key); tor_free(intro); } /** Encode a set of rend_encoded_v2_service_descriptor_t's for <b>desc</b> * at time <b>now</b> using <b>descriptor_cookie</b> (may be <b>NULL</b> if * introduction points shall not be encrypted) and <b>period</b> (e.g. 0 Loading Loading @@ -353,7 +336,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, seconds_valid = period * REND_TIME_PERIOD_V2_DESC_VALIDITY + get_seconds_valid(now, service_id); /* Assemble, possibly encrypt, and encode introduction points. */ if (desc->n_intro_points > 0 && if (smartlist_len(desc->intro_nodes) > 0 && rend_encode_v2_intro_points(&ipos_base64, desc, descriptor_cookie) < 0) { log_warn(LD_REND, "Encoding of introduction points did not succeed."); return -1; Loading Loading @@ -408,7 +391,8 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, else protocol_versions_string[0]= '\0'; /* Assemble complete descriptor. */ desc_len = 2000 + desc->n_intro_points * 1000; /* far too long, but ok. */ desc_len = 2000 + smartlist_len(desc->intro_nodes) * 1000; /* far too long, but okay.*/ enc->desc_str = desc_str = tor_malloc_zero(desc_len); result = tor_snprintf(desc_str, desc_len, "rendezvous-service-descriptor %s\n" Loading Loading @@ -503,18 +487,24 @@ rend_encode_service_descriptor(rend_service_descriptor_t *desc, char *end; int i; size_t asn1len; size_t buflen = PK_BYTES*2*(desc->n_intro_points+2);/*Too long, but ok*/ size_t buflen = PK_BYTES*2*(smartlist_len(desc->intro_nodes)+2);/*Too long, but ok*/ cp = *str_out = tor_malloc(buflen); end = cp + PK_BYTES*2*(desc->n_intro_points+1); end = cp + PK_BYTES*2*(smartlist_len(desc->intro_nodes)+1); asn1len = crypto_pk_asn1_encode(desc->pk, cp+2, end-(cp+2)); set_uint16(cp, htons((uint16_t)asn1len)); cp += 2+asn1len; set_uint32(cp, htonl((uint32_t)desc->timestamp)); cp += 4; set_uint16(cp, htons((uint16_t)desc->n_intro_points)); set_uint16(cp, htons((uint16_t)smartlist_len(desc->intro_nodes))); cp += 2; for (i=0; i < desc->n_intro_points; ++i) { char *ipoint = (char*)desc->intro_points[i]; for (i=0; i < smartlist_len(desc->intro_nodes); ++i) { rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i); char ipoint[HEX_DIGEST_LEN+2]; ipoint[0] = '$'; base16_encode(ipoint+1, HEX_DIGEST_LEN+1, intro->extend_info->identity_digest, DIGEST_LEN); strlcpy(cp, ipoint, buflen-(cp-*str_out)); cp += strlen(ipoint)+1; } Loading @@ -537,9 +527,10 @@ rend_service_descriptor_t * rend_parse_service_descriptor(const char *str, size_t len) { rend_service_descriptor_t *result = NULL; int i; int i, n_intro_points; size_t keylen, asn1len; const char *end, *cp, *eos; rend_intro_point_t *intro; result = tor_malloc_zero(sizeof(rend_service_descriptor_t)); cp = str; Loading @@ -558,20 +549,23 @@ rend_parse_service_descriptor(const char *str, size_t len) cp += 4; result->protocols = 1<<2; /* always use intro format 2 */ if (end-cp < 2) goto truncated; result->n_intro_points = ntohs(get_uint16(cp)); n_intro_points = ntohs(get_uint16(cp)); cp += 2; if (result->n_intro_points != 0) { result->intro_points = tor_malloc_zero(sizeof(char*)*result->n_intro_points); for (i=0;i<result->n_intro_points;++i) { result->intro_nodes = smartlist_create(); for (i=0;i<n_intro_points;++i) { if (end-cp < 2) goto truncated; eos = (const char *)memchr(cp,'\0',end-cp); if (!eos) goto truncated; result->intro_points[i] = tor_strdup(cp); /* Write nickname to extend info, but postpone the lookup whether * we know that router. It's not part of the parsing process. */ intro = tor_malloc_zero(sizeof(rend_intro_point_t)); intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); strlcpy(intro->extend_info->nickname, cp, sizeof(intro->extend_info->nickname)); smartlist_add(result->intro_nodes, intro); cp = eos+1; } } keylen = crypto_pk_keysize(result->pk); tor_assert(end-cp >= 0); if ((size_t)(end-cp) < keylen) goto truncated; Loading Loading @@ -1091,7 +1085,7 @@ rend_cache_store_v2_desc_as_client(const char *desc, return -1; } } else { parsed->n_intro_points = 0; parsed->intro_nodes = smartlist_create(); } /* We don't need the encoded/encrypted introduction points any longer. */ tor_free(intro_content); Loading src/or/rendservice.c +62 −106 File changed.Preview size limit exceeded, changes collapsed. Show changes src/or/routerparse.c +17 −41 Original line number Diff line number Diff line Loading @@ -862,8 +862,8 @@ check_signature_token(const char *digest, tor_free(signed_digest); return -1; } log_debug(LD_DIR,"Signed %s hash starts %s", doctype, hex_str(signed_digest,4)); // log_debug(LD_DIR,"Signed %s hash starts %s", doctype, // hex_str(signed_digest,4)); if (memcmp(digest, signed_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype); tor_free(signed_digest); Loading Loading @@ -3384,14 +3384,15 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, { char *ipos_decrypted = NULL; const char **current_ipo; smartlist_t *intropoints; smartlist_t *tokens; int i; directory_token_t *tok; rend_intro_point_t *intro; extend_info_t *info; struct in_addr ip; int result; tor_assert(parsed); /** Function may only be invoked once. */ tor_assert(!parsed->intro_nodes); tor_assert(intro_points_encrypted); tor_assert(intro_points_encrypted_size > 0); /* Decrypt introduction points, if required. */ Loading @@ -3413,15 +3414,9 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, intro_points_encrypted_size = unenclen; } /* Consider one intro point after the other. */ current_ipo = &intro_points_encrypted; intropoints = smartlist_create(); current_ipo = (const char **)&intro_points_encrypted; tokens = smartlist_create(); if (parsed->intro_keys) { log_warn(LD_BUG, "Parsing list of introduction points for the same " "hidden service, twice."); } else { parsed->intro_keys = strmap_new(); } parsed->intro_nodes = smartlist_create(); while (!strcmpstart(*current_ipo, "introduction-point ")) { /* Determine end of string. */ const char *eos = strstr(*current_ipo, "\nintroduction-point "); Loading @@ -3444,8 +3439,9 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, log_warn(LD_REND, "Impossibly short introduction point."); goto err; } /* Allocate new extend info. */ info = tor_malloc_zero(sizeof(extend_info_t)); /* Allocate new intro point and extend info. */ intro = tor_malloc_zero(sizeof(rend_intro_point_t)); info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); /* Parse identifier. */ tok = find_first_by_keyword(tokens, R_IPO_IDENTIFIER); tor_assert(tok); Loading @@ -3453,7 +3449,7 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) { log_warn(LD_REND, "Identity digest contains illegal characters: %s", tok->args[0]); tor_free(info); rend_intro_point_free(intro); goto err; } /* Write identifier to nickname. */ Loading @@ -3464,7 +3460,7 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, tok = find_first_by_keyword(tokens, R_IPO_IP_ADDRESS); if (tor_inet_aton(tok->args[0], &ip) == 0) { log_warn(LD_REND, "Could not parse IP address."); tor_free(info); rend_intro_point_free(intro); goto err; } info->addr = ntohl(ip.s_addr); Loading @@ -3477,7 +3473,7 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, if (!info->port) { log_warn(LD_REND, "Introduction point onion port is out of range: %d", info->port); tor_free(info); rend_intro_point_free(intro); goto err; } /* Parse onion key. */ Loading @@ -3486,30 +3482,12 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, tok->key = NULL; /* Prevent free */ /* Parse service key. */ tok = find_first_by_keyword(tokens, R_IPO_SERVICE_KEY); strmap_set(parsed->intro_keys, info->nickname, tok->key); intro->intro_key = tok->key; tok->key = NULL; /* Prevent free */ /* Add extend info to list of introduction points. */ smartlist_add(intropoints, info); /* XXX if intropoints has items on it, but we goto err the next * time through the loop, we don't free the items in the 'err' * section below. -RD */ } /* Write extend infos to descriptor. */ /* XXXX020 what if intro_points (&tc) are already set? */ /* This function is not intended to be invoced multiple times for * the same descriptor. Should this be asserted? -KL */ /* Yes. -NM */ parsed->n_intro_points = smartlist_len(intropoints); parsed->intro_point_extend_info = tor_malloc_zero(sizeof(extend_info_t *) * parsed->n_intro_points); parsed->intro_points = tor_malloc_zero(sizeof(char *) * parsed->n_intro_points); i = 0; SMARTLIST_FOREACH(intropoints, extend_info_t *, ipo, { parsed->intro_points[i] = tor_strdup(ipo->nickname); parsed->intro_point_extend_info[i++] = ipo; }); result = parsed->n_intro_points; smartlist_add(parsed->intro_nodes, intro); } result = smartlist_len(parsed->intro_nodes); goto done; err: Loading @@ -3520,8 +3498,6 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); smartlist_free(tokens); smartlist_free(intropoints); return result; } Loading
src/or/or.h +11 −15 Original line number Diff line number Diff line Loading @@ -3598,6 +3598,13 @@ typedef struct rend_encoded_v2_service_descriptor_t { char *desc_str; /**< Descriptor string. */ } rend_encoded_v2_service_descriptor_t; /** Introduction point information. */ typedef struct rend_intro_point_t { extend_info_t *extend_info; /**< Extend info of this introduction point. */ crypto_pk_env_t *intro_key; /**< Introduction key that replaces the service * key, if this descriptor is V2. */ } rend_intro_point_t; /** Information used to connect to a hidden service. */ typedef struct rend_service_descriptor_t { crypto_pk_env_t *pk; /**< This service's public key. */ Loading @@ -3605,21 +3612,9 @@ typedef struct rend_service_descriptor_t { time_t timestamp; /**< Time when the descriptor was generated. */ uint16_t protocols; /**< Bitmask: which rendezvous protocols are supported? * (We allow bits '0', '1', and '2' to be set.) */ int n_intro_points; /**< Number of introduction points. */ /** Array of n_intro_points elements for this service's introduction points' * nicknames. Elements are removed from this array if introduction attempts * fail. */ char **intro_points; /** Array of n_intro_points elements for this service's introduction points' * extend_infos, or NULL if this descriptor is V0. Elements are removed * from this array if introduction attempts fail. If this array is present, * its elements correspond to the elements of intro_points. */ extend_info_t **intro_point_extend_info; strmap_t *intro_keys; /**< map from intro node hexdigest to key; only * used for versioned hidden service descriptors. */ /* XXXX020 Refactor n_intro_points, intro_points, intro_point_extend_info, * and intro_keys into a list of intro points. */ /** List of the service's introduction points. Elements are removed if * introduction attempts fail. */ smartlist_t *intro_nodes; } rend_service_descriptor_t; int rend_cmp_service_ids(const char *one, const char *two); Loading @@ -3637,6 +3632,7 @@ rend_service_descriptor_t *rend_parse_service_descriptor(const char *str, int rend_get_service_id(crypto_pk_env_t *pk, char *out); void rend_encoded_v2_service_descriptor_free( rend_encoded_v2_service_descriptor_t *desc); void rend_intro_point_free(rend_intro_point_t *intro); /** A cached rendezvous descriptor. */ typedef struct rend_cache_entry_t { Loading
src/or/rendclient.c +34 −48 Original line number Diff line number Diff line Loading @@ -82,12 +82,15 @@ rend_client_send_introduction(origin_circuit_t *introcirc, if (entry->parsed->version == 0) { /* unversioned descriptor */ intro_key = entry->parsed->pk; } else { /* versioned descriptor */ char hex_digest[HEX_DIGEST_LEN+2]; hex_digest[0] = '$'; base16_encode(hex_digest+1, HEX_DIGEST_LEN+1, introcirc->build_state->chosen_exit->identity_digest, DIGEST_LEN); intro_key = strmap_get(entry->parsed->intro_keys, hex_digest); intro_key = NULL; SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, { if (!memcmp(introcirc->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { intro_key = intro->intro_key; break; } }); if (!intro_key) { log_warn(LD_BUG, "Internal error: could not find intro key."); goto err; Loading Loading @@ -342,35 +345,17 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) return 0; } if (ent->parsed->intro_point_extend_info) { for (i=0; i < ent->parsed->n_intro_points; ++i) { for (i = 0; i < smartlist_len(ent->parsed->intro_nodes); i++) { rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i); if (!memcmp(failed_intro->identity_digest, ent->parsed->intro_point_extend_info[i]->identity_digest, DIGEST_LEN)) { tor_assert(!strcmp(ent->parsed->intro_points[i], ent->parsed->intro_point_extend_info[i]->nickname)); tor_free(ent->parsed->intro_points[i]); extend_info_free(ent->parsed->intro_point_extend_info[i]); --ent->parsed->n_intro_points; ent->parsed->intro_points[i] = ent->parsed->intro_points[ent->parsed->n_intro_points]; ent->parsed->intro_point_extend_info[i] = ent->parsed->intro_point_extend_info[ent->parsed->n_intro_points]; break; } } } else { for (i=0; i < ent->parsed->n_intro_points; ++i) { if (!strcasecmp(ent->parsed->intro_points[i], failed_intro->nickname)) { tor_free(ent->parsed->intro_points[i]); ent->parsed->intro_points[i] = ent->parsed->intro_points[--ent->parsed->n_intro_points]; intro->extend_info->identity_digest, DIGEST_LEN)) { rend_intro_point_free(intro); smartlist_del(ent->parsed->intro_nodes, i); break; } } } if (!ent->parsed->n_intro_points) { if (smartlist_len(ent->parsed->intro_nodes) == 0) { log_info(LD_REND, "No more intro points remain for %s. Re-fetching descriptor.", escaped_safe_str(query)); Loading @@ -388,7 +373,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) return 0; } log_info(LD_REND,"%d options left for %s.", ent->parsed->n_intro_points, escaped_safe_str(query)); smartlist_len(ent->parsed->intro_nodes), escaped_safe_str(query)); return 1; } Loading Loading @@ -503,7 +488,7 @@ rend_client_desc_here(const char *query) continue; assert_connection_ok(TO_CONN(conn), now); if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 && entry->parsed->n_intro_points > 0) { smartlist_len(entry->parsed->intro_nodes) > 0) { /* either this fetch worked, or it failed but there was a * valid entry from before which we should reuse */ log_info(LD_REND,"Rend desc is usable. Launching circuits."); Loading Loading @@ -537,6 +522,8 @@ rend_client_get_random_intro(const char *query) { int i; rend_cache_entry_t *entry; rend_intro_point_t *intro; routerinfo_t *router; if (rend_cache_lookup_entry(query, -1, &entry) < 1) { log_warn(LD_REND, Loading @@ -546,26 +533,25 @@ rend_client_get_random_intro(const char *query) } again: if (!entry->parsed->n_intro_points) if (smartlist_len(entry->parsed->intro_nodes) == 0) return NULL; i = crypto_rand_int(entry->parsed->n_intro_points); if (entry->parsed->intro_point_extend_info) { return extend_info_dup(entry->parsed->intro_point_extend_info[i]); } else { /* add the intro point nicknames */ char *choice = entry->parsed->intro_points[i]; routerinfo_t *router = router_get_by_nickname(choice, 0); i = crypto_rand_int(smartlist_len(entry->parsed->intro_nodes)); intro = smartlist_get(entry->parsed->intro_nodes, i); /* Do we need to look up the router or is the extend info complete? */ if (!intro->extend_info->onion_key) { router = router_get_by_nickname(intro->extend_info->nickname, 0); if (!router) { log_info(LD_REND, "Unknown router with nickname '%s'; trying another.", choice); tor_free(choice); entry->parsed->intro_points[i] = entry->parsed->intro_points[--entry->parsed->n_intro_points]; intro->extend_info->nickname); rend_intro_point_free(intro); smartlist_del(entry->parsed->intro_nodes, i); goto again; } return extend_info_from_router(router); extend_info_free(intro->extend_info); intro = tor_malloc_zero(sizeof(rend_intro_point_t)); intro->extend_info = extend_info_from_router(router); } return extend_info_dup(intro->extend_info); }
src/or/rendcommon.c +51 −57 Original line number Diff line number Diff line Loading @@ -20,41 +20,17 @@ rend_cmp_service_ids(const char *one, const char *two) return strcasecmp(one,two); } /** Helper: Release the storage held by the intro key in <b>_ent</b>. */ /*XXXX020 there's also one of these in rendservice.c */ /* Right. But the only alternative to that (which I know) would be to * write it to or.h. Should I do that? -KL */ static void intro_key_free(void *_ent) { crypto_pk_env_t *ent = _ent; crypto_free_pk_env(ent); } /** Free the storage held by the service descriptor <b>desc</b>. */ void rend_service_descriptor_free(rend_service_descriptor_t *desc) { int i; if (desc->pk) crypto_free_pk_env(desc->pk); if (desc->intro_points) { for (i=0; i < desc->n_intro_points; ++i) { tor_free(desc->intro_points[i]); } tor_free(desc->intro_points); } if (desc->intro_point_extend_info) { for (i=0; i < desc->n_intro_points; ++i) { if (desc->intro_point_extend_info[i]) extend_info_free(desc->intro_point_extend_info[i]); } tor_free(desc->intro_point_extend_info); } if (desc->intro_keys) { strmap_free(desc->intro_keys, intro_key_free); if (desc->intro_nodes) { SMARTLIST_FOREACH(desc->intro_nodes, rend_intro_point_t *, intro, rend_intro_point_free(intro);); smartlist_free(desc->intro_nodes); } tor_free(desc); } Loading Loading @@ -191,9 +167,9 @@ rend_encode_v2_intro_points(char **ipos_base64, int r = -1; /* Assemble unencrypted list of introduction points. */ *ipos_base64 = NULL; unenc_len = desc->n_intro_points * 1000; /* too long, but ok. */ unenc_len = smartlist_len(desc->intro_nodes) * 1000; /* too long, but ok. */ unenc = tor_malloc_zero(unenc_len); for (i = 0; i < desc->n_intro_points; i++) { for (i = 0; i < smartlist_len(desc->intro_nodes); i++) { char id_base32[REND_INTRO_POINT_ID_LEN_BASE32 + 1]; char *onion_key = NULL; size_t onion_key_len; Loading @@ -202,9 +178,9 @@ rend_encode_v2_intro_points(char **ipos_base64, char *address = NULL; size_t service_key_len; int res; char hex_digest[HEX_DIGEST_LEN+2]; /* includes $ and NUL. */ rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i); /* Obtain extend info with introduction point details. */ extend_info_t *info = desc->intro_point_extend_info[i]; extend_info_t *info = intro->extend_info; /* Encode introduction point ID. */ base32_encode(id_base32, sizeof(id_base32), info->identity_digest, DIGEST_LEN); Loading @@ -215,11 +191,7 @@ rend_encode_v2_intro_points(char **ipos_base64, goto done; } /* Encode intro key. */ hex_digest[0] = '$'; base16_encode(hex_digest+1, HEX_DIGEST_LEN+1, info->identity_digest, DIGEST_LEN); intro_key = strmap_get(desc->intro_keys, hex_digest); intro_key = intro->intro_key; if (!intro_key || crypto_pk_write_public_key_to_string(intro_key, &service_key, &service_key_len) < 0) { Loading Loading @@ -324,6 +296,17 @@ rend_encoded_v2_service_descriptor_free( tor_free(desc); } /** Free the storage held by an introduction point info. */ void rend_intro_point_free(rend_intro_point_t *intro) { if (intro->extend_info) extend_info_free(intro->extend_info); if (intro->intro_key) crypto_free_pk_env(intro->intro_key); tor_free(intro); } /** Encode a set of rend_encoded_v2_service_descriptor_t's for <b>desc</b> * at time <b>now</b> using <b>descriptor_cookie</b> (may be <b>NULL</b> if * introduction points shall not be encrypted) and <b>period</b> (e.g. 0 Loading Loading @@ -353,7 +336,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, seconds_valid = period * REND_TIME_PERIOD_V2_DESC_VALIDITY + get_seconds_valid(now, service_id); /* Assemble, possibly encrypt, and encode introduction points. */ if (desc->n_intro_points > 0 && if (smartlist_len(desc->intro_nodes) > 0 && rend_encode_v2_intro_points(&ipos_base64, desc, descriptor_cookie) < 0) { log_warn(LD_REND, "Encoding of introduction points did not succeed."); return -1; Loading Loading @@ -408,7 +391,8 @@ rend_encode_v2_descriptors(smartlist_t *descs_out, else protocol_versions_string[0]= '\0'; /* Assemble complete descriptor. */ desc_len = 2000 + desc->n_intro_points * 1000; /* far too long, but ok. */ desc_len = 2000 + smartlist_len(desc->intro_nodes) * 1000; /* far too long, but okay.*/ enc->desc_str = desc_str = tor_malloc_zero(desc_len); result = tor_snprintf(desc_str, desc_len, "rendezvous-service-descriptor %s\n" Loading Loading @@ -503,18 +487,24 @@ rend_encode_service_descriptor(rend_service_descriptor_t *desc, char *end; int i; size_t asn1len; size_t buflen = PK_BYTES*2*(desc->n_intro_points+2);/*Too long, but ok*/ size_t buflen = PK_BYTES*2*(smartlist_len(desc->intro_nodes)+2);/*Too long, but ok*/ cp = *str_out = tor_malloc(buflen); end = cp + PK_BYTES*2*(desc->n_intro_points+1); end = cp + PK_BYTES*2*(smartlist_len(desc->intro_nodes)+1); asn1len = crypto_pk_asn1_encode(desc->pk, cp+2, end-(cp+2)); set_uint16(cp, htons((uint16_t)asn1len)); cp += 2+asn1len; set_uint32(cp, htonl((uint32_t)desc->timestamp)); cp += 4; set_uint16(cp, htons((uint16_t)desc->n_intro_points)); set_uint16(cp, htons((uint16_t)smartlist_len(desc->intro_nodes))); cp += 2; for (i=0; i < desc->n_intro_points; ++i) { char *ipoint = (char*)desc->intro_points[i]; for (i=0; i < smartlist_len(desc->intro_nodes); ++i) { rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i); char ipoint[HEX_DIGEST_LEN+2]; ipoint[0] = '$'; base16_encode(ipoint+1, HEX_DIGEST_LEN+1, intro->extend_info->identity_digest, DIGEST_LEN); strlcpy(cp, ipoint, buflen-(cp-*str_out)); cp += strlen(ipoint)+1; } Loading @@ -537,9 +527,10 @@ rend_service_descriptor_t * rend_parse_service_descriptor(const char *str, size_t len) { rend_service_descriptor_t *result = NULL; int i; int i, n_intro_points; size_t keylen, asn1len; const char *end, *cp, *eos; rend_intro_point_t *intro; result = tor_malloc_zero(sizeof(rend_service_descriptor_t)); cp = str; Loading @@ -558,20 +549,23 @@ rend_parse_service_descriptor(const char *str, size_t len) cp += 4; result->protocols = 1<<2; /* always use intro format 2 */ if (end-cp < 2) goto truncated; result->n_intro_points = ntohs(get_uint16(cp)); n_intro_points = ntohs(get_uint16(cp)); cp += 2; if (result->n_intro_points != 0) { result->intro_points = tor_malloc_zero(sizeof(char*)*result->n_intro_points); for (i=0;i<result->n_intro_points;++i) { result->intro_nodes = smartlist_create(); for (i=0;i<n_intro_points;++i) { if (end-cp < 2) goto truncated; eos = (const char *)memchr(cp,'\0',end-cp); if (!eos) goto truncated; result->intro_points[i] = tor_strdup(cp); /* Write nickname to extend info, but postpone the lookup whether * we know that router. It's not part of the parsing process. */ intro = tor_malloc_zero(sizeof(rend_intro_point_t)); intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); strlcpy(intro->extend_info->nickname, cp, sizeof(intro->extend_info->nickname)); smartlist_add(result->intro_nodes, intro); cp = eos+1; } } keylen = crypto_pk_keysize(result->pk); tor_assert(end-cp >= 0); if ((size_t)(end-cp) < keylen) goto truncated; Loading Loading @@ -1091,7 +1085,7 @@ rend_cache_store_v2_desc_as_client(const char *desc, return -1; } } else { parsed->n_intro_points = 0; parsed->intro_nodes = smartlist_create(); } /* We don't need the encoded/encrypted introduction points any longer. */ tor_free(intro_content); Loading
src/or/rendservice.c +62 −106 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/or/routerparse.c +17 −41 Original line number Diff line number Diff line Loading @@ -862,8 +862,8 @@ check_signature_token(const char *digest, tor_free(signed_digest); return -1; } log_debug(LD_DIR,"Signed %s hash starts %s", doctype, hex_str(signed_digest,4)); // log_debug(LD_DIR,"Signed %s hash starts %s", doctype, // hex_str(signed_digest,4)); if (memcmp(digest, signed_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype); tor_free(signed_digest); Loading Loading @@ -3384,14 +3384,15 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, { char *ipos_decrypted = NULL; const char **current_ipo; smartlist_t *intropoints; smartlist_t *tokens; int i; directory_token_t *tok; rend_intro_point_t *intro; extend_info_t *info; struct in_addr ip; int result; tor_assert(parsed); /** Function may only be invoked once. */ tor_assert(!parsed->intro_nodes); tor_assert(intro_points_encrypted); tor_assert(intro_points_encrypted_size > 0); /* Decrypt introduction points, if required. */ Loading @@ -3413,15 +3414,9 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, intro_points_encrypted_size = unenclen; } /* Consider one intro point after the other. */ current_ipo = &intro_points_encrypted; intropoints = smartlist_create(); current_ipo = (const char **)&intro_points_encrypted; tokens = smartlist_create(); if (parsed->intro_keys) { log_warn(LD_BUG, "Parsing list of introduction points for the same " "hidden service, twice."); } else { parsed->intro_keys = strmap_new(); } parsed->intro_nodes = smartlist_create(); while (!strcmpstart(*current_ipo, "introduction-point ")) { /* Determine end of string. */ const char *eos = strstr(*current_ipo, "\nintroduction-point "); Loading @@ -3444,8 +3439,9 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, log_warn(LD_REND, "Impossibly short introduction point."); goto err; } /* Allocate new extend info. */ info = tor_malloc_zero(sizeof(extend_info_t)); /* Allocate new intro point and extend info. */ intro = tor_malloc_zero(sizeof(rend_intro_point_t)); info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); /* Parse identifier. */ tok = find_first_by_keyword(tokens, R_IPO_IDENTIFIER); tor_assert(tok); Loading @@ -3453,7 +3449,7 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) { log_warn(LD_REND, "Identity digest contains illegal characters: %s", tok->args[0]); tor_free(info); rend_intro_point_free(intro); goto err; } /* Write identifier to nickname. */ Loading @@ -3464,7 +3460,7 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, tok = find_first_by_keyword(tokens, R_IPO_IP_ADDRESS); if (tor_inet_aton(tok->args[0], &ip) == 0) { log_warn(LD_REND, "Could not parse IP address."); tor_free(info); rend_intro_point_free(intro); goto err; } info->addr = ntohl(ip.s_addr); Loading @@ -3477,7 +3473,7 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, if (!info->port) { log_warn(LD_REND, "Introduction point onion port is out of range: %d", info->port); tor_free(info); rend_intro_point_free(intro); goto err; } /* Parse onion key. */ Loading @@ -3486,30 +3482,12 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, tok->key = NULL; /* Prevent free */ /* Parse service key. */ tok = find_first_by_keyword(tokens, R_IPO_SERVICE_KEY); strmap_set(parsed->intro_keys, info->nickname, tok->key); intro->intro_key = tok->key; tok->key = NULL; /* Prevent free */ /* Add extend info to list of introduction points. */ smartlist_add(intropoints, info); /* XXX if intropoints has items on it, but we goto err the next * time through the loop, we don't free the items in the 'err' * section below. -RD */ } /* Write extend infos to descriptor. */ /* XXXX020 what if intro_points (&tc) are already set? */ /* This function is not intended to be invoced multiple times for * the same descriptor. Should this be asserted? -KL */ /* Yes. -NM */ parsed->n_intro_points = smartlist_len(intropoints); parsed->intro_point_extend_info = tor_malloc_zero(sizeof(extend_info_t *) * parsed->n_intro_points); parsed->intro_points = tor_malloc_zero(sizeof(char *) * parsed->n_intro_points); i = 0; SMARTLIST_FOREACH(intropoints, extend_info_t *, ipo, { parsed->intro_points[i] = tor_strdup(ipo->nickname); parsed->intro_point_extend_info[i++] = ipo; }); result = parsed->n_intro_points; smartlist_add(parsed->intro_nodes, intro); } result = smartlist_len(parsed->intro_nodes); goto done; err: Loading @@ -3520,8 +3498,6 @@ rend_decrypt_introduction_points(rend_service_descriptor_t *parsed, SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t)); smartlist_free(tokens); smartlist_free(intropoints); return result; }