static void test_rend_cache_lookup_entry(void *data) { int ret; rend_data_t *mock_rend_query = NULL; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; rend_cache_entry_t *entry = NULL; rend_encoded_v2_service_descriptor_t *desc_holder = NULL; char *service_id = NULL; (void)data; rend_cache_init(); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); ret = rend_cache_lookup_entry("abababababababab", 0, NULL); tt_int_op(ret, OP_EQ, -ENOENT); ret = rend_cache_lookup_entry("invalid query", 2, NULL); tt_int_op(ret, OP_EQ, -EINVAL); ret = rend_cache_lookup_entry("abababababababab", 2, NULL); tt_int_op(ret, OP_EQ, -ENOENT); ret = rend_cache_lookup_entry("abababababababab", 4224, NULL); tt_int_op(ret, OP_EQ, -ENOENT); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); ret = rend_cache_lookup_entry(service_id, 2, NULL); tt_int_op(ret, OP_EQ, 0); ret = rend_cache_lookup_entry(service_id, 2, &entry); tt_int_op(ret, OP_EQ, 0); tt_assert(entry); tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str)); tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str); done: rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_cache_free_all(); rend_data_free(mock_rend_query); }
static void test_rend_cache_store_v2_desc_as_client(void *data) { int ret; rend_data_t *mock_rend_query; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; rend_cache_entry_t *entry = NULL; rend_encoded_v2_service_descriptor_t *desc_holder = NULL; char *service_id = NULL; char client_cookie[REND_DESC_COOKIE_LEN]; (void)data; rend_cache_init(); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); // Test success mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, &entry); tt_int_op(ret, OP_EQ, 0); tt_assert(entry); tt_int_op(entry->len, OP_EQ, strlen(desc_holder->desc_str)); tt_str_op(entry->desc, OP_EQ, desc_holder->desc_str); // Test various failure modes // TODO: a too long desc_id_base32 argument crashes the function /* ret = rend_cache_store_v2_desc_as_client( */ /* desc_holder->desc_str, */ /* "3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG3TOOLONG", */ /* &mock_rend_query, NULL); */ /* tt_int_op(ret, OP_EQ, -1); */ // Test bad base32 failure // This causes an assertion failure if we're running with assertions. // But when building without asserts, we can test it. #ifdef DISABLE_ASSERTS_IN_UNIT_TESTS ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, "!xqunszqnaolrrfmtzgaki7mxelgvkj", mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); #endif // Test invalid descriptor ret = rend_cache_store_v2_desc_as_client("invalid descriptor", "3xqunszqnaolrrfmtzgaki7mxelgvkje", mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); // TODO: it doesn't seem to be possible to test invalid service ID condition. // that means it is likely not possible to have that condition without // earlier conditions failing first (such as signature checking of the desc) rend_cache_free_all(); // Test mismatch between service ID and onion address rend_cache_init(); strncpy(mock_rend_query->onion_address, "abc", REND_SERVICE_ID_LEN_BASE32+1); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); rend_cache_free_all(); rend_data_free(mock_rend_query); // Test incorrect descriptor ID rend_cache_init(); mock_rend_query = mock_rend_data(service_id); desc_id_base32[0]++; ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); desc_id_base32[0]--; rend_cache_free_all(); // Test too old descriptor rend_cache_init(); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_data_free(mock_rend_query); generate_desc(TIME_IN_THE_PAST, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); rend_cache_free_all(); // Test too new descriptor (in the future) rend_cache_init(); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_data_free(mock_rend_query); generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); rend_cache_free_all(); // Test when a descriptor is already in the cache rend_cache_init(); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_data_free(mock_rend_query); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, 0); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, &entry); tt_int_op(ret, OP_EQ, 0); tt_assert(entry); rend_cache_free_all(); // Test unsuccessful decrypting of introduction points rend_cache_init(); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_data_free(mock_rend_query); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); mock_rend_query->auth_type = REND_BASIC_AUTH; client_cookie[0] = 'A'; memcpy(mock_rend_query->descriptor_cookie, client_cookie, REND_DESC_COOKIE_LEN); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, 0); rend_cache_free_all(); // Test successful run when we have REND_BASIC_AUTH but not cookie rend_cache_init(); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_data_free(mock_rend_query); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); mock_rend_query = mock_rend_data(service_id); mock_rend_query->auth_type = REND_BASIC_AUTH; base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, 0); rend_cache_free_all(); // Test when we have no introduction points rend_cache_init(); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_data_free(mock_rend_query); generate_desc(RECENT_TIME, &desc_holder, &service_id, 0); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); rend_cache_free_all(); // Test when we have too many intro points rend_cache_init(); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_data_free(mock_rend_query); generate_desc(RECENT_TIME, &desc_holder, &service_id, MAX_INTRO_POINTS+1); mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder->desc_id, DIGEST_LEN); ret = rend_cache_store_v2_desc_as_client(desc_holder->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, -1); done: rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_cache_free_all(); rend_data_free(mock_rend_query); }
static void test_rend_cache_store_v2_desc_as_client_with_different_time(void *data) { int ret; rend_data_t *mock_rend_query; char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; rend_service_descriptor_t *generated = NULL; smartlist_t *descs = smartlist_new(); time_t t; char *service_id = NULL; rend_encoded_v2_service_descriptor_t *desc_holder_newer; rend_encoded_v2_service_descriptor_t *desc_holder_older; t = time(NULL); rend_cache_init(); create_descriptor(&generated, &service_id, 3); generated->timestamp = t + RECENT_TIME; rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); desc_holder_newer = ((rend_encoded_v2_service_descriptor_t *) smartlist_get(descs, 0)); smartlist_set(descs, 0, NULL); SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d, rend_encoded_v2_service_descriptor_free(d)); smartlist_free(descs); descs = smartlist_new(); generated->timestamp = (t + RECENT_TIME) - 20; rend_encode_v2_descriptors(descs, generated, t + RECENT_TIME, 0, REND_NO_AUTH, NULL, NULL); desc_holder_older = ((rend_encoded_v2_service_descriptor_t *) smartlist_get(descs, 0)); smartlist_set(descs, 0, NULL); (void)data; // Test when a descriptor is already in the cache and it is newer than the // one we submit mock_rend_query = mock_rend_data(service_id); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_holder_newer->desc_id, DIGEST_LEN); rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, desc_id_base32, mock_rend_query, NULL); ret = rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, 0); rend_cache_free_all(); // Test when an old descriptor is in the cache and we submit a newer one rend_cache_init(); rend_cache_store_v2_desc_as_client(desc_holder_older->desc_str, desc_id_base32, mock_rend_query, NULL); ret = rend_cache_store_v2_desc_as_client(desc_holder_newer->desc_str, desc_id_base32, mock_rend_query, NULL); tt_int_op(ret, OP_EQ, 0); done: rend_encoded_v2_service_descriptor_free(desc_holder_newer); rend_encoded_v2_service_descriptor_free(desc_holder_older); SMARTLIST_FOREACH(descs, rend_encoded_v2_service_descriptor_t *, d, rend_encoded_v2_service_descriptor_free(d)); smartlist_free(descs); rend_service_descriptor_free(generated); tor_free(service_id); rend_cache_free_all(); rend_data_free(mock_rend_query); }
/* Make sure rend_data_t is valid at creation, destruction and when * duplicated. */ static void test_hs_rend_data(void *arg) { int rep; rend_data_t *client = NULL, *client_dup = NULL; /* Binary format of a descriptor ID. */ char desc_id[DIGEST_LEN]; char client_cookie[REND_DESC_COOKIE_LEN]; time_t now = time(NULL); rend_data_t *service_dup = NULL; rend_data_t *service = NULL; (void)arg; base32_decode(desc_id, sizeof(desc_id), STR_DESC_ID_BASE32, REND_DESC_ID_V2_LEN_BASE32); memset(client_cookie, 'e', sizeof(client_cookie)); client = rend_data_client_create(STR_HS_ADDR, desc_id, client_cookie, REND_NO_AUTH); tt_assert(client); rend_data_v2_t *client_v2 = TO_REND_DATA_V2(client); tt_int_op(client_v2->auth_type, OP_EQ, REND_NO_AUTH); tt_str_op(client_v2->onion_address, OP_EQ, STR_HS_ADDR); tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id)); tt_mem_op(client_v2->descriptor_cookie, OP_EQ, client_cookie, sizeof(client_cookie)); tt_assert(client->hsdirs_fp); tt_int_op(smartlist_len(client->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { int ret = rend_compute_v2_desc_id(desc_id, client_v2->onion_address, client_v2->descriptor_cookie, now, rep); /* That shouldn't never fail. */ tt_int_op(ret, OP_EQ, 0); tt_mem_op(client_v2->descriptor_id[rep], OP_EQ, desc_id, sizeof(desc_id)); } /* The rest should be zeroed because this is a client request. */ tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), OP_EQ, 1); tt_int_op(tor_digest_is_zero(client->rend_cookie), OP_EQ, 1); /* Test dup(). */ client_dup = rend_data_dup(client); tt_assert(client_dup); rend_data_v2_t *client_dup_v2 = TO_REND_DATA_V2(client_dup); tt_int_op(client_dup_v2->auth_type, OP_EQ, client_v2->auth_type); tt_str_op(client_dup_v2->onion_address, OP_EQ, client_v2->onion_address); tt_mem_op(client_dup_v2->desc_id_fetch, OP_EQ, client_v2->desc_id_fetch, sizeof(client_dup_v2->desc_id_fetch)); tt_mem_op(client_dup_v2->descriptor_cookie, OP_EQ, client_v2->descriptor_cookie, sizeof(client_dup_v2->descriptor_cookie)); tt_assert(client_dup->hsdirs_fp); tt_int_op(smartlist_len(client_dup->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { tt_mem_op(client_dup_v2->descriptor_id[rep], OP_EQ, client_v2->descriptor_id[rep], DIGEST_LEN); } /* The rest should be zeroed because this is a client request. */ tt_int_op(tor_digest_is_zero(client_dup_v2->rend_pk_digest), OP_EQ, 1); tt_int_op(tor_digest_is_zero(client_dup->rend_cookie), OP_EQ, 1); rend_data_free(client); client = NULL; rend_data_free(client_dup); client_dup = NULL; /* Reset state. */ base32_decode(desc_id, sizeof(desc_id), STR_DESC_ID_BASE32, REND_DESC_ID_V2_LEN_BASE32); memset(client_cookie, 'e', sizeof(client_cookie)); /* Try with different parameters here for which some content should be * zeroed out. */ client = rend_data_client_create(NULL, desc_id, NULL, REND_BASIC_AUTH); tt_assert(client); client_v2 = TO_REND_DATA_V2(client); tt_int_op(client_v2->auth_type, OP_EQ, REND_BASIC_AUTH); tt_int_op(strlen(client_v2->onion_address), OP_EQ, 0); tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id)); tt_int_op(tor_mem_is_zero(client_v2->descriptor_cookie, sizeof(client_v2->descriptor_cookie)), OP_EQ, 1); tt_assert(client->hsdirs_fp); tt_int_op(smartlist_len(client->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { tt_int_op(tor_digest_is_zero(client_v2->descriptor_id[rep]), OP_EQ, 1); } /* The rest should be zeroed because this is a client request. */ tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), OP_EQ, 1); tt_int_op(tor_digest_is_zero(client->rend_cookie), OP_EQ, 1); rend_data_free(client); client = NULL; /* Let's test the service object now. */ char rend_pk_digest[DIGEST_LEN]; uint8_t rend_cookie[DIGEST_LEN]; memset(rend_pk_digest, 'f', sizeof(rend_pk_digest)); memset(rend_cookie, 'g', sizeof(rend_cookie)); service = rend_data_service_create(STR_HS_ADDR, rend_pk_digest, rend_cookie, REND_NO_AUTH); tt_assert(service); rend_data_v2_t *service_v2 = TO_REND_DATA_V2(service); tt_int_op(service_v2->auth_type, OP_EQ, REND_NO_AUTH); tt_str_op(service_v2->onion_address, OP_EQ, STR_HS_ADDR); tt_mem_op(service_v2->rend_pk_digest, OP_EQ, rend_pk_digest, sizeof(rend_pk_digest)); tt_mem_op(service->rend_cookie, OP_EQ, rend_cookie, sizeof(rend_cookie)); tt_assert(service->hsdirs_fp); tt_int_op(smartlist_len(service->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { tt_int_op(tor_digest_is_zero(service_v2->descriptor_id[rep]), OP_EQ, 1); } /* The rest should be zeroed because this is a service request. */ tt_int_op(tor_digest_is_zero(service_v2->descriptor_cookie), OP_EQ, 1); tt_int_op(tor_digest_is_zero(service_v2->desc_id_fetch), OP_EQ, 1); /* Test dup(). */ service_dup = rend_data_dup(service); rend_data_v2_t *service_dup_v2 = TO_REND_DATA_V2(service_dup); tt_assert(service_dup); tt_int_op(service_dup_v2->auth_type, OP_EQ, service_v2->auth_type); tt_str_op(service_dup_v2->onion_address, OP_EQ, service_v2->onion_address); tt_mem_op(service_dup_v2->rend_pk_digest, OP_EQ, service_v2->rend_pk_digest, sizeof(service_dup_v2->rend_pk_digest)); tt_mem_op(service_dup->rend_cookie, OP_EQ, service->rend_cookie, sizeof(service_dup->rend_cookie)); tt_assert(service_dup->hsdirs_fp); tt_int_op(smartlist_len(service_dup->hsdirs_fp), OP_EQ, 0); for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) { tt_assert(tor_digest_is_zero(service_dup_v2->descriptor_id[rep])); } /* The rest should be zeroed because this is a service request. */ tt_int_op(tor_digest_is_zero(service_dup_v2->descriptor_cookie), OP_EQ, 1); tt_int_op(tor_digest_is_zero(service_dup_v2->desc_id_fetch), OP_EQ, 1); done: rend_data_free(service); rend_data_free(service_dup); rend_data_free(client); rend_data_free(client_dup); }
/** Deallocate space associated with circ. */ static void circuit_free(circuit_t *circ) { void *mem; size_t memlen; tor_assert(circ); if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); mem = ocirc; memlen = sizeof(origin_circuit_t); tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC); if (ocirc->build_state) { if (ocirc->build_state->chosen_exit) extend_info_free(ocirc->build_state->chosen_exit); if (ocirc->build_state->pending_final_cpath) circuit_free_cpath_node(ocirc->build_state->pending_final_cpath); } tor_free(ocirc->build_state); circuit_free_cpath(ocirc->cpath); if (ocirc->intro_key) crypto_free_pk_env(ocirc->intro_key); if (ocirc->rend_data) rend_data_free(ocirc->rend_data); } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); mem = ocirc; memlen = sizeof(or_circuit_t); tor_assert(circ->magic == OR_CIRCUIT_MAGIC); if (ocirc->p_crypto) crypto_free_cipher_env(ocirc->p_crypto); if (ocirc->p_digest) crypto_free_digest_env(ocirc->p_digest); if (ocirc->n_crypto) crypto_free_cipher_env(ocirc->n_crypto); if (ocirc->n_digest) crypto_free_digest_env(ocirc->n_digest); if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC); other->rend_splice = NULL; } /* remove from map. */ circuit_set_p_circid_orconn(ocirc, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(ô->p_conn_cells); } if (circ->n_hop) extend_info_free(circ->n_hop); tor_free(circ->n_conn_onionskin); /* Remove from map. */ circuit_set_n_circid_orconn(circ, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(&circ->n_conn_cells); memset(circ, 0xAA, memlen); /* poison memory */ tor_free(mem); }
/** Deallocate space associated with circ. */ static void circuit_free(circuit_t *circ) { void *mem; size_t memlen; if (!circ) return; if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); mem = ocirc; memlen = sizeof(origin_circuit_t); tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC); if (ocirc->build_state) { extend_info_free(ocirc->build_state->chosen_exit); circuit_free_cpath_node(ocirc->build_state->pending_final_cpath); cpath_ref_decref(ocirc->build_state->service_pending_final_cpath_ref); } tor_free(ocirc->build_state); circuit_free_cpath(ocirc->cpath); crypto_pk_free(ocirc->intro_key); rend_data_free(ocirc->rend_data); tor_free(ocirc->dest_address); if (ocirc->socks_username) { memwipe(ocirc->socks_username, 0x12, ocirc->socks_username_len); tor_free(ocirc->socks_username); } if (ocirc->socks_password) { memwipe(ocirc->socks_password, 0x06, ocirc->socks_password_len); tor_free(ocirc->socks_password); } } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); /* Remember cell statistics for this circuit before deallocating. */ if (get_options()->CellStatistics) rep_hist_buffer_stats_add_circ(circ, time(NULL)); mem = ocirc; memlen = sizeof(or_circuit_t); tor_assert(circ->magic == OR_CIRCUIT_MAGIC); crypto_cipher_free(ocirc->p_crypto); crypto_digest_free(ocirc->p_digest); crypto_cipher_free(ocirc->n_crypto); crypto_digest_free(ocirc->n_digest); if (ocirc->rend_splice) { or_circuit_t *other = ocirc->rend_splice; tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC); other->rend_splice = NULL; } /* remove from map. */ circuit_set_p_circid_orconn(ocirc, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(ô->p_conn_cells); } extend_info_free(circ->n_hop); tor_free(circ->n_conn_onionskin); /* Remove from map. */ circuit_set_n_circid_orconn(circ, 0, NULL); /* Clear cell queue _after_ removing it from the map. Otherwise our * "active" checks will be violated. */ cell_queue_clear(&circ->n_conn_cells); memwipe(mem, 0xAA, memlen); /* poison memory */ tor_free(mem); }