static void test_replaycache_realtime(void *arg) { replaycache_t *r = NULL; /* * Negative so we fail if replaycache_add_test_and_elapsed() doesn't * write to elapsed. */ time_t elapsed = -1; int result; /* Test the realtime as well as *_internal() entry points */ (void)arg; r = replaycache_new(600, 300); tt_assert(r != NULL); /* This should miss */ result = replaycache_add_and_test(r, test_buffer, strlen(test_buffer)); tt_int_op(result,OP_EQ, 0); /* This should hit */ result = replaycache_add_and_test(r, test_buffer, strlen(test_buffer)); tt_int_op(result,OP_EQ, 1); /* This should hit and return a small elapsed time */ result = replaycache_add_test_and_elapsed(r, test_buffer, strlen(test_buffer), &elapsed); tt_int_op(result,OP_EQ, 1); tt_assert(elapsed >= 0); tt_assert(elapsed <= 5); /* Scrub it to exercise that entry point too */ replaycache_scrub_if_needed(r); done: if (r) replaycache_free(r); return; }
/* We just received an INTRODUCE2 cell on the established introduction circuit * circ. Handle the INTRODUCE2 payload of size payload_len for the given * circuit and service. This cell is associated with the intro point object ip * and the subcredential. Return 0 on success else a negative value. */ int hs_circ_handle_introduce2(const hs_service_t *service, const origin_circuit_t *circ, hs_service_intro_point_t *ip, const uint8_t *subcredential, const uint8_t *payload, size_t payload_len) { int ret = -1; time_t elapsed; hs_cell_introduce2_data_t data; tor_assert(service); tor_assert(circ); tor_assert(ip); tor_assert(subcredential); tor_assert(payload); /* Populate the data structure with everything we need for the cell to be * parsed, decrypted and key material computed correctly. */ data.auth_pk = &ip->auth_key_kp.pubkey; data.enc_kp = &ip->enc_key_kp; data.subcredential = subcredential; data.payload = payload; data.payload_len = payload_len; data.link_specifiers = smartlist_new(); data.replay_cache = ip->replay_cache; if (hs_cell_parse_introduce2(&data, circ, service) < 0) { goto done; } /* Check whether we've seen this REND_COOKIE before to detect repeats. */ if (replaycache_add_test_and_elapsed( service->state.replay_cache_rend_cookie, data.rendezvous_cookie, sizeof(data.rendezvous_cookie), &elapsed)) { /* A Tor client will send a new INTRODUCE1 cell with the same REND_COOKIE * as its previous one if its intro circ times out while in state * CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT. If we received the first * INTRODUCE1 cell (the intro-point relay converts it into an INTRODUCE2 * cell), we are already trying to connect to that rend point (and may * have already succeeded); drop this cell. */ log_info(LD_REND, "We received an INTRODUCE2 cell with same REND_COOKIE " "field %ld seconds ago. Dropping cell.", (long int) elapsed); goto done; } /* At this point, we just confirmed that the full INTRODUCE2 cell is valid * so increment our counter that we've seen one on this intro point. */ ip->introduce2_count++; /* Launch rendezvous circuit with the onion key and rend cookie. */ launch_rendezvous_point_circuit(service, ip, &data); /* Success. */ ret = 0; done: SMARTLIST_FOREACH(data.link_specifiers, link_specifier_t *, lspec, link_specifier_free(lspec)); smartlist_free(data.link_specifiers); memwipe(&data, 0, sizeof(data)); return ret; }