/** We simulate a failure to create an ESTABLISH_INTRO cell */ static void test_gen_establish_intro_cell_bad(void *arg) { (void) arg; ssize_t cell_len = 0; trn_cell_establish_intro_t *cell = NULL; char circ_nonce[DIGEST_LEN] = {0}; hs_service_intro_point_t *ip = NULL; MOCK(ed25519_sign_prefixed, mock_ed25519_sign_prefixed); crypto_rand(circ_nonce, sizeof(circ_nonce)); setup_full_capture_of_logs(LOG_WARN); /* Easiest way to make that function fail is to mock the ed25519_sign_prefixed() function and make it fail. */ cell = trn_cell_establish_intro_new(); tt_assert(cell); ip = service_intro_point_new(NULL); cell_len = hs_cell_build_establish_intro(circ_nonce, ip, NULL); service_intro_point_free(ip); expect_log_msg_containing("Unable to make signature for " "ESTABLISH_INTRO cell."); teardown_capture_of_logs(); tt_i64_op(cell_len, OP_EQ, -1); done: trn_cell_establish_intro_free(cell); UNMOCK(ed25519_sign_prefixed); }
/* Send a legit ESTABLISH_INTRO cell but slightly change the signature. Should * fail. */ static void test_establish_intro_wrong_sig(void *arg) { int retval; char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; or_circuit_t *intro_circ = or_circuit_new(0,NULL); (void) arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we attempt to parse it. */ cell_len = new_establish_intro_encoded_cell(circ_nonce, cell_body); tt_i64_op(cell_len, OP_GT, 0); /* Mutate the last byte (signature)! :) */ cell_body[cell_len - 1]++; /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, (size_t)cell_len); expect_log_msg_containing("Failed to verify ESTABLISH_INTRO cell."); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: circuit_free_(TO_CIRCUIT(intro_circ)); }
/* Try sending an ESTABLISH_INTRO cell on a circuit that is already an intro * point. Should fail. */ static void test_establish_intro_wrong_purpose(void *arg) { int retval; ssize_t cell_len = 0; char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; or_circuit_t *intro_circ = or_circuit_new(0,NULL); (void)arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); memcpy(intro_circ->rend_circ_nonce, circ_nonce, DIGEST_LEN); /* Set a bad circuit purpose!! :) */ circuit_change_purpose(TO_CIRCUIT(intro_circ), CIRCUIT_PURPOSE_INTRO_POINT); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we attempt to parse it. */ cell_len = new_establish_intro_encoded_cell(circ_nonce, cell_body); tt_i64_op(cell_len, OP_GT, 0); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("Rejecting ESTABLISH_INTRO on non-OR circuit."); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: circuit_free_(TO_CIRCUIT(intro_circ)); }
/** Test warn_early_consensus(), expecting a warning */ static void test_warn_early_consensus_yes(const networkstatus_t *c, time_t now, long offset) { mock_apparent_skew = 0; setup_capture_of_logs(LOG_WARN); warn_early_consensus(c, "microdesc", now + offset); /* Can't use expect_single_log_msg() because of unrecognized authorities */ expect_log_msg_containing("behind the time published in the consensus"); tt_int_op(mock_apparent_skew, OP_EQ, offset); done: teardown_capture_of_logs(); }
/** Test early consensus */ static void test_early_consensus(void *arg) { time_t now = time(NULL); unsigned long offset = 0; int retval = 0; retval = test_skew_common(arg, now, &offset); /* Can't use expect_single_log_msg() because of unrecognized authorities */ expect_log_msg_containing("behind the time published in the consensus"); tt_int_op(retval, OP_EQ, 0); /* This depends on construct_consensus() setting valid_after=now+1000 */ tt_int_op(mock_apparent_skew, OP_EQ, offset - 1000); done: teardown_capture_of_logs(); UNMOCK(clock_skew_warning); }
/* Send a legit ESTABLISH_INTRO cell but with a wrong sig length. Should * fail. */ static void test_establish_intro_wrong_sig_len(void *arg) { int retval; char circ_nonce[DIGEST_LEN] = {0}; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; size_t bad_sig_len = ED25519_SIG_LEN - 1; trn_cell_establish_intro_t *cell = NULL; or_circuit_t *intro_circ = or_circuit_new(0,NULL); (void) arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we * attempt to parse it. */ cell_len = new_establish_intro_cell(circ_nonce, &cell); tt_i64_op(cell_len, OP_GT, 0); tt_assert(cell); /* Mangle the signature length. */ trn_cell_establish_intro_set_sig_len(cell, bad_sig_len); trn_cell_establish_intro_setlen_sig(cell, bad_sig_len); /* Encode cell. */ cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), cell); tt_int_op(cell_len, OP_GT, 0); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("ESTABLISH_INTRO sig len is invalid"); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: trn_cell_establish_intro_free(cell); circuit_free_(TO_CIRCUIT(intro_circ)); }
/* Send an empty ESTABLISH_INTRO cell. Should fail. */ static void test_establish_intro_wrong_keytype(void *arg) { int retval; or_circuit_t *intro_circ = or_circuit_new(0,NULL); char circ_nonce[DIGEST_LEN] = {0}; (void) arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Receive the cell. Should fail. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, (uint8_t *) "", 0); expect_log_msg_containing("Empty ESTABLISH_INTRO cell."); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: circuit_free_(TO_CIRCUIT(intro_circ)); }
static void test_channel_duplicates(void *arg) { channel_t *chan = NULL; routerstatus_t rs; (void) arg; setup_full_capture_of_logs(LOG_INFO); /* Try a flat call with channel nor connections. */ channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); mock_ns = tor_malloc_zero(sizeof(*mock_ns)); mock_ns->routerstatus_list = smartlist_new(); MOCK(networkstatus_get_latest_consensus, mock_networkstatus_get_latest_consensus); chan = new_fake_channel(); tt_assert(chan); chan->is_canonical = test_chan_is_canonical; memset(chan->identity_digest, 'A', sizeof(chan->identity_digest)); channel_add_to_digest_map(chan); tt_ptr_op(channel_find_by_remote_identity(chan->identity_digest, NULL), OP_EQ, chan); /* No relay has been associated with this channel. */ channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); /* Associate relay to this connection in the consensus. */ memset(&rs, 0, sizeof(rs)); memset(rs.identity_digest, 'A', sizeof(rs.identity_digest)); smartlist_add(mock_ns->routerstatus_list, &rs); /* Non opened channel. */ chan->state = CHANNEL_STATE_CLOSING; channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); chan->state = CHANNEL_STATE_OPEN; channel_check_for_duplicates(); expect_log_msg_containing( "Found 1 connections to 1 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); test_chan_should_be_canonical = 1; channel_check_for_duplicates(); expect_log_msg_containing( "Found 1 connections to 1 relays. Found 1 current canonical " "connections, in 1 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); teardown_capture_of_logs(); done: free_fake_channel(chan); smartlist_clear(mock_ns->routerstatus_list); networkstatus_vote_free(mock_ns); UNMOCK(networkstatus_get_latest_consensus); }
static void test_router_check_descriptor_bandwidth_changed(void *arg) { (void)arg; routerinfo_t routerinfo; memset(&routerinfo, 0, sizeof(routerinfo)); mock_router_get_my_routerinfo_result = NULL; MOCK(we_are_hibernating, mock_we_are_not_hibernating); MOCK(router_get_my_routerinfo, mock_router_get_my_routerinfo); mock_router_get_my_routerinfo_result = &routerinfo; /* When uptime is less than 24h, no previous bandwidth, no last_changed * Uptime: 10800, last_changed: 0, Previous bw: 0, Current bw: 0 */ routerinfo.bandwidthcapacity = 0; MOCK(get_uptime, mock_get_uptime_3h); setup_full_capture_of_logs(LOG_INFO); check_descriptor_bandwidth_changed(time(NULL)); expect_log_msg_not_containing( "Measured bandwidth has changed; rebuilding descriptor."); teardown_capture_of_logs(); /* When uptime is less than 24h, previous bandwidth, * last_changed more than 3h ago * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */ routerinfo.bandwidthcapacity = 10000; setup_full_capture_of_logs(LOG_INFO); check_descriptor_bandwidth_changed(time(NULL)); expect_log_msg_containing( "Measured bandwidth has changed; rebuilding descriptor."); teardown_capture_of_logs(); /* When uptime is less than 24h, previous bandwidth, * last_changed more than 3h ago, and hibernating * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */ UNMOCK(we_are_hibernating); MOCK(we_are_hibernating, mock_we_are_hibernating); routerinfo.bandwidthcapacity = 10000; setup_full_capture_of_logs(LOG_INFO); check_descriptor_bandwidth_changed(time(NULL)); expect_log_msg_not_containing( "Measured bandwidth has changed; rebuilding descriptor."); teardown_capture_of_logs(); UNMOCK(we_are_hibernating); MOCK(we_are_hibernating, mock_we_are_not_hibernating); /* When uptime is less than 24h, last_changed is not more than 3h ago * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 0 */ setup_full_capture_of_logs(LOG_INFO); check_descriptor_bandwidth_changed(time(NULL)); expect_log_msg_not_containing( "Measured bandwidth has changed; rebuilding descriptor."); teardown_capture_of_logs(); /* When uptime is less than 24h and bandwidthcapacity does not change * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 20001 */ MOCK(rep_hist_bandwidth_assess, mock_rep_hist_bandwidth_assess); setup_full_capture_of_logs(LOG_INFO); check_descriptor_bandwidth_changed(time(NULL) + 6*60*60 + 1); expect_log_msg_containing( "Measured bandwidth has changed; rebuilding descriptor."); UNMOCK(get_uptime); UNMOCK(rep_hist_bandwidth_assess); teardown_capture_of_logs(); /* When uptime is more than 24h */ MOCK(get_uptime, mock_get_uptime_1d); setup_full_capture_of_logs(LOG_INFO); check_descriptor_bandwidth_changed(time(NULL)); expect_log_msg_not_containing( "Measured bandwidth has changed; rebuilding descriptor."); teardown_capture_of_logs(); done: UNMOCK(get_uptime); UNMOCK(router_get_my_routerinfo); UNMOCK(we_are_hibernating); }
/** Test that we will use our directory guards to fetch mds even if we don't * have any dirinfo (tests bug #23862). */ static void test_directory_guard_fetch_with_no_dirinfo(void *arg) { int retval; char *consensus_text_md = NULL; or_options_t *options = get_options_mutable(); time_t now = time(NULL); (void) arg; hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE); /* Initialize the SRV subsystem */ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m); mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, strlen(AUTHORITY_CERT_1), NULL); sr_init(0); UNMOCK(get_my_v3_authority_cert); /* Initialize the entry node configuration from the ticket */ options->UseEntryGuards = 1; options->StrictNodes = 1; get_options_mutable()->EntryNodes = routerset_new(); routerset_parse(get_options_mutable()->EntryNodes, "2121212121212121212121212121212121212121", "foo"); /* Mock some functions */ dummy_state = tor_malloc_zero(sizeof(or_state_t)); MOCK(get_or_state, get_or_state_replacement); MOCK(directory_initiate_request, mock_directory_initiate_request); /* we need to mock this one to avoid memleaks */ MOCK(circuit_guard_state_new, mock_circuit_guard_state_new); /* Call guards_update_all() to simulate loading our state file (see * entry_guards_load_guards_from_state() and ticket #23989). */ guards_update_all(); /* Test logic: Simulate the arrival of a new consensus when we have no * dirinfo at all. Tor will need to fetch the mds from the consensus. Make * sure that Tor will use the specified entry guard instead of relying on the * fallback directories. */ /* Fixup the dirconn that will deliver the consensus */ dir_connection_t *conn = dir_connection_new(AF_INET); tor_addr_from_ipv4h(&conn->base_.addr, 0x7f000001); conn->base_.port = 8800; TO_CONN(conn)->address = tor_strdup("127.0.0.1"); conn->base_.purpose = DIR_PURPOSE_FETCH_CONSENSUS; conn->requested_resource = tor_strdup("ns"); /* Construct a consensus */ construct_consensus(&consensus_text_md, now); tt_assert(consensus_text_md); /* Place the consensus in the dirconn */ response_handler_args_t args; memset(&args, 0, sizeof(response_handler_args_t)); args.status_code = 200; args.body = consensus_text_md; args.body_len = strlen(consensus_text_md); /* Update approx time so that the consensus is considered live */ update_approx_time(now+1010); setup_capture_of_logs(LOG_DEBUG); /* Now handle the consensus */ retval = handle_response_fetch_consensus(conn, &args); tt_int_op(retval, OP_EQ, 0); /* Make sure that our primary guard was chosen */ expect_log_msg_containing("Selected primary guard router3"); done: tor_free(consensus_text_md); tor_free(dummy_state); connection_free_minimal(TO_CONN(conn)); entry_guards_free_all(); teardown_capture_of_logs(); }
static void test_invalid_service(void *arg) { int ret; (void) arg; /* Try with a missing port configuration. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 1\n"; /* Wrong not supported version. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceVersion must be between 2 and 3"); teardown_capture_of_logs(); } /* Bad value of HiddenServiceAllowUnknownPorts. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServiceAllowUnknownPorts 2\n"; /* Should be 0 or 1. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceAllowUnknownPorts must be " "between 0 and 1, not 2"); teardown_capture_of_logs(); } /* Bad value of HiddenServiceDirGroupReadable */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServiceDirGroupReadable 2\n"; /* Should be 0 or 1. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceDirGroupReadable must be " "between 0 and 1, not 2"); teardown_capture_of_logs(); } /* Bad value of HiddenServiceMaxStreamsCloseCircuit */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServiceMaxStreamsCloseCircuit 2\n"; /* Should be 0 or 1. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceMaxStreamsCloseCircuit must " "be between 0 and 1, not 2"); teardown_capture_of_logs(); } /* Too much max streams. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 80\n" "HiddenServiceMaxStreams 65536\n"; /* One too many. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceMaxStreams must be between " "0 and 65535, not 65536"); teardown_capture_of_logs(); } /* Duplicate directory directive. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 80\n" "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 81\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("Another hidden service is already " "configured for directory"); teardown_capture_of_logs(); } /* Bad port. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 65536\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("Missing or invalid port"); teardown_capture_of_logs(); } /* Bad target addr:port separation. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 80 127.0.0.1 8000\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServicePort parse error: " "invalid port mapping"); teardown_capture_of_logs(); } /* Out of order directives. */ { const char *conf = "HiddenServiceVersion 2\n" "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServicePort 80\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, 1); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceVersion with no preceding " "HiddenServiceDir directive"); teardown_capture_of_logs(); } done: ; }
static void test_invalid_service_v3(void *arg) { int validate_only = 1, ret; (void) arg; /* Try with a missing port configuration. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 3\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("with no ports configured."); teardown_capture_of_logs(); } /* Too many introduction points. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 3\n" "HiddenServicePort 80\n" "HiddenServiceNumIntroductionPoints 21\n"; /* One too many. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceNumIntroductionPoints must " "be between 3 and 20, not 21."); teardown_capture_of_logs(); } /* Too little introduction points. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 3\n" "HiddenServicePort 80\n" "HiddenServiceNumIntroductionPoints 1\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceNumIntroductionPoints must " "be between 3 and 20, not 1."); teardown_capture_of_logs(); } /* v2-specific HiddenServiceAuthorizeClient set. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 3\n" "HiddenServiceAuthorizeClient stealth client1\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("Hidden service option " "HiddenServiceAuthorizeClient is incompatible " "with version 3 of service in " "/tmp/tor-test-hs-RANDOM/hs1"); teardown_capture_of_logs(); } done: ; }
static void test_invalid_service_v2(void *arg) { int validate_only = 1, ret; (void) arg; /* Try with a missing port configuration. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("with no ports configured."); teardown_capture_of_logs(); } /* Too many introduction points. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 80\n" "HiddenServiceNumIntroductionPoints 11\n"; /* One too many. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceNumIntroductionPoints should " "be between 0 and 10, not 11"); teardown_capture_of_logs(); } /* Too little introduction points. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 80\n" "HiddenServiceNumIntroductionPoints -1\n"; setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceNumIntroductionPoints should " "be between 0 and 10, not -1"); teardown_capture_of_logs(); } /* Bad authorized client type. */ { const char *conf = "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" "HiddenServiceVersion 2\n" "HiddenServicePort 80\n" "HiddenServiceAuthorizeClient blah alice,bob\n"; /* blah is no good. */ setup_full_capture_of_logs(LOG_WARN); ret = helper_config_service(conf, validate_only); tt_int_op(ret, OP_EQ, -1); expect_log_msg_containing("HiddenServiceAuthorizeClient contains " "unrecognized auth-type"); teardown_capture_of_logs(); } done: ; }
/* Send a legit ESTABLISH_INTRO cell but with a wrong MAC. Should fail. */ static void test_establish_intro_wrong_mac(void *arg) { int retval; char circ_nonce[DIGEST_LEN] = {0}; ssize_t cell_len = 0; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; trn_cell_establish_intro_t *cell = NULL; or_circuit_t *intro_circ = or_circuit_new(0,NULL); (void) arg; /* Get the auth key of the intro point */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we * attempt to parse it. */ cell_len = new_establish_intro_cell(circ_nonce, &cell); tt_i64_op(cell_len, OP_GT, 0); tt_assert(cell); /* Mangle one byte of the MAC. */ uint8_t *handshake_ptr = trn_cell_establish_intro_getarray_handshake_mac(cell); handshake_ptr[TRUNNEL_SHA3_256_LEN - 1]++; /* We need to resign the payload with that change. */ { ed25519_signature_t sig; ed25519_keypair_t key_struct; /* New keypair for the signature since we don't have access to the private * key material generated earlier when creating the cell. */ retval = ed25519_keypair_generate(&key_struct, 0); tt_int_op(retval, OP_EQ, 0); uint8_t *auth_key_ptr = trn_cell_establish_intro_getarray_auth_key(cell); memcpy(auth_key_ptr, key_struct.pubkey.pubkey, ED25519_PUBKEY_LEN); /* Encode payload so we can sign it. */ cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), cell); tt_i64_op(cell_len, OP_GT, 0); retval = ed25519_sign_prefixed(&sig, cell_body, cell_len - (ED25519_SIG_LEN + sizeof(cell->sig_len)), ESTABLISH_INTRO_SIG_PREFIX, &key_struct); tt_int_op(retval, OP_EQ, 0); /* And write the signature to the cell */ uint8_t *sig_ptr = trn_cell_establish_intro_getarray_sig(cell); memcpy(sig_ptr, sig.sig, cell->sig_len); /* Re-encode with the new signature. */ cell_len = trn_cell_establish_intro_encode(cell_body, sizeof(cell_body), cell); tt_i64_op(cell_len, OP_GT, 0); } /* Receive the cell. Should fail because our MAC is wrong. */ setup_full_capture_of_logs(LOG_INFO); retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len); expect_log_msg_containing("ESTABLISH_INTRO handshake_auth not as expected"); teardown_capture_of_logs(); tt_int_op(retval, OP_EQ, -1); done: trn_cell_establish_intro_free(cell); circuit_free_(TO_CIRCUIT(intro_circ)); }