test_hs_service.c (98431B)
1 /* Copyright (c) 2016-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 /** 5 * \file test_hs_service.c 6 * \brief Test hidden service functionality. 7 */ 8 9 #define CIRCUITBUILD_PRIVATE 10 #define CIRCUITLIST_PRIVATE 11 #define CONFIG_PRIVATE 12 #define CONNECTION_PRIVATE 13 #define CONNECTION_EDGE_PRIVATE 14 #define CRYPTO_PRIVATE 15 #define HS_COMMON_PRIVATE 16 #define HS_SERVICE_PRIVATE 17 #define HS_INTROPOINT_PRIVATE 18 #define HS_CIRCUIT_PRIVATE 19 #define MAINLOOP_PRIVATE 20 #define NETWORKSTATUS_PRIVATE 21 #define STATEFILE_PRIVATE 22 #define CHANNEL_OBJECT_PRIVATE 23 #define HS_CLIENT_PRIVATE 24 #define CRYPT_PATH_PRIVATE 25 26 #include "test/test.h" 27 #include "test/test_helpers.h" 28 #include "test/log_test_helpers.h" 29 #include "test/hs_test_helpers.h" 30 31 #include "core/or/or.h" 32 #include "app/config/config.h" 33 #include "app/config/statefile.h" 34 #include "core/crypto/hs_ntor.h" 35 #include "core/mainloop/connection.h" 36 #include "core/mainloop/mainloop.h" 37 #include "core/or/circuitbuild.h" 38 #include "core/or/circuitlist.h" 39 #include "core/or/circuituse.h" 40 #include "core/or/connection_edge.h" 41 #include "core/or/edge_connection_st.h" 42 #include "core/or/relay.h" 43 #include "core/or/versions.h" 44 #include "feature/dirauth/dirvote.h" 45 #include "feature/dirauth/shared_random_state.h" 46 #include "feature/dirauth/voting_schedule.h" 47 #include "feature/hs/hs_circuit.h" 48 #include "feature/hs/hs_circuitmap.h" 49 #include "feature/hs/hs_client.h" 50 #include "feature/hs/hs_common.h" 51 #include "feature/hs/hs_config.h" 52 #include "feature/hs/hs_ident.h" 53 #include "feature/hs/hs_ob.h" 54 #include "feature/hs/hs_cell.h" 55 #include "feature/hs/hs_intropoint.h" 56 #include "feature/hs/hs_metrics.h" 57 #include "feature/hs/hs_service.h" 58 #include "feature/nodelist/networkstatus.h" 59 #include "feature/nodelist/nodelist.h" 60 #include "lib/crypt_ops/crypto_rand.h" 61 #include "lib/fs/dir.h" 62 63 #include "core/or/cpath_build_state_st.h" 64 #include "core/or/crypt_path_st.h" 65 #include "core/or/crypt_path.h" 66 #include "feature/nodelist/networkstatus_st.h" 67 #include "feature/nodelist/node_st.h" 68 #include "core/or/origin_circuit_st.h" 69 #include "app/config/or_state_st.h" 70 #include "feature/nodelist/routerinfo_st.h" 71 72 /* Trunnel */ 73 #include "trunnel/hs/cell_establish_intro.h" 74 75 #ifdef HAVE_SYS_STAT_H 76 #include <sys/stat.h> 77 #endif 78 #ifdef HAVE_UNISTD_H 79 #include <unistd.h> 80 #endif 81 82 static networkstatus_t mock_ns; 83 84 static networkstatus_t * 85 mock_networkstatus_get_reasonably_live_consensus(time_t now, int flavor) 86 { 87 (void) now; 88 (void) flavor; 89 return &mock_ns; 90 } 91 92 static networkstatus_t * 93 mock_networkstatus_get_reasonably_live_consensus_null(time_t now, int flavor) 94 { 95 (void) now; 96 (void) flavor; 97 return NULL; 98 } 99 100 static or_state_t *dummy_state = NULL; 101 102 /* Mock function to get fake or state (used for rev counters) */ 103 static or_state_t * 104 get_or_state_replacement(void) 105 { 106 return dummy_state; 107 } 108 109 /* Mock function because we are not trying to test the close circuit that does 110 * an awful lot of checks on the circuit object. */ 111 static void 112 mock_circuit_mark_for_close(circuit_t *circ, int reason, int line, 113 const char *file) 114 { 115 (void) circ; 116 (void) reason; 117 (void) line; 118 (void) file; 119 return; 120 } 121 122 static size_t relay_payload_len; 123 static char relay_payload[RELAY_PAYLOAD_SIZE]; 124 125 static int 126 mock_relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, 127 uint8_t relay_command, const char *payload, 128 size_t payload_len, 129 crypt_path_t *cpath_layer, 130 const char *filename, int lineno) 131 { 132 (void) stream_id; 133 (void) circ; 134 (void) relay_command; 135 (void) payload; 136 (void) payload_len; 137 (void) cpath_layer; 138 (void) filename; 139 (void) lineno; 140 141 memcpy(relay_payload, payload, payload_len); 142 relay_payload_len = payload_len; 143 144 return 0; 145 } 146 147 static unsigned int num_intro_points = 0; 148 static unsigned int 149 mock_count_desc_circuit_established(const hs_service_descriptor_t *desc) 150 { 151 (void) desc; 152 return num_intro_points; 153 } 154 155 static int 156 mock_router_have_minimum_dir_info_false(void) 157 { 158 return 0; 159 } 160 161 /* Helper: from a set of options in conf, configure a service which will add 162 * it to the staging list of the HS subsystem. */ 163 static int 164 helper_config_service(const char *conf) 165 { 166 int ret = 0; 167 or_options_t *options = NULL; 168 tt_assert(conf); 169 options = helper_parse_options(conf); 170 tt_assert(options); 171 ret = hs_config_service_all(options, 0); 172 done: 173 or_options_free(options); 174 return ret; 175 } 176 177 /* Test: Ensure that setting up rendezvous circuits works correctly. */ 178 static void 179 test_e2e_rend_circuit_setup(void *arg) 180 { 181 ed25519_public_key_t service_pk; 182 origin_circuit_t *or_circ; 183 int retval; 184 185 /** In this test we create a v3 prop224 service-side rendezvous circuit. 186 * We simulate an HS ntor key exchange with a client, and check that 187 * the circuit was setup correctly and is ready to accept rendezvous data */ 188 189 (void) arg; 190 191 /* Now make dummy circuit */ 192 { 193 or_circ = origin_circuit_new(); 194 195 or_circ->base_.purpose = CIRCUIT_PURPOSE_S_CONNECT_REND; 196 197 or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); 198 or_circ->build_state->is_internal = 1; 199 200 /* prop224: Setup hs conn identifier on the stream */ 201 ed25519_secret_key_t sk; 202 tt_int_op(0, OP_EQ, ed25519_secret_key_generate(&sk, 0)); 203 tt_int_op(0, OP_EQ, ed25519_public_key_generate(&service_pk, &sk)); 204 205 or_circ->hs_ident = hs_ident_circuit_new(&service_pk); 206 207 TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN; 208 } 209 210 /* Check number of hops */ 211 retval = cpath_get_n_hops(&or_circ->cpath); 212 tt_int_op(retval, OP_EQ, 0); 213 214 /* Setup the circuit: do the ntor key exchange */ 215 { 216 uint8_t ntor_key_seed[DIGEST256_LEN] = {2}; 217 retval = hs_circuit_setup_e2e_rend_circ(or_circ, ntor_key_seed, 218 sizeof(ntor_key_seed), 1); 219 tt_int_op(retval, OP_EQ, 0); 220 } 221 222 /* See that a hop was added to the circuit's cpath */ 223 retval = cpath_get_n_hops(&or_circ->cpath); 224 tt_int_op(retval, OP_EQ, 1); 225 226 /* Check the digest algo */ 227 tt_int_op(crypto_digest_get_algorithm( 228 or_circ->cpath->pvt_crypto.c.tor1.f_digest), 229 OP_EQ, DIGEST_SHA3_256); 230 tt_int_op(crypto_digest_get_algorithm( 231 or_circ->cpath->pvt_crypto.c.tor1.b_digest), 232 OP_EQ, DIGEST_SHA3_256); 233 tt_assert(or_circ->cpath->pvt_crypto.c.tor1.f_crypto); 234 tt_assert(or_circ->cpath->pvt_crypto.c.tor1.b_crypto); 235 236 /* Ensure that circ purpose was changed */ 237 tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED); 238 239 done: 240 circuit_free_(TO_CIRCUIT(or_circ)); 241 } 242 243 /* Helper: Return a newly allocated and initialized origin circuit with 244 * purpose and flags. A default HS identifier is set to an ed25519 245 * authentication key for introduction point. */ 246 static origin_circuit_t * 247 helper_create_origin_circuit(int purpose, int flags) 248 { 249 origin_circuit_t *circ = NULL; 250 251 circ = origin_circuit_init(purpose, flags); 252 tor_assert(circ); 253 circ->cpath = tor_malloc_zero(sizeof(crypt_path_t)); 254 circ->cpath->magic = CRYPT_PATH_MAGIC; 255 circ->cpath->state = CPATH_STATE_OPEN; 256 circ->cpath->package_window = circuit_initial_package_window(); 257 circ->cpath->deliver_window = CIRCWINDOW_START; 258 circ->cpath->prev = circ->cpath; 259 /* Random nonce. */ 260 crypto_rand(circ->cpath->prev->rend_circ_nonce, DIGEST_LEN); 261 /* Create a default HS identifier. */ 262 circ->hs_ident = tor_malloc_zero(sizeof(hs_ident_circuit_t)); 263 264 return circ; 265 } 266 267 /* Helper: Return a newly allocated authorized client object with 268 * and a newly generated public key. */ 269 static hs_service_authorized_client_t * 270 helper_create_authorized_client(void) 271 { 272 int ret; 273 hs_service_authorized_client_t *client; 274 curve25519_secret_key_t seckey; 275 client = tor_malloc_zero(sizeof(hs_service_authorized_client_t)); 276 277 ret = curve25519_secret_key_generate(&seckey, 0); 278 tt_int_op(ret, OP_EQ, 0); 279 curve25519_public_key_generate(&client->client_pk, &seckey); 280 281 done: 282 return client; 283 } 284 285 /* Helper: Return a newly allocated authorized client object with the 286 * same client name and the same public key as the given client. */ 287 static hs_service_authorized_client_t * 288 helper_clone_authorized_client(const hs_service_authorized_client_t *client) 289 { 290 hs_service_authorized_client_t *client_out; 291 292 tor_assert(client); 293 294 client_out = tor_malloc_zero(sizeof(hs_service_authorized_client_t)); 295 memcpy(client_out->client_pk.public_key, 296 client->client_pk.public_key, CURVE25519_PUBKEY_LEN); 297 298 return client_out; 299 } 300 301 /* Helper: Return a newly allocated service object with the identity keypair 302 * sets and the current descriptor. Then register it to the global map. 303 * Caller should use hs_free_all() to free this service or remove it from the 304 * global map before freeing. */ 305 static hs_service_t * 306 helper_create_service(void) 307 { 308 /* Set a service for this circuit. */ 309 hs_service_t *service = hs_service_new(get_options()); 310 tor_assert(service); 311 service->config.version = HS_VERSION_THREE; 312 ed25519_secret_key_generate(&service->keys.identity_sk, 0); 313 ed25519_public_key_generate(&service->keys.identity_pk, 314 &service->keys.identity_sk); 315 service->desc_current = service_descriptor_new(); 316 tt_assert(service->desc_current); 317 /* Register service to global map. */ 318 int ret = register_service(get_hs_service_map(), service); 319 tt_int_op(ret, OP_EQ, 0); 320 321 done: 322 return service; 323 } 324 325 /* Helper: Deallocate a given service object, its child objects and 326 * remove it from onion service map. 327 * */ 328 static void 329 helper_destroy_service(hs_service_t *service) 330 { 331 if (!service) 332 return; 333 334 remove_service(get_hs_service_map(), service); 335 336 hs_service_free(service); 337 } 338 339 /* Helper: Return a newly allocated service object with clients. */ 340 static hs_service_t * 341 helper_create_service_with_clients(int num_clients) 342 { 343 int i; 344 hs_service_t *service = helper_create_service(); 345 tt_assert(service); 346 service->config.clients = smartlist_new(); 347 348 for (i = 0; i < num_clients; i++) { 349 hs_service_authorized_client_t *client; 350 client = helper_create_authorized_client(); 351 smartlist_add(service->config.clients, client); 352 } 353 354 done: 355 return service; 356 } 357 358 /* Helper: Return a newly allocated service intro point with two link 359 * specifiers, one IPv4 and one legacy ID set to As. */ 360 static hs_service_intro_point_t * 361 helper_create_service_ip(void) 362 { 363 link_specifier_t *ls; 364 hs_service_intro_point_t *ip = service_intro_point_new(NULL); 365 tor_assert(ip); 366 /* Add a first unused link specifier. */ 367 ls = link_specifier_new(); 368 link_specifier_set_ls_type(ls, LS_IPV4); 369 smartlist_add(ip->base.link_specifiers, ls); 370 /* Add a second link specifier used by a test. */ 371 ls = link_specifier_new(); 372 link_specifier_set_ls_type(ls, LS_LEGACY_ID); 373 memset(link_specifier_getarray_un_legacy_id(ls), 'A', 374 link_specifier_getlen_un_legacy_id(ls)); 375 smartlist_add(ip->base.link_specifiers, ls); 376 377 return ip; 378 } 379 380 static void 381 test_load_keys(void *arg) 382 { 383 int ret; 384 char *conf = NULL; 385 char *hsdir_v3 = tor_strdup(get_fname("hs3")); 386 char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1]; 387 388 (void) arg; 389 390 /* We'll register one service then we'll load keys and validate that both 391 * are in a correct state. */ 392 393 hs_init(); 394 395 #define conf_fmt \ 396 "HiddenServiceDir %s\n" \ 397 "HiddenServiceVersion %d\n" \ 398 "HiddenServicePort 65535\n" 399 400 /* v3 service. */ 401 tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE); 402 ret = helper_config_service(conf); 403 tor_free(conf); 404 tt_int_op(ret, OP_EQ, 0); 405 /* It's in staging? */ 406 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); 407 408 #undef conf_fmt 409 410 /* Load the keys for these. After that, the v3 service should be registered 411 * in the global map. */ 412 hs_service_load_all_keys(); 413 tt_int_op(get_hs_service_map_size(), OP_EQ, 1); 414 hs_service_t *s = get_first_service(); 415 tt_assert(s); 416 417 /* Ok we have the service object. Validate few things. */ 418 tt_assert(!fast_mem_is_zero(s->onion_address, sizeof(s->onion_address))); 419 tt_int_op(hs_address_is_valid(s->onion_address), OP_EQ, 1); 420 tt_assert(!fast_mem_is_zero((char *) s->keys.identity_sk.seckey, 421 ED25519_SECKEY_LEN)); 422 tt_assert(!fast_mem_is_zero((char *) s->keys.identity_pk.pubkey, 423 ED25519_PUBKEY_LEN)); 424 /* Check onion address from identity key. */ 425 hs_build_address(&s->keys.identity_pk, s->config.version, addr); 426 tt_int_op(hs_address_is_valid(addr), OP_EQ, 1); 427 tt_str_op(addr, OP_EQ, s->onion_address); 428 429 done: 430 tor_free(hsdir_v3); 431 hs_free_all(); 432 } 433 434 static void 435 test_client_filename_is_valid(void *arg) 436 { 437 (void) arg; 438 439 /* Valid file name. */ 440 tt_assert(client_filename_is_valid("a.auth")); 441 /* Valid file name with special character. */ 442 tt_assert(client_filename_is_valid("a-.auth")); 443 /* Invalid extension. */ 444 tt_assert(!client_filename_is_valid("a.ath")); 445 /* Nothing before the extension. */ 446 tt_assert(!client_filename_is_valid(".auth")); 447 448 done: 449 ; 450 } 451 452 static void 453 test_parse_authorized_client(void *arg) 454 { 455 hs_service_authorized_client_t *client = NULL; 456 457 (void) arg; 458 459 /* Valid authorized client. */ 460 client = parse_authorized_client( 461 "descriptor:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"); 462 tt_assert(client); 463 464 /* Wrong number of fields. */ 465 tt_assert(!parse_authorized_client("a:b:c:d:e")); 466 /* Wrong auth type. */ 467 tt_assert(!parse_authorized_client( 468 "x:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); 469 /* Wrong key type. */ 470 tt_assert(!parse_authorized_client( 471 "descriptor:x:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); 472 /* Some malformed string. */ 473 tt_assert(!parse_authorized_client("descriptor:x25519:aa==")); 474 tt_assert(!parse_authorized_client("descriptor:")); 475 tt_assert(!parse_authorized_client("descriptor:x25519")); 476 tt_assert(!parse_authorized_client("descriptor:x25519:")); 477 tt_assert(!parse_authorized_client("")); 478 479 done: 480 service_authorized_client_free(client); 481 } 482 483 static char * 484 mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out) 485 { 486 char *ret = NULL; 487 488 (void) flags; 489 (void) stat_out; 490 491 if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR 492 "authorized_clients" PATH_SEPARATOR 493 "client1.auth"))) { 494 ret = tor_strdup("descriptor:x25519:" 495 "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"); 496 goto done; 497 } 498 499 if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR 500 "authorized_clients" PATH_SEPARATOR 501 "dummy.xxx"))) { 502 ret = tor_strdup("descriptor:x25519:" 503 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 504 goto done; 505 } 506 507 if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR 508 "authorized_clients" PATH_SEPARATOR 509 "client2.auth"))) { 510 ret = tor_strdup("descriptor:x25519:" 511 "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta"); 512 goto done; 513 } 514 515 done: 516 return ret; 517 } 518 519 static smartlist_t * 520 mock_tor_listdir(const char *dirname) 521 { 522 smartlist_t *file_list = smartlist_new(); 523 524 (void) dirname; 525 526 smartlist_add(file_list, tor_strdup("client1.auth")); 527 smartlist_add(file_list, tor_strdup("dummy.xxx")); 528 smartlist_add(file_list, tor_strdup("client2.auth")); 529 530 return file_list; 531 } 532 533 static void 534 test_load_keys_with_client_auth(void *arg) 535 { 536 int ret; 537 char *conf = NULL; 538 smartlist_t *pubkey_b32_list = smartlist_new(); 539 char *hsdir_v3 = tor_strdup(get_fname("hs3")); 540 hs_service_t *service; 541 542 (void) arg; 543 544 hs_init(); 545 smartlist_add(pubkey_b32_list, tor_strdup( 546 "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); 547 smartlist_add(pubkey_b32_list, tor_strdup( 548 "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta")); 549 550 #define conf_fmt \ 551 "HiddenServiceDir %s\n" \ 552 "HiddenServiceVersion %d\n" \ 553 "HiddenServicePort 65534\n" 554 555 tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE); 556 ret = helper_config_service(conf); 557 tor_free(conf); 558 tt_int_op(ret, OP_EQ, 0); 559 /* It's in staging? */ 560 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); 561 562 #undef conf_fmt 563 564 MOCK(read_file_to_str, mock_read_file_to_str); 565 MOCK(tor_listdir, mock_tor_listdir); 566 567 /* Load the keys for these. After that, the v3 service should be registered 568 * in the global map. */ 569 hs_service_load_all_keys(); 570 tt_int_op(get_hs_service_map_size(), OP_EQ, 1); 571 572 service = get_first_service(); 573 tt_assert(service); 574 tt_assert(service->config.clients); 575 tt_int_op(smartlist_len(service->config.clients), OP_EQ, 576 smartlist_len(pubkey_b32_list)); 577 578 /* Test that the keys in clients are correct. */ 579 SMARTLIST_FOREACH_BEGIN(pubkey_b32_list, char *, pubkey_b32) { 580 581 curve25519_public_key_t pubkey; 582 /* This flag will be set if the key is found in clients. */ 583 int is_found = 0; 584 base32_decode((char *) pubkey.public_key, sizeof(pubkey.public_key), 585 pubkey_b32, strlen(pubkey_b32)); 586 587 SMARTLIST_FOREACH_BEGIN(service->config.clients, 588 hs_service_authorized_client_t *, client) { 589 if (tor_memeq(&pubkey, &client->client_pk, sizeof(pubkey))) { 590 is_found = 1; 591 break; 592 } 593 } SMARTLIST_FOREACH_END(client); 594 595 tt_assert(is_found); 596 597 } SMARTLIST_FOREACH_END(pubkey_b32); 598 599 done: 600 SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s)); 601 smartlist_free(pubkey_b32_list); 602 tor_free(hsdir_v3); 603 hs_free_all(); 604 UNMOCK(read_file_to_str); 605 UNMOCK(tor_listdir); 606 } 607 608 static void 609 test_access_service(void *arg) 610 { 611 int ret; 612 char *conf = NULL; 613 char *hsdir_v3 = tor_strdup(get_fname("hs3")); 614 hs_service_ht *global_map; 615 hs_service_t *s = NULL; 616 617 (void) arg; 618 619 /* We'll register one service then we'll load keys and validate that both 620 * are in a correct state. */ 621 622 hs_init(); 623 624 #define conf_fmt \ 625 "HiddenServiceDir %s\n" \ 626 "HiddenServiceVersion %d\n" \ 627 "HiddenServicePort 65535\n" 628 629 /* v3 service. */ 630 tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE); 631 ret = helper_config_service(conf); 632 tor_free(conf); 633 tt_int_op(ret, OP_EQ, 0); 634 /* It's in staging? */ 635 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); 636 637 /* Load the keys for these. After that, the v3 service should be registered 638 * in the global map. */ 639 hs_service_load_all_keys(); 640 tt_int_op(get_hs_service_map_size(), OP_EQ, 1); 641 s = get_first_service(); 642 tt_assert(s); 643 global_map = get_hs_service_map(); 644 tt_assert(global_map); 645 646 /* From here, we'll try the service accessors. */ 647 hs_service_t *query = find_service(global_map, &s->keys.identity_pk); 648 tt_assert(query); 649 tt_mem_op(query, OP_EQ, s, sizeof(hs_service_t)); 650 /* Remove service, check if it actually works and then put it back. */ 651 remove_service(global_map, s); 652 hs_metrics_service_free(s); 653 tt_int_op(get_hs_service_map_size(), OP_EQ, 0); 654 query = find_service(global_map, &s->keys.identity_pk); 655 tt_ptr_op(query, OP_EQ, NULL); 656 657 /* Register back the service in the map. */ 658 ret = register_service(global_map, s); 659 tt_int_op(ret, OP_EQ, 0); 660 tt_int_op(get_hs_service_map_size(), OP_EQ, 1); 661 /* Twice should fail. */ 662 hs_metrics_service_free(s); /* Avoid BUG() on metrics init. */ 663 ret = register_service(global_map, s); 664 tt_int_op(ret, OP_EQ, -1); 665 /* Remove service from map so we don't double free on cleanup. */ 666 remove_service(global_map, s); 667 tt_int_op(get_hs_service_map_size(), OP_EQ, 0); 668 query = find_service(global_map, &s->keys.identity_pk); 669 tt_ptr_op(query, OP_EQ, NULL); 670 /* Let's try to remove twice for fun. */ 671 setup_full_capture_of_logs(LOG_WARN); 672 remove_service(global_map, s); 673 expect_log_msg_containing("Could not find service in the global map"); 674 teardown_capture_of_logs(); 675 676 done: 677 hs_service_free(s); 678 tor_free(hsdir_v3); 679 hs_free_all(); 680 } 681 682 /** Test that we can create intro point objects, index them and find them */ 683 static void 684 test_service_intro_point(void *arg) 685 { 686 hs_service_t *service = NULL; 687 hs_service_intro_point_t *ip = NULL; 688 689 (void) arg; 690 691 update_approx_time(1481621834); 692 693 /* Test simple creation of an object. */ 694 { 695 time_t now = approx_time(); 696 ip = helper_create_service_ip(); 697 tt_assert(ip); 698 /* Make sure the authentication keypair is not zeroes. */ 699 tt_int_op(fast_mem_is_zero((const char *) &ip->auth_key_kp, 700 sizeof(ed25519_keypair_t)), OP_EQ, 0); 701 /* The introduce2_max MUST be in that range. */ 702 tt_u64_op(ip->introduce2_max, OP_GE, 703 INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS); 704 tt_u64_op(ip->introduce2_max, OP_LE, 705 INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS); 706 /* Time to expire MUST also be in that range. We subtract 500 seconds 707 * because there could be a gap between setting now and the time taken in 708 * service_intro_point_new. On ARM and other older CPUs, it can be 709 * surprisingly slow... */ 710 tt_u64_op(ip->time_to_expire, OP_GE, 711 now + INTRO_POINT_LIFETIME_MIN_SECONDS - 500); 712 /* We add 500 seconds, because this time we're testing against the 713 * maximum allowed time. */ 714 tt_u64_op(ip->time_to_expire, OP_LE, 715 now + INTRO_POINT_LIFETIME_MAX_SECONDS + 500); 716 tt_assert(ip->replay_cache); 717 tt_assert(ip->base.link_specifiers); 718 /* By default, this is NOT a legacy object. */ 719 tt_int_op(ip->base.is_only_legacy, OP_EQ, 0); 720 } 721 722 /* Test functions that uses a service intropoints map with that previously 723 * created object (non legacy). */ 724 { 725 ed25519_public_key_t garbage = { {0} }; 726 hs_service_intro_point_t *query; 727 728 service = hs_service_new(get_options()); 729 tt_assert(service); 730 service->desc_current = service_descriptor_new(); 731 tt_assert(service->desc_current); 732 /* Add intropoint to descriptor map. */ 733 service_intro_point_add(service->desc_current->intro_points.map, ip); 734 query = service_intro_point_find(service, &ip->auth_key_kp.pubkey); 735 tt_mem_op(query, OP_EQ, ip, sizeof(hs_service_intro_point_t)); 736 query = service_intro_point_find(service, &garbage); 737 tt_ptr_op(query, OP_EQ, NULL); 738 739 /* While at it, can I find the descriptor with the intro point? */ 740 hs_service_descriptor_t *desc_lookup = 741 service_desc_find_by_intro(service, ip); 742 tt_mem_op(service->desc_current, OP_EQ, desc_lookup, 743 sizeof(hs_service_descriptor_t)); 744 745 /* Remove object from service descriptor and make sure it is out. */ 746 service_intro_point_remove(service, ip); 747 query = service_intro_point_find(service, &ip->auth_key_kp.pubkey); 748 tt_ptr_op(query, OP_EQ, NULL); 749 } 750 751 done: 752 /* If the test succeed, this object is no longer referenced in the service 753 * so we can free it without use after free. Else, it might explode because 754 * it's still in the service descriptor map. */ 755 service_intro_point_free(ip); 756 hs_service_free(service); 757 } 758 759 static node_t mock_node; 760 static const node_t * 761 mock_node_get_by_id(const char *digest) 762 { 763 (void) digest; 764 memset(mock_node.identity, 'A', DIGEST_LEN); 765 /* Only return the matching identity of As */ 766 if (!tor_memcmp(mock_node.identity, digest, DIGEST_LEN)) { 767 return &mock_node; 768 } 769 return NULL; 770 } 771 772 static void 773 test_helper_functions(void *arg) 774 { 775 int ret; 776 hs_service_t *service = NULL; 777 hs_service_intro_point_t *ip = NULL; 778 hs_ident_circuit_t ident; 779 780 (void) arg; 781 782 MOCK(node_get_by_id, mock_node_get_by_id); 783 784 hs_service_init(); 785 time_t now = time(NULL); 786 update_approx_time(now); 787 788 service = helper_create_service(); 789 790 ip = helper_create_service_ip(); 791 /* Immediately add the intro point to the service so the free service at the 792 * end cleans it as well. */ 793 service_intro_point_add(service->desc_current->intro_points.map, ip); 794 795 /* Setup the circuit identifier. */ 796 ed25519_pubkey_copy(&ident.intro_auth_pk, &ip->auth_key_kp.pubkey); 797 ed25519_pubkey_copy(&ident.identity_pk, &service->keys.identity_pk); 798 799 /* Testing get_objects_from_ident(). */ 800 { 801 hs_service_t *s_lookup = NULL; 802 hs_service_intro_point_t *ip_lookup = NULL; 803 hs_service_descriptor_t *desc_lookup = NULL; 804 805 get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup); 806 tt_mem_op(s_lookup, OP_EQ, service, sizeof(hs_service_t)); 807 tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t)); 808 tt_mem_op(desc_lookup, OP_EQ, service->desc_current, 809 sizeof(hs_service_descriptor_t)); 810 /* Reset */ 811 s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL; 812 813 /* NULL parameter should work. */ 814 get_objects_from_ident(&ident, NULL, &ip_lookup, &desc_lookup); 815 tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t)); 816 tt_mem_op(desc_lookup, OP_EQ, service->desc_current, 817 sizeof(hs_service_descriptor_t)); 818 /* Reset. */ 819 s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL; 820 821 /* Break the ident and we should find nothing. */ 822 memset(&ident, 0, sizeof(ident)); 823 get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup); 824 tt_ptr_op(s_lookup, OP_EQ, NULL); 825 tt_ptr_op(ip_lookup, OP_EQ, NULL); 826 tt_ptr_op(desc_lookup, OP_EQ, NULL); 827 } 828 829 /* Testing get_node_from_intro_point() */ 830 { 831 const node_t *node = get_node_from_intro_point(ip); 832 tt_ptr_op(node, OP_EQ, &mock_node); 833 SMARTLIST_FOREACH_BEGIN(ip->base.link_specifiers, 834 link_specifier_t *, ls) { 835 if (link_specifier_get_ls_type(ls) == LS_LEGACY_ID) { 836 /* Change legacy id in link specifier which is not the mock node. */ 837 memset(link_specifier_getarray_un_legacy_id(ls), 'B', 838 link_specifier_getlen_un_legacy_id(ls)); 839 } 840 } SMARTLIST_FOREACH_END(ls); 841 node = get_node_from_intro_point(ip); 842 tt_ptr_op(node, OP_EQ, NULL); 843 } 844 845 /* Testing can_service_launch_intro_circuit() */ 846 { 847 /* Put the start of the retry period back in time, we should be allowed. 848 * to launch intro circuit. */ 849 service->state.num_intro_circ_launched = 2; 850 service->state.intro_circ_retry_started_time = 851 (now - INTRO_CIRC_RETRY_PERIOD - 1); 852 ret = can_service_launch_intro_circuit(service, now); 853 tt_int_op(ret, OP_EQ, 1); 854 tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now); 855 tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0); 856 /* Call it again, we should still be allowed because we are under 857 * MAX_INTRO_CIRCS_PER_PERIOD which been set to 0 previously. */ 858 ret = can_service_launch_intro_circuit(service, now); 859 tt_int_op(ret, OP_EQ, 1); 860 tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now); 861 tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0); 862 /* Too many intro circuit launched means we are not allowed. */ 863 service->state.num_intro_circ_launched = 20; 864 ret = can_service_launch_intro_circuit(service, now); 865 tt_int_op(ret, OP_EQ, 0); 866 } 867 868 /* Testing intro_point_should_expire(). */ 869 { 870 /* Just some basic test of the current state. */ 871 tt_u64_op(ip->introduce2_max, OP_GE, 872 INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS); 873 tt_u64_op(ip->introduce2_max, OP_LE, 874 INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS); 875 tt_u64_op(ip->time_to_expire, OP_GE, 876 now + INTRO_POINT_LIFETIME_MIN_SECONDS); 877 tt_u64_op(ip->time_to_expire, OP_LE, 878 now + INTRO_POINT_LIFETIME_MAX_SECONDS); 879 880 /* This newly created IP from above shouldn't expire now. */ 881 ret = intro_point_should_expire(ip, now); 882 tt_int_op(ret, OP_EQ, 0); 883 /* Maximum number of INTRODUCE2 cell reached, it should expire. */ 884 ip->introduce2_count = INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS + 1; 885 ret = intro_point_should_expire(ip, now); 886 tt_int_op(ret, OP_EQ, 1); 887 ip->introduce2_count = 0; 888 /* It should expire if time to expire has been reached. */ 889 ip->time_to_expire = now - 1000; 890 ret = intro_point_should_expire(ip, now); 891 tt_int_op(ret, OP_EQ, 1); 892 } 893 894 done: 895 /* This will free the service and all objects associated to it. */ 896 if (service) { 897 remove_service(get_hs_service_map(), service); 898 hs_service_free(service); 899 } 900 hs_service_free_all(); 901 UNMOCK(node_get_by_id); 902 } 903 904 /** Test that we do the right operations when an intro circuit opens */ 905 static void 906 test_intro_circuit_opened(void *arg) 907 { 908 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; 909 hs_service_t *service = NULL; 910 origin_circuit_t *circ = NULL; 911 912 (void) arg; 913 914 hs_init(); 915 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); 916 MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge); 917 918 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, 919 flags); 920 921 /* No service associated with this circuit. */ 922 setup_full_capture_of_logs(LOG_WARN); 923 hs_service_circuit_has_opened(circ); 924 expect_log_msg_containing("Unknown service identity key"); 925 teardown_capture_of_logs(); 926 927 /* Set a service for this circuit. */ 928 { 929 service = helper_create_service(); 930 ed25519_pubkey_copy(&circ->hs_ident->identity_pk, 931 &service->keys.identity_pk); 932 933 /* No intro point associated with this circuit. */ 934 setup_full_capture_of_logs(LOG_WARN); 935 hs_service_circuit_has_opened(circ); 936 expect_log_msg_containing("Unknown introduction point auth key"); 937 teardown_capture_of_logs(); 938 } 939 940 /* Set an IP object now for this circuit. */ 941 { 942 hs_service_intro_point_t *ip = helper_create_service_ip(); 943 service_intro_point_add(service->desc_current->intro_points.map, ip); 944 /* Update ident to contain the intro point auth key. */ 945 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, 946 &ip->auth_key_kp.pubkey); 947 } 948 949 /* This one should go all the way. */ 950 setup_full_capture_of_logs(LOG_INFO); 951 hs_service_circuit_has_opened(circ); 952 expect_log_msg_containing("Introduction circuit 0 established for service"); 953 teardown_capture_of_logs(); 954 955 done: 956 circuit_free_(TO_CIRCUIT(circ)); 957 if (service) { 958 remove_service(get_hs_service_map(), service); 959 hs_service_free(service); 960 } 961 hs_free_all(); 962 UNMOCK(circuit_mark_for_close_); 963 UNMOCK(relay_send_command_from_edge_); 964 } 965 966 /** Test the operations we do on a circuit after we learn that we successfully 967 * established an intro point on it */ 968 static void 969 test_intro_established(void *arg) 970 { 971 int ret; 972 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; 973 uint8_t payload[RELAY_PAYLOAD_SIZE] = {0}; 974 origin_circuit_t *circ = NULL; 975 hs_service_t *service = NULL; 976 hs_service_intro_point_t *ip = NULL; 977 978 (void) arg; 979 980 hs_init(); 981 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); 982 983 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, 984 flags); 985 tt_assert(circ); 986 987 /* Test a wrong purpose. */ 988 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO; 989 setup_full_capture_of_logs(LOG_WARN); 990 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); 991 tt_int_op(ret, OP_EQ, -1); 992 expect_log_msg_containing("Received an INTRO_ESTABLISHED cell on a " 993 "non introduction circuit of purpose"); 994 teardown_capture_of_logs(); 995 996 /* Back to normal. */ 997 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO; 998 999 /* No service associated to it. */ 1000 setup_full_capture_of_logs(LOG_WARN); 1001 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); 1002 tt_int_op(ret, OP_EQ, -1); 1003 expect_log_msg_containing("Unknown service identity key"); 1004 teardown_capture_of_logs(); 1005 1006 /* Set a service for this circuit. */ 1007 service = helper_create_service(); 1008 ed25519_pubkey_copy(&circ->hs_ident->identity_pk, 1009 &service->keys.identity_pk); 1010 /* No introduction point associated to it. */ 1011 setup_full_capture_of_logs(LOG_WARN); 1012 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); 1013 tt_int_op(ret, OP_EQ, -1); 1014 expect_log_msg_containing("Introduction circuit established without an " 1015 "intro point object on circuit"); 1016 teardown_capture_of_logs(); 1017 1018 /* Set an IP object now for this circuit. */ 1019 { 1020 ip = helper_create_service_ip(); 1021 service_intro_point_add(service->desc_current->intro_points.map, ip); 1022 /* Update ident to contain the intro point auth key. */ 1023 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, 1024 &ip->auth_key_kp.pubkey); 1025 } 1026 1027 /* Send an empty payload. INTRO_ESTABLISHED cells are basically zeroes. */ 1028 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); 1029 tt_int_op(ret, OP_EQ, 0); 1030 tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_INTRO); 1031 1032 done: 1033 if (circ) 1034 circuit_free_(TO_CIRCUIT(circ)); 1035 if (service) { 1036 remove_service(get_hs_service_map(), service); 1037 hs_service_free(service); 1038 } 1039 hs_free_all(); 1040 UNMOCK(circuit_mark_for_close_); 1041 } 1042 1043 /** Check the operations we do on a rendezvous circuit after we learn it's 1044 * open */ 1045 static void 1046 test_rdv_circuit_opened(void *arg) 1047 { 1048 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; 1049 origin_circuit_t *circ = NULL; 1050 hs_service_t *service = NULL; 1051 1052 (void) arg; 1053 1054 hs_init(); 1055 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); 1056 MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge); 1057 1058 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND, flags); 1059 crypto_rand((char *) circ->hs_ident->rendezvous_cookie, REND_COOKIE_LEN); 1060 crypto_rand((char *) circ->hs_ident->rendezvous_handshake_info, 1061 sizeof(circ->hs_ident->rendezvous_handshake_info)); 1062 1063 /* No service associated with this circuit. */ 1064 setup_full_capture_of_logs(LOG_WARN); 1065 hs_service_circuit_has_opened(circ); 1066 expect_log_msg_containing("Unknown service identity key"); 1067 teardown_capture_of_logs(); 1068 /* This should be set to a non zero timestamp. */ 1069 tt_u64_op(TO_CIRCUIT(circ)->timestamp_dirty, OP_NE, 0); 1070 1071 /* Set a service for this circuit. */ 1072 service = helper_create_service(); 1073 ed25519_pubkey_copy(&circ->hs_ident->identity_pk, 1074 &service->keys.identity_pk); 1075 /* Should be all good. */ 1076 hs_service_circuit_has_opened(circ); 1077 tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED); 1078 1079 done: 1080 circuit_free_(TO_CIRCUIT(circ)); 1081 if (service) { 1082 remove_service(get_hs_service_map(), service); 1083 hs_service_free(service); 1084 } 1085 hs_free_all(); 1086 UNMOCK(circuit_mark_for_close_); 1087 UNMOCK(relay_send_command_from_edge_); 1088 } 1089 1090 static void 1091 mock_assert_circuit_ok(const circuit_t *c) 1092 { 1093 (void) c; 1094 return; 1095 } 1096 1097 /** Test for the general mechanism for closing intro circs. 1098 * Also a way to identify that #23603 has been fixed. */ 1099 static void 1100 test_closing_intro_circs(void *arg) 1101 { 1102 hs_service_t *service = NULL; 1103 hs_service_intro_point_t *ip = NULL, *entry = NULL; 1104 origin_circuit_t *intro_circ = NULL, *tmp_circ; 1105 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; 1106 1107 (void) arg; 1108 1109 MOCK(assert_circuit_ok, mock_assert_circuit_ok); 1110 1111 hs_init(); 1112 1113 /* Initialize service */ 1114 service = helper_create_service(); 1115 /* Initialize intro point */ 1116 ip = helper_create_service_ip(); 1117 tt_assert(ip); 1118 service_intro_point_add(service->desc_current->intro_points.map, ip); 1119 1120 /* Initialize intro circuit */ 1121 intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags); 1122 intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk); 1123 /* Register circuit in the circuitmap . */ 1124 hs_circuitmap_register_intro_circ_v3_service_side(intro_circ, 1125 &ip->auth_key_kp.pubkey); 1126 tmp_circ = 1127 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); 1128 tt_ptr_op(tmp_circ, OP_EQ, intro_circ); 1129 1130 /* Pretend that intro point has failed too much */ 1131 ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES+1; 1132 1133 /* Now pretend we are freeing this intro circuit. We want to see that our 1134 * destructor is not gonna kill our intro point structure since that's the 1135 * job of the cleanup routine. */ 1136 circuit_free_(TO_CIRCUIT(intro_circ)); 1137 intro_circ = NULL; 1138 entry = service_intro_point_find(service, &ip->auth_key_kp.pubkey); 1139 tt_assert(entry); 1140 /* The free should also remove the circuit from the circuitmap. */ 1141 tmp_circ = 1142 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); 1143 tt_assert(!tmp_circ); 1144 1145 /* Now pretend that a new intro point circ was launched and opened. Check 1146 * that the intro point will be established correctly. */ 1147 intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags); 1148 intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk); 1149 ed25519_pubkey_copy(&intro_circ->hs_ident->intro_auth_pk, 1150 &ip->auth_key_kp.pubkey); 1151 /* Register circuit in the circuitmap . */ 1152 hs_circuitmap_register_intro_circ_v3_service_side(intro_circ, 1153 &ip->auth_key_kp.pubkey); 1154 tmp_circ = 1155 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); 1156 tt_ptr_op(tmp_circ, OP_EQ, intro_circ); 1157 tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_EQ, 0); 1158 circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_INTERNAL); 1159 tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_NE, 0); 1160 /* At this point, we should not be able to find it in the circuitmap. */ 1161 tmp_circ = 1162 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey); 1163 tt_assert(!tmp_circ); 1164 1165 done: 1166 if (intro_circ) { 1167 circuit_free_(TO_CIRCUIT(intro_circ)); 1168 } 1169 /* Frees the service object. */ 1170 if (service) { 1171 remove_service(get_hs_service_map(), service); 1172 hs_service_free(service); 1173 } 1174 hs_free_all(); 1175 UNMOCK(assert_circuit_ok); 1176 } 1177 1178 /** Test sending and receiving introduce2 cells */ 1179 static void 1180 test_bad_introduce2(void *arg) 1181 { 1182 int ret; 1183 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; 1184 uint8_t payload[RELAY_PAYLOAD_SIZE] = {0}; 1185 origin_circuit_t *circ = NULL; 1186 hs_service_t *service = NULL; 1187 hs_service_intro_point_t *ip = NULL; 1188 const smartlist_t *entries = NULL; 1189 const metrics_store_entry_t *entry = NULL; 1190 1191 (void) arg; 1192 1193 hs_init(); 1194 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); 1195 MOCK(get_or_state, 1196 get_or_state_replacement); 1197 1198 dummy_state = or_state_new(); 1199 1200 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags); 1201 tt_assert(circ); 1202 1203 /* Test a wrong purpose. */ 1204 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO; 1205 setup_full_capture_of_logs(LOG_WARN); 1206 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); 1207 tt_int_op(ret, OP_EQ, -1); 1208 expect_log_msg_containing("Received an INTRODUCE2 cell on a " 1209 "non introduction circuit of purpose"); 1210 teardown_capture_of_logs(); 1211 1212 /* Back to normal. */ 1213 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO; 1214 1215 /* No service associated to it. */ 1216 setup_full_capture_of_logs(LOG_WARN); 1217 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); 1218 tt_int_op(ret, OP_EQ, -1); 1219 expect_log_msg_containing("Unknown service identity key"); 1220 teardown_capture_of_logs(); 1221 1222 /* Set a service for this circuit. */ 1223 service = helper_create_service(); 1224 ed25519_pubkey_copy(&circ->hs_ident->identity_pk, 1225 &service->keys.identity_pk); 1226 /* No introduction point associated to it. */ 1227 setup_full_capture_of_logs(LOG_WARN); 1228 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); 1229 tt_int_op(ret, OP_EQ, -1); 1230 expect_log_msg_containing("Unknown introduction auth key when handling " 1231 "an INTRODUCE2 cell on circuit"); 1232 teardown_capture_of_logs(); 1233 1234 entries = metrics_store_get_all(service->metrics.store, 1235 "tor_hs_intro_rejected_intro_req_count"); 1236 1237 tt_assert(entries); 1238 /* There are `hs_metrics_intro_req_size` entries (one for each 1239 * possible `reason` label value). */ 1240 tt_int_op(smartlist_len(entries), OP_EQ, 1241 hs_metrics_intro_req_error_reasons_size); 1242 1243 /* Make sure the tor_hs_intro_rejected_intro_req_count metric was 1244 * only incremented for reason HS_METRICS_ERR_INTRO_REQ_BAD_AUTH_KEY. */ 1245 for (size_t i = 0; i < hs_metrics_intro_req_error_reasons_size; ++i) { 1246 const char *reason = hs_metrics_intro_req_error_reasons[i]; 1247 1248 if (!strcmp(reason, HS_METRICS_ERR_INTRO_REQ_BAD_AUTH_KEY)) { 1249 continue; 1250 } 1251 1252 entry = metrics_store_find_entry_with_label( 1253 entries, 1254 metrics_format_label("reason", reason)); 1255 tt_assert(entry); 1256 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 0); 1257 } 1258 1259 entry = metrics_store_find_entry_with_label( 1260 entries, 1261 metrics_format_label("reason", HS_METRICS_ERR_INTRO_REQ_BAD_AUTH_KEY)); 1262 tt_assert(entry); 1263 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 1); 1264 1265 /* Set an IP object now for this circuit. */ 1266 { 1267 ip = helper_create_service_ip(); 1268 service_intro_point_add(service->desc_current->intro_points.map, ip); 1269 /* Update ident to contain the intro point auth key. */ 1270 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, 1271 &ip->auth_key_kp.pubkey); 1272 } 1273 1274 /* This will fail because receiving an INTRODUCE2 cell implies a valid cell 1275 * and then launching circuits so let's not do that and instead test that 1276 * behaviour differently. */ 1277 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload)); 1278 tt_int_op(ret, OP_EQ, -1); 1279 tt_u64_op(ip->introduce2_count, OP_EQ, 0); 1280 1281 /* Make sure the tor_hs_intro_rejected_intro_req_count metric was incremented 1282 * a second time, this time, with reason="invalid_introduce2_cell". */ 1283 entry = metrics_store_find_entry_with_label( 1284 entries, 1285 metrics_format_label("reason", HS_METRICS_ERR_INTRO_REQ_INTRODUCE2)); 1286 tt_assert(entry); 1287 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 1); 1288 1289 /* The metric entries with other reason labels are unaffected */ 1290 entry = metrics_store_find_entry_with_label( 1291 entries, 1292 metrics_format_label("reason", HS_METRICS_ERR_INTRO_REQ_SUBCREDENTIAL)); 1293 tt_assert(entry); 1294 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 0); 1295 1296 entry = metrics_store_find_entry_with_label( 1297 entries, metrics_format_label( 1298 "reason", HS_METRICS_ERR_INTRO_REQ_INTRODUCE2_REPLAY)); 1299 tt_assert(entry); 1300 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 0); 1301 1302 entry = metrics_store_find_entry_with_label( 1303 entries, 1304 metrics_format_label("reason", HS_METRICS_ERR_INTRO_REQ_BAD_AUTH_KEY)); 1305 tt_assert(entry); 1306 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 1); 1307 1308 done: 1309 or_state_free(dummy_state); 1310 dummy_state = NULL; 1311 if (circ) 1312 circuit_free_(TO_CIRCUIT(circ)); 1313 if (service) { 1314 remove_service(get_hs_service_map(), service); 1315 hs_service_free(service); 1316 } 1317 hs_free_all(); 1318 UNMOCK(circuit_mark_for_close_); 1319 } 1320 1321 /** Test basic hidden service housekeeping operations (maintaining intro 1322 * points, etc) */ 1323 static void 1324 test_service_event(void *arg) 1325 { 1326 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; 1327 time_t now = time(NULL); 1328 hs_service_t *service; 1329 origin_circuit_t *circ = NULL; 1330 1331 (void) arg; 1332 1333 hs_init(); 1334 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); 1335 1336 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags); 1337 1338 /* Set a service for this circuit. */ 1339 service = helper_create_service(); 1340 tt_assert(service); 1341 ed25519_pubkey_copy(&circ->hs_ident->identity_pk, 1342 &service->keys.identity_pk); 1343 1344 /* Currently this consists of cleaning invalid intro points. So adding IPs 1345 * here that should get cleaned up. */ 1346 { 1347 hs_service_intro_point_t *ip = helper_create_service_ip(); 1348 service_intro_point_add(service->desc_current->intro_points.map, ip); 1349 /* This run will remove the IP because we have no circuits nor node_t 1350 * associated with it. */ 1351 run_housekeeping_event(now); 1352 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1353 OP_EQ, 0); 1354 /* We'll trigger a removal because we've reached our maximum amount of 1355 * times we should retry a circuit. For this, we need to have a node_t 1356 * that matches the identity of this IP. */ 1357 routerinfo_t ri; 1358 memset(&ri, 0, sizeof(ri)); 1359 ip = helper_create_service_ip(); 1360 service_intro_point_add(service->desc_current->intro_points.map, ip); 1361 memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN); 1362 /* This triggers a node_t creation. */ 1363 tt_assert(nodelist_set_routerinfo(&ri, NULL)); 1364 ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1; 1365 run_housekeeping_event(now); 1366 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1367 OP_EQ, 0); 1368 /* No removal but no circuit so this means the IP object will stay in the 1369 * descriptor map so we can retry it. */ 1370 ip = helper_create_service_ip(); 1371 service_intro_point_add(service->desc_current->intro_points.map, ip); 1372 run_housekeeping_event(now); 1373 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1374 OP_EQ, 1); 1375 /* Remove the IP object at once for the next test. */ 1376 ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1; 1377 run_housekeeping_event(now); 1378 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1379 OP_EQ, 0); 1380 /* Now, we'll create an IP with a registered circuit. The IP object 1381 * shouldn't go away. */ 1382 ip = helper_create_service_ip(); 1383 service_intro_point_add(service->desc_current->intro_points.map, ip); 1384 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk, 1385 &ip->auth_key_kp.pubkey); 1386 hs_circuitmap_register_intro_circ_v3_service_side( 1387 circ, &ip->auth_key_kp.pubkey); 1388 run_housekeeping_event(now); 1389 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1390 OP_EQ, 1); 1391 /* We'll mangle the IP object to expire. */ 1392 ip->time_to_expire = now; 1393 run_housekeeping_event(now); 1394 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1395 OP_EQ, 0); 1396 } 1397 1398 done: 1399 hs_circuitmap_remove_circuit(TO_CIRCUIT(circ)); 1400 circuit_free_(TO_CIRCUIT(circ)); 1401 if (service) { 1402 remove_service(get_hs_service_map(), service); 1403 hs_service_free(service); 1404 } 1405 hs_free_all(); 1406 UNMOCK(circuit_mark_for_close_); 1407 } 1408 1409 /** Test that we rotate descriptors correctly. */ 1410 static void 1411 test_rotate_descriptors(void *arg) 1412 { 1413 int ret; 1414 time_t next_rotation_time, now; 1415 hs_service_t *service = NULL; 1416 hs_service_descriptor_t *desc_next; 1417 1418 (void) arg; 1419 1420 dummy_state = or_state_new(); 1421 1422 hs_init(); 1423 MOCK(get_or_state, get_or_state_replacement); 1424 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close); 1425 MOCK(networkstatus_get_reasonably_live_consensus, 1426 mock_networkstatus_get_reasonably_live_consensus); 1427 1428 /* Descriptor rotation happens with a consensus with a new SRV. */ 1429 1430 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", 1431 &mock_ns.valid_after); 1432 tt_int_op(ret, OP_EQ, 0); 1433 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", 1434 &mock_ns.fresh_until); 1435 tt_int_op(ret, OP_EQ, 0); 1436 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after); 1437 1438 update_approx_time(mock_ns.valid_after+1); 1439 now = mock_ns.valid_after+1; 1440 1441 /* Create a service with a default descriptor and state. It's added to the 1442 * global map. */ 1443 service = helper_create_service(); 1444 service_descriptor_free(service->desc_current); 1445 service->desc_current = NULL; 1446 /* This triggers a build for both descriptors. The time now is only used in 1447 * the descriptor certificate which is important to be now else the decoding 1448 * will complain that the cert has expired if we use valid_after. */ 1449 build_all_descriptors(now); 1450 tt_assert(service->desc_current); 1451 tt_assert(service->desc_next); 1452 1453 /* Tweak our service next rotation time so we can use a custom time. */ 1454 service->state.next_rotation_time = next_rotation_time = 1455 mock_ns.valid_after + (11 * 60 * 60); 1456 1457 /* Nothing should happen, we are not at a new SRV. Our next rotation time 1458 * should be untouched. */ 1459 rotate_all_descriptors(mock_ns.valid_after); 1460 tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time); 1461 tt_assert(service->desc_current); 1462 tt_assert(service->desc_next); 1463 tt_u64_op(service->desc_current->time_period_num, OP_EQ, 1464 hs_get_previous_time_period_num(0)); 1465 tt_u64_op(service->desc_next->time_period_num, OP_EQ, 1466 hs_get_time_period_num(0)); 1467 /* Keep a reference so we can compare it after rotation to the current. */ 1468 desc_next = service->desc_next; 1469 1470 /* Going right after a new SRV. */ 1471 ret = parse_rfc1123_time("Sat, 27 Oct 1985 01:00:00 UTC", 1472 &mock_ns.valid_after); 1473 tt_int_op(ret, OP_EQ, 0); 1474 ret = parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC", 1475 &mock_ns.fresh_until); 1476 tt_int_op(ret, OP_EQ, 0); 1477 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after); 1478 1479 update_approx_time(mock_ns.valid_after+1); 1480 now = mock_ns.valid_after+1; 1481 1482 /* Note down what to expect for the next rotation time which is 01:00 + 23h 1483 * meaning 00:00:00. */ 1484 next_rotation_time = mock_ns.valid_after + (23 * 60 * 60); 1485 /* We should have our next rotation time modified, our current descriptor 1486 * cleaned up and the next descriptor becoming the current. */ 1487 rotate_all_descriptors(mock_ns.valid_after); 1488 tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time); 1489 tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next)); 1490 tt_assert(service->desc_next == NULL); 1491 1492 /* A second time should do nothing. */ 1493 rotate_all_descriptors(mock_ns.valid_after); 1494 tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time); 1495 tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next)); 1496 tt_assert(service->desc_next == NULL); 1497 1498 build_all_descriptors(now); 1499 tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next)); 1500 tt_u64_op(service->desc_current->time_period_num, OP_EQ, 1501 hs_get_time_period_num(0)); 1502 tt_u64_op(service->desc_next->time_period_num, OP_EQ, 1503 hs_get_next_time_period_num(0)); 1504 tt_assert(service->desc_next); 1505 1506 done: 1507 if (service) { 1508 remove_service(get_hs_service_map(), service); 1509 hs_service_free(service); 1510 } 1511 hs_free_all(); 1512 UNMOCK(get_or_state); 1513 UNMOCK(circuit_mark_for_close_); 1514 UNMOCK(networkstatus_get_reasonably_live_consensus); 1515 } 1516 1517 /** Test building descriptors: picking intro points, setting up their link 1518 * specifiers, etc. */ 1519 static void 1520 test_build_update_descriptors(void *arg) 1521 { 1522 int ret; 1523 node_t *node; 1524 hs_service_t *service = NULL; 1525 hs_service_intro_point_t *ip_cur, *ip_next; 1526 routerinfo_t ri; 1527 1528 (void) arg; 1529 1530 hs_init(); 1531 1532 MOCK(get_or_state, 1533 get_or_state_replacement); 1534 MOCK(networkstatus_get_reasonably_live_consensus, 1535 mock_networkstatus_get_reasonably_live_consensus); 1536 1537 dummy_state = or_state_new(); 1538 1539 ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC", 1540 &mock_ns.valid_after); 1541 tt_int_op(ret, OP_EQ, 0); 1542 ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC", 1543 &mock_ns.fresh_until); 1544 tt_int_op(ret, OP_EQ, 0); 1545 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after); 1546 1547 update_approx_time(mock_ns.valid_after+1); 1548 1549 time_t now = mock_ns.valid_after+1; 1550 1551 /* Create a service without a current descriptor to trigger a build. */ 1552 service = helper_create_service(); 1553 tt_assert(service); 1554 /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */ 1555 service_descriptor_free(service->desc_current); 1556 service->desc_current = NULL; 1557 1558 /* We have a fresh service so this should trigger a build for both 1559 * descriptors for specific time period that we'll test. */ 1560 build_all_descriptors(now); 1561 /* Check *current* descriptor. */ 1562 tt_assert(service->desc_current); 1563 tt_assert(service->desc_current->desc); 1564 tt_assert(service->desc_current->intro_points.map); 1565 /* The current time period is the one expected when starting at 03:00. */ 1566 tt_u64_op(service->desc_current->time_period_num, OP_EQ, 1567 hs_get_time_period_num(0)); 1568 /* This should be untouched, the update descriptor process changes it. */ 1569 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0); 1570 1571 /* Check *next* descriptor. */ 1572 tt_assert(service->desc_next); 1573 tt_assert(service->desc_next->desc); 1574 tt_assert(service->desc_next->intro_points.map); 1575 tt_assert(service->desc_current != service->desc_next); 1576 tt_u64_op(service->desc_next->time_period_num, OP_EQ, 1577 hs_get_next_time_period_num(0)); 1578 /* This should be untouched, the update descriptor process changes it. */ 1579 tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0); 1580 1581 /* Time to test the update of those descriptors. At first, we have no node 1582 * in the routerlist so this will find NO suitable node for the IPs. */ 1583 setup_full_capture_of_logs(LOG_INFO); 1584 update_all_descriptors_intro_points(now); 1585 expect_log_msg_containing("Unable to find a suitable node to be an " 1586 "introduction point for service"); 1587 teardown_capture_of_logs(); 1588 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1589 OP_EQ, 0); 1590 tt_int_op(digest256map_size(service->desc_next->intro_points.map), 1591 OP_EQ, 0); 1592 1593 /* Now, we'll setup a node_t. */ 1594 { 1595 curve25519_secret_key_t curve25519_secret_key; 1596 1597 memset(&ri, 0, sizeof(routerinfo_t)); 1598 1599 tor_addr_parse(&ri.ipv4_addr, "127.0.0.1"); 1600 ri.ipv4_orport = 1337; 1601 ri.purpose = ROUTER_PURPOSE_GENERAL; 1602 /* Ugly yes but we never free the "ri" object so this just makes things 1603 * easier. */ 1604 ri.protocol_list = (char *) "HSDir=1-2 LinkAuth=3"; 1605 summarize_protover_flags(&ri.pv, ri.protocol_list, NULL); 1606 ret = curve25519_secret_key_generate(&curve25519_secret_key, 0); 1607 tt_int_op(ret, OP_EQ, 0); 1608 ri.onion_curve25519_pkey = 1609 tor_malloc_zero(sizeof(curve25519_public_key_t)); 1610 curve25519_public_key_generate(ri.onion_curve25519_pkey, 1611 &curve25519_secret_key); 1612 memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN); 1613 /* Setup ed25519 identity */ 1614 ed25519_keypair_t kp1; 1615 ed25519_keypair_generate(&kp1, 0); 1616 ri.cache_info.signing_key_cert = tor_malloc_zero(sizeof(tor_cert_t)); 1617 tt_assert(ri.cache_info.signing_key_cert); 1618 ed25519_pubkey_copy(&ri.cache_info.signing_key_cert->signing_key, 1619 &kp1.pubkey); 1620 nodelist_set_routerinfo(&ri, NULL); 1621 node = node_get_mutable_by_id(ri.cache_info.identity_digest); 1622 tt_assert(node); 1623 node->is_running = node->is_valid = node->is_fast = node->is_stable = 1; 1624 } 1625 1626 /* We have to set this, or the lack of microdescriptors for these 1627 * nodes will make them unusable. */ 1628 get_options_mutable()->UseMicrodescriptors = 0; 1629 1630 /* We expect to pick only one intro point from the node above. */ 1631 setup_full_capture_of_logs(LOG_INFO); 1632 update_all_descriptors_intro_points(now); 1633 tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */ 1634 tor_free(node->ri->cache_info.signing_key_cert); 1635 expect_log_msg_containing("just picked 1 intro points and wanted 3 for next " 1636 "descriptor. It currently has 0 intro points. " 1637 "Launching ESTABLISH_INTRO circuit shortly."); 1638 teardown_capture_of_logs(); 1639 tt_int_op(digest256map_size(service->desc_current->intro_points.map), 1640 OP_EQ, 1); 1641 tt_int_op(digest256map_size(service->desc_next->intro_points.map), 1642 OP_EQ, 1); 1643 /* Get the IP object. Because we don't have the auth key of the IP, we can't 1644 * query it so get the first element in the map. */ 1645 { 1646 void *obj = NULL; 1647 const uint8_t *key; 1648 digest256map_iter_t *iter = 1649 digest256map_iter_init(service->desc_current->intro_points.map); 1650 digest256map_iter_get(iter, &key, &obj); 1651 tt_assert(obj); 1652 ip_cur = obj; 1653 /* Get also the IP from the next descriptor. We'll make sure it's not the 1654 * same object as in the current descriptor. */ 1655 iter = digest256map_iter_init(service->desc_next->intro_points.map); 1656 digest256map_iter_get(iter, &key, &obj); 1657 tt_assert(obj); 1658 ip_next = obj; 1659 } 1660 tt_mem_op(ip_cur, OP_NE, ip_next, sizeof(hs_desc_intro_point_t)); 1661 1662 /* We won't test the service IP object because there is a specific test 1663 * already for this but we'll make sure that the state is coherent.*/ 1664 1665 /* Three link specifiers are mandatory so make sure we do have them. */ 1666 tt_int_op(smartlist_len(ip_cur->base.link_specifiers), OP_EQ, 3); 1667 /* Make sure we have a valid encryption keypair generated when we pick an 1668 * intro point in the update process. */ 1669 tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.seckey.secret_key, 1670 CURVE25519_SECKEY_LEN)); 1671 tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.pubkey.public_key, 1672 CURVE25519_PUBKEY_LEN)); 1673 tt_u64_op(ip_cur->time_to_expire, OP_GE, now + 1674 INTRO_POINT_LIFETIME_MIN_SECONDS); 1675 tt_u64_op(ip_cur->time_to_expire, OP_LE, now + 1676 INTRO_POINT_LIFETIME_MAX_SECONDS); 1677 1678 /* Now, we will try to set up a service after a new time period has started 1679 * and see if it behaves as expected. */ 1680 1681 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", 1682 &mock_ns.valid_after); 1683 tt_int_op(ret, OP_EQ, 0); 1684 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", 1685 &mock_ns.fresh_until); 1686 tt_int_op(ret, OP_EQ, 0); 1687 1688 update_approx_time(mock_ns.valid_after+1); 1689 now = mock_ns.valid_after+1; 1690 1691 /* Create a service without a current descriptor to trigger a build. */ 1692 service = helper_create_service(); 1693 tt_assert(service); 1694 /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */ 1695 service_descriptor_free(service->desc_current); 1696 service->desc_current = NULL; 1697 1698 /* We have a fresh service so this should trigger a build for both 1699 * descriptors for specific time period that we'll test. */ 1700 build_all_descriptors(now); 1701 /* Check *current* descriptor. */ 1702 tt_assert(service->desc_current); 1703 tt_assert(service->desc_current->desc); 1704 tt_assert(service->desc_current->intro_points.map); 1705 /* This should be for the previous time period. */ 1706 tt_u64_op(service->desc_current->time_period_num, OP_EQ, 1707 hs_get_previous_time_period_num(0)); 1708 /* This should be untouched, the update descriptor process changes it. */ 1709 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0); 1710 1711 /* Check *next* descriptor. */ 1712 tt_assert(service->desc_next); 1713 tt_assert(service->desc_next->desc); 1714 tt_assert(service->desc_next->intro_points.map); 1715 tt_assert(service->desc_current != service->desc_next); 1716 tt_u64_op(service->desc_next->time_period_num, OP_EQ, 1717 hs_get_time_period_num(0)); 1718 /* This should be untouched, the update descriptor process changes it. */ 1719 tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0); 1720 1721 /* Let's remove the next descriptor to simulate a rotation. */ 1722 service_descriptor_free(service->desc_next); 1723 service->desc_next = NULL; 1724 1725 build_all_descriptors(now); 1726 /* Check *next* descriptor. */ 1727 tt_assert(service->desc_next); 1728 tt_assert(service->desc_next->desc); 1729 tt_assert(service->desc_next->intro_points.map); 1730 tt_assert(service->desc_current != service->desc_next); 1731 tt_u64_op(service->desc_next->time_period_num, OP_EQ, 1732 hs_get_next_time_period_num(0)); 1733 /* This should be untouched, the update descriptor process changes it. */ 1734 tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0); 1735 1736 done: 1737 if (service) { 1738 remove_service(get_hs_service_map(), service); 1739 hs_service_free(service); 1740 } 1741 hs_free_all(); 1742 nodelist_free_all(); 1743 } 1744 1745 /** Test building descriptors. We use this separate function instead of 1746 * using test_build_update_descriptors because that function is too complex 1747 * and also too interactive. */ 1748 static void 1749 test_build_descriptors(void *arg) 1750 { 1751 int ret; 1752 time_t now = time(NULL); 1753 hs_service_t *last_service = NULL; 1754 1755 (void) arg; 1756 1757 hs_init(); 1758 1759 MOCK(get_or_state, 1760 get_or_state_replacement); 1761 MOCK(networkstatus_get_reasonably_live_consensus, 1762 mock_networkstatus_get_reasonably_live_consensus); 1763 1764 dummy_state = or_state_new(); 1765 1766 ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC", 1767 &mock_ns.valid_after); 1768 tt_int_op(ret, OP_EQ, 0); 1769 ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC", 1770 &mock_ns.fresh_until); 1771 tt_int_op(ret, OP_EQ, 0); 1772 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after); 1773 1774 /* Generate a valid number of fake auth clients when a client authorization 1775 * is disabled. */ 1776 { 1777 hs_service_t *service = helper_create_service(); 1778 last_service = service; 1779 service_descriptor_free(service->desc_current); 1780 service->desc_current = NULL; 1781 1782 build_all_descriptors(now); 1783 tt_assert(service->desc_current); 1784 tt_assert(service->desc_current->desc); 1785 1786 hs_desc_superencrypted_data_t *superencrypted; 1787 superencrypted = &service->desc_current->desc->superencrypted_data; 1788 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16); 1789 1790 helper_destroy_service(service); 1791 last_service = NULL; 1792 } 1793 1794 /* Generate a valid number of fake auth clients when the number of 1795 * clients is zero. */ 1796 { 1797 hs_service_t *service = helper_create_service_with_clients(0); 1798 last_service = service; 1799 service_descriptor_free(service->desc_current); 1800 service->desc_current = NULL; 1801 1802 build_all_descriptors(now); 1803 hs_desc_superencrypted_data_t *superencrypted; 1804 superencrypted = &service->desc_current->desc->superencrypted_data; 1805 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16); 1806 1807 helper_destroy_service(service); 1808 last_service = NULL; 1809 } 1810 1811 /* Generate a valid number of fake auth clients when the number of 1812 * clients is not a multiple of 16. */ 1813 { 1814 hs_service_t *service = helper_create_service_with_clients(20); 1815 last_service = service; 1816 service_descriptor_free(service->desc_current); 1817 service->desc_current = NULL; 1818 1819 build_all_descriptors(now); 1820 hs_desc_superencrypted_data_t *superencrypted; 1821 superencrypted = &service->desc_current->desc->superencrypted_data; 1822 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32); 1823 1824 helper_destroy_service(service); 1825 last_service = NULL; 1826 } 1827 1828 /* Do not generate any fake desc client when the number of clients is 1829 * a multiple of 16 but not zero. */ 1830 { 1831 hs_service_t *service = helper_create_service_with_clients(32); 1832 last_service = service; 1833 service_descriptor_free(service->desc_current); 1834 service->desc_current = NULL; 1835 1836 build_all_descriptors(now); 1837 hs_desc_superencrypted_data_t *superencrypted; 1838 superencrypted = &service->desc_current->desc->superencrypted_data; 1839 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32); 1840 1841 helper_destroy_service(service); 1842 last_service = NULL; 1843 } 1844 1845 done: 1846 helper_destroy_service(last_service); 1847 hs_free_all(); 1848 } 1849 1850 static void 1851 test_upload_descriptors(void *arg) 1852 { 1853 int ret; 1854 time_t now; 1855 hs_service_t *service; 1856 1857 (void) arg; 1858 1859 hs_init(); 1860 MOCK(get_or_state, 1861 get_or_state_replacement); 1862 MOCK(networkstatus_get_reasonably_live_consensus, 1863 mock_networkstatus_get_reasonably_live_consensus); 1864 1865 dummy_state = or_state_new(); 1866 1867 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", 1868 &mock_ns.valid_after); 1869 tt_int_op(ret, OP_EQ, 0); 1870 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", 1871 &mock_ns.fresh_until); 1872 tt_int_op(ret, OP_EQ, 0); 1873 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after); 1874 1875 update_approx_time(mock_ns.valid_after+1); 1876 now = mock_ns.valid_after+1; 1877 1878 /* Create a service with no descriptor. It's added to the global map. */ 1879 service = hs_service_new(get_options()); 1880 tt_assert(service); 1881 service->config.version = HS_VERSION_THREE; 1882 ed25519_secret_key_generate(&service->keys.identity_sk, 0); 1883 ed25519_public_key_generate(&service->keys.identity_pk, 1884 &service->keys.identity_sk); 1885 /* Register service to global map. */ 1886 ret = register_service(get_hs_service_map(), service); 1887 tt_int_op(ret, OP_EQ, 0); 1888 /* But first, build our descriptor. */ 1889 build_all_descriptors(now); 1890 1891 /* Nothing should happen because we have 0 introduction circuit established 1892 * and we want (by default) 3 intro points. */ 1893 run_upload_descriptor_event(now); 1894 /* If no upload happened, this should be untouched. */ 1895 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0); 1896 /* We'll simulate that we've opened our intro point circuit and that we only 1897 * want one intro point. */ 1898 service->config.num_intro_points = 1; 1899 1900 /* Set our next upload time after now which will skip the upload. */ 1901 service->desc_current->next_upload_time = now + 1000; 1902 run_upload_descriptor_event(now); 1903 /* If no upload happened, this should be untouched. */ 1904 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, now + 1000); 1905 1906 done: 1907 hs_free_all(); 1908 UNMOCK(get_or_state); 1909 } 1910 1911 /** Global vars used by test_rendezvous1_parsing() */ 1912 static char rend1_payload[RELAY_PAYLOAD_SIZE]; 1913 static size_t rend1_payload_len = 0; 1914 1915 /** Mock for relay_send_command_from_edge() to send a RENDEZVOUS1 cell. Instead 1916 * of sending it to the network, instead save it to the global `rend1_payload` 1917 * variable so that we can inspect it in the test_rendezvous1_parsing() 1918 * test. */ 1919 static int 1920 mock_relay_send_rendezvous1(streamid_t stream_id, circuit_t *circ, 1921 uint8_t relay_command, const char *payload, 1922 size_t payload_len, 1923 crypt_path_t *cpath_layer, 1924 const char *filename, int lineno) 1925 { 1926 (void) stream_id; 1927 (void) circ; 1928 (void) relay_command; 1929 (void) cpath_layer; 1930 (void) filename; 1931 (void) lineno; 1932 1933 memcpy(rend1_payload, payload, payload_len); 1934 rend1_payload_len = payload_len; 1935 1936 return 0; 1937 } 1938 1939 /** Send a RENDEZVOUS1 as a service, and parse it as a client. */ 1940 static void 1941 test_rendezvous1_parsing(void *arg) 1942 { 1943 int retval; 1944 static const char *test_addr = 1945 "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion"; 1946 hs_service_t *service = NULL; 1947 origin_circuit_t *service_circ = NULL; 1948 origin_circuit_t *client_circ = NULL; 1949 ed25519_keypair_t ip_auth_kp; 1950 curve25519_keypair_t ephemeral_kp; 1951 curve25519_keypair_t client_kp; 1952 curve25519_keypair_t ip_enc_kp; 1953 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL; 1954 1955 (void) arg; 1956 1957 MOCK(relay_send_command_from_edge_, mock_relay_send_rendezvous1); 1958 1959 { 1960 /* Let's start by setting up the service that will start the rend */ 1961 service = tor_malloc_zero(sizeof(hs_service_t)); 1962 ed25519_secret_key_generate(&service->keys.identity_sk, 0); 1963 ed25519_public_key_generate(&service->keys.identity_pk, 1964 &service->keys.identity_sk); 1965 memcpy(service->onion_address, test_addr, sizeof(service->onion_address)); 1966 tt_assert(service); 1967 } 1968 1969 { 1970 /* Now let's set up the service rendezvous circuit and its keys. */ 1971 service_circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND, 1972 flags); 1973 tor_free(service_circ->hs_ident); 1974 hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys; 1975 uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN]; 1976 curve25519_keypair_generate(&ip_enc_kp, 0); 1977 curve25519_keypair_generate(&ephemeral_kp, 0); 1978 curve25519_keypair_generate(&client_kp, 0); 1979 ed25519_keypair_generate(&ip_auth_kp, 0); 1980 retval = hs_ntor_service_get_rendezvous1_keys(&ip_auth_kp.pubkey, 1981 &ip_enc_kp, 1982 &ephemeral_kp, 1983 &client_kp.pubkey, 1984 &hs_ntor_rend_cell_keys); 1985 tt_int_op(retval, OP_EQ, 0); 1986 1987 memset(rendezvous_cookie, 2, sizeof(rendezvous_cookie)); 1988 service_circ->hs_ident = 1989 create_rp_circuit_identifier(service, rendezvous_cookie, 1990 &ephemeral_kp.pubkey, 1991 &hs_ntor_rend_cell_keys); 1992 } 1993 1994 /* Send out the RENDEZVOUS1 and make sure that our mock func worked */ 1995 tt_assert(fast_mem_is_zero(rend1_payload, 32)); 1996 hs_circ_service_rp_has_opened(service, service_circ); 1997 tt_assert(!fast_mem_is_zero(rend1_payload, 32)); 1998 tt_int_op(rend1_payload_len, OP_EQ, HS_LEGACY_RENDEZVOUS_CELL_SIZE); 1999 2000 /******************************/ 2001 2002 /** Now let's create the client rendezvous circuit */ 2003 client_circ = 2004 helper_create_origin_circuit(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED, 2005 flags); 2006 /* fix up its circ ident */ 2007 ed25519_pubkey_copy(&client_circ->hs_ident->intro_auth_pk, 2008 &ip_auth_kp.pubkey); 2009 memcpy(&client_circ->hs_ident->rendezvous_client_kp, 2010 &client_kp, sizeof(client_circ->hs_ident->rendezvous_client_kp)); 2011 memcpy(&client_circ->hs_ident->intro_enc_pk.public_key, 2012 &ip_enc_kp.pubkey.public_key, 2013 sizeof(client_circ->hs_ident->intro_enc_pk.public_key)); 2014 2015 /* Now parse the rendezvous2 circuit and make sure it was fine. We are 2016 * skipping 20 bytes off its payload, since that's the rendezvous cookie 2017 * which is only present in REND1. */ 2018 retval = handle_rendezvous2(client_circ, 2019 (uint8_t*)rend1_payload+20, 2020 rend1_payload_len-20); 2021 tt_int_op(retval, OP_EQ, 0); 2022 2023 /* TODO: We are only simulating client/service here. We could also simulate 2024 * the rendezvous point by plugging in rend_mid_establish_rendezvous(). We 2025 * would need an extra circuit and some more stuff but it's doable. */ 2026 2027 done: 2028 circuit_free_(TO_CIRCUIT(service_circ)); 2029 circuit_free_(TO_CIRCUIT(client_circ)); 2030 hs_service_free(service); 2031 hs_free_all(); 2032 UNMOCK(relay_send_command_from_edge_); 2033 } 2034 2035 static void 2036 test_authorized_client_config_equal(void *arg) 2037 { 2038 int ret; 2039 hs_service_config_t *config1, *config2; 2040 2041 (void) arg; 2042 2043 config1 = tor_malloc_zero(sizeof(*config1)); 2044 config2 = tor_malloc_zero(sizeof(*config2)); 2045 2046 /* Both configs are empty. */ 2047 { 2048 config1->clients = smartlist_new(); 2049 config2->clients = smartlist_new(); 2050 2051 ret = service_authorized_client_config_equal(config1, config2); 2052 tt_int_op(ret, OP_EQ, 1); 2053 2054 service_clear_config(config1); 2055 service_clear_config(config2); 2056 } 2057 2058 /* Both configs have exactly the same client config. */ 2059 { 2060 config1->clients = smartlist_new(); 2061 config2->clients = smartlist_new(); 2062 2063 hs_service_authorized_client_t *client1, *client2; 2064 client1 = helper_create_authorized_client(); 2065 client2 = helper_create_authorized_client(); 2066 2067 smartlist_add(config1->clients, client1); 2068 smartlist_add(config1->clients, client2); 2069 2070 /* We should swap the order of clients here to test that the order 2071 * does not matter. */ 2072 smartlist_add(config2->clients, helper_clone_authorized_client(client2)); 2073 smartlist_add(config2->clients, helper_clone_authorized_client(client1)); 2074 2075 ret = service_authorized_client_config_equal(config1, config2); 2076 tt_int_op(ret, OP_EQ, 1); 2077 2078 service_clear_config(config1); 2079 service_clear_config(config2); 2080 } 2081 2082 /* The numbers of clients in both configs are not equal. */ 2083 { 2084 config1->clients = smartlist_new(); 2085 config2->clients = smartlist_new(); 2086 2087 hs_service_authorized_client_t *client1, *client2; 2088 client1 = helper_create_authorized_client(); 2089 client2 = helper_create_authorized_client(); 2090 2091 smartlist_add(config1->clients, client1); 2092 smartlist_add(config1->clients, client2); 2093 2094 smartlist_add(config2->clients, helper_clone_authorized_client(client1)); 2095 2096 ret = service_authorized_client_config_equal(config1, config2); 2097 tt_int_op(ret, OP_EQ, 0); 2098 2099 service_clear_config(config1); 2100 service_clear_config(config2); 2101 } 2102 2103 /* The first config has two distinct clients while the second config 2104 * has two clients but they are duplicate. */ 2105 { 2106 config1->clients = smartlist_new(); 2107 config2->clients = smartlist_new(); 2108 2109 hs_service_authorized_client_t *client1, *client2; 2110 client1 = helper_create_authorized_client(); 2111 client2 = helper_create_authorized_client(); 2112 2113 smartlist_add(config1->clients, client1); 2114 smartlist_add(config1->clients, client2); 2115 2116 smartlist_add(config2->clients, helper_clone_authorized_client(client1)); 2117 smartlist_add(config2->clients, helper_clone_authorized_client(client1)); 2118 2119 ret = service_authorized_client_config_equal(config1, config2); 2120 tt_int_op(ret, OP_EQ, 0); 2121 2122 service_clear_config(config1); 2123 service_clear_config(config2); 2124 } 2125 2126 /* Both configs have totally distinct clients. */ 2127 { 2128 config1->clients = smartlist_new(); 2129 config2->clients = smartlist_new(); 2130 2131 hs_service_authorized_client_t *client1, *client2, *client3, *client4; 2132 client1 = helper_create_authorized_client(); 2133 client2 = helper_create_authorized_client(); 2134 client3 = helper_create_authorized_client(); 2135 client4 = helper_create_authorized_client(); 2136 2137 smartlist_add(config1->clients, client1); 2138 smartlist_add(config1->clients, client2); 2139 2140 smartlist_add(config2->clients, client3); 2141 smartlist_add(config2->clients, client4); 2142 2143 ret = service_authorized_client_config_equal(config1, config2); 2144 tt_int_op(ret, OP_EQ, 0); 2145 2146 service_clear_config(config1); 2147 service_clear_config(config2); 2148 } 2149 2150 done: 2151 tor_free(config1); 2152 tor_free(config2); 2153 } 2154 2155 /** Test that client circuit ID gets correctly exported */ 2156 static void 2157 test_export_client_circuit_id(void *arg) 2158 { 2159 origin_circuit_t *or_circ = NULL; 2160 size_t sz; 2161 char *cp1=NULL, *cp2=NULL; 2162 connection_t *conn = NULL; 2163 2164 (void) arg; 2165 2166 MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock); 2167 2168 hs_service_init(); 2169 2170 /* Create service */ 2171 hs_service_t *service = helper_create_service(); 2172 /* Check that export circuit ID detection works */ 2173 service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_NONE; 2174 tt_int_op(0, OP_EQ, 2175 hs_service_exports_circuit_id(&service->keys.identity_pk)); 2176 service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_HAPROXY; 2177 tt_int_op(1, OP_EQ, 2178 hs_service_exports_circuit_id(&service->keys.identity_pk)); 2179 2180 /* Create client connection */ 2181 conn = test_conn_get_connection(AP_CONN_STATE_CIRCUIT_WAIT, CONN_TYPE_AP, 0); 2182 2183 /* Create client edge conn hs_ident */ 2184 edge_connection_t *edge_conn = TO_EDGE_CONN(conn); 2185 edge_conn->hs_ident = hs_ident_edge_conn_new(&service->keys.identity_pk); 2186 edge_conn->hs_ident->orig_virtual_port = 42; 2187 2188 /* Create rend circuit */ 2189 or_circ = origin_circuit_new(); 2190 or_circ->base_.purpose = CIRCUIT_PURPOSE_C_REND_JOINED; 2191 edge_conn->on_circuit = TO_CIRCUIT(or_circ); 2192 or_circ->global_identifier = 666; 2193 2194 /* Export circuit ID */ 2195 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); 2196 2197 /* Check contents */ 2198 cp1 = buf_get_contents(conn->outbuf, &sz); 2199 tt_str_op(cp1, OP_EQ, 2200 "PROXY TCP6 fc00:dead:beef:4dad::0:29a ::1 666 42\r\n"); 2201 2202 /* Change circ GID and see that the reported circuit ID also changes */ 2203 or_circ->global_identifier = 22; 2204 2205 /* check changes */ 2206 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); 2207 cp2 = buf_get_contents(conn->outbuf, &sz); 2208 tt_str_op(cp1, OP_NE, cp2); 2209 tor_free(cp1); 2210 2211 /* Check that GID with UINT32_MAX works. */ 2212 or_circ->global_identifier = UINT32_MAX; 2213 2214 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); 2215 cp1 = buf_get_contents(conn->outbuf, &sz); 2216 tt_str_op(cp1, OP_EQ, 2217 "PROXY TCP6 fc00:dead:beef:4dad::ffff:ffff ::1 65535 42\r\n"); 2218 tor_free(cp1); 2219 2220 /* Check that GID with UINT16_MAX works. */ 2221 or_circ->global_identifier = UINT16_MAX; 2222 2223 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); 2224 cp1 = buf_get_contents(conn->outbuf, &sz); 2225 tt_str_op(cp1, OP_EQ, 2226 "PROXY TCP6 fc00:dead:beef:4dad::0:ffff ::1 65535 42\r\n"); 2227 tor_free(cp1); 2228 2229 /* Check that GID with UINT16_MAX + 7 works. */ 2230 or_circ->global_identifier = UINT16_MAX + 7; 2231 2232 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol); 2233 cp1 = buf_get_contents(conn->outbuf, &sz); 2234 tt_str_op(cp1, OP_EQ, "PROXY TCP6 fc00:dead:beef:4dad::1:6 ::1 6 42\r\n"); 2235 2236 done: 2237 UNMOCK(connection_write_to_buf_impl_); 2238 circuit_free_(TO_CIRCUIT(or_circ)); 2239 connection_free_minimal(conn); 2240 hs_service_free(service); 2241 tor_free(cp1); 2242 tor_free(cp2); 2243 } 2244 2245 static smartlist_t * 2246 mock_node_get_link_specifier_smartlist(const node_t *node, bool direct_conn) 2247 { 2248 (void) node; 2249 (void) direct_conn; 2250 2251 smartlist_t *lspecs = smartlist_new(); 2252 link_specifier_t *ls_legacy = link_specifier_new(); 2253 smartlist_add(lspecs, ls_legacy); 2254 2255 return lspecs; 2256 } 2257 2258 static node_t *fake_node = NULL; 2259 2260 static const node_t * 2261 mock_build_state_get_exit_node(cpath_build_state_t *state) 2262 { 2263 (void) state; 2264 2265 if (!fake_node) { 2266 curve25519_secret_key_t seckey; 2267 curve25519_secret_key_generate(&seckey, 0); 2268 2269 fake_node = tor_malloc_zero(sizeof(node_t)); 2270 fake_node->ri = tor_malloc_zero(sizeof(routerinfo_t)); 2271 fake_node->ri->onion_curve25519_pkey = 2272 tor_malloc_zero(sizeof(curve25519_public_key_t)); 2273 curve25519_public_key_generate(fake_node->ri->onion_curve25519_pkey, 2274 &seckey); 2275 } 2276 2277 return fake_node; 2278 } 2279 2280 static void 2281 mock_launch_rendezvous_point_circuit(const hs_service_t *service, 2282 const ed25519_public_key_t *ip_auth_pubkey, 2283 const curve25519_keypair_t *ip_enc_key_kp, 2284 const hs_cell_intro_rdv_data_t *rdv_data, 2285 time_t now) 2286 { 2287 (void) service; 2288 (void) ip_auth_pubkey; 2289 (void) ip_enc_key_kp; 2290 (void) rdv_data; 2291 (void) now; 2292 return; 2293 } 2294 2295 /** 2296 * Test that INTRO2 cells are handled well by onion services in the normal 2297 * case and also when onionbalance is enabled. 2298 */ 2299 static void 2300 test_intro2_handling(void *arg) 2301 { 2302 (void)arg; 2303 2304 MOCK(build_state_get_exit_node, mock_build_state_get_exit_node); 2305 MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge); 2306 MOCK(node_get_link_specifier_smartlist, 2307 mock_node_get_link_specifier_smartlist); 2308 MOCK(launch_rendezvous_point_circuit, mock_launch_rendezvous_point_circuit); 2309 2310 memset(relay_payload, 0, sizeof(relay_payload)); 2311 2312 int retval; 2313 time_t now = 0101010101; 2314 update_approx_time(now); 2315 2316 /** OK this is the play: 2317 * 2318 * In Act I, we have a standalone onion service X (without onionbalance 2319 * enabled). We test that X can properly handle INTRO2 cells sent by a 2320 * client Alice. 2321 * 2322 * In Act II, we create an onionbalance setup with frontend being Z which 2323 * includes instances X and Y. We then setup onionbalance on X and test that 2324 * Alice who addresses Z can communicate with X through INTRO2 cells. 2325 * 2326 * In Act III, we test that Alice can also communicate with X 2327 * directly even tho onionbalance is enabled. 2328 * 2329 * And finally in Act IV, we check various cases where the INTRO2 cell 2330 * should not go through because the subcredentials don't line up 2331 * (e.g. Alice sends INTRO2 to X using Y's subcredential). 2332 */ 2333 2334 /** Let's start with some setup! Create the instances and the frontend 2335 service, create Alice, etc: */ 2336 2337 /* Create instance X */ 2338 hs_service_t x_service; 2339 memset(&x_service, 0, sizeof(hs_service_t)); 2340 /* Disable onionbalance */ 2341 x_service.config.ob_master_pubkeys = NULL; 2342 x_service.state.replay_cache_rend_cookie = replaycache_new(0,0); 2343 /* Initialize the metrics store */ 2344 hs_metrics_service_init(&x_service); 2345 2346 /* Create subcredential for x: */ 2347 ed25519_keypair_t x_identity_keypair; 2348 hs_subcredential_t x_subcred; 2349 ed25519_keypair_generate(&x_identity_keypair, 0); 2350 hs_helper_get_subcred_from_identity_keypair(&x_identity_keypair, 2351 &x_subcred); 2352 2353 /* Create the x instance's intro point */ 2354 hs_service_intro_point_t *x_ip = NULL; 2355 { 2356 curve25519_secret_key_t seckey; 2357 curve25519_public_key_t pkey; 2358 curve25519_secret_key_generate(&seckey, 0); 2359 curve25519_public_key_generate(&pkey, &seckey); 2360 2361 node_t intro_node; 2362 memset(&intro_node, 0, sizeof(intro_node)); 2363 routerinfo_t ri; 2364 memset(&ri, 0, sizeof(routerinfo_t)); 2365 ri.onion_curve25519_pkey = &pkey; 2366 intro_node.ri = &ri; 2367 2368 x_ip = service_intro_point_new(&intro_node); 2369 } 2370 2371 /* Create z frontend's subcredential */ 2372 ed25519_keypair_t z_identity_keypair; 2373 hs_subcredential_t z_subcred; 2374 ed25519_keypair_generate(&z_identity_keypair, 0); 2375 hs_helper_get_subcred_from_identity_keypair(&z_identity_keypair, 2376 &z_subcred); 2377 2378 /* Create y instance's subcredential */ 2379 ed25519_keypair_t y_identity_keypair; 2380 hs_subcredential_t y_subcred; 2381 ed25519_keypair_generate(&y_identity_keypair, 0); 2382 hs_helper_get_subcred_from_identity_keypair(&y_identity_keypair, 2383 &y_subcred); 2384 2385 /* Create Alice's intro point */ 2386 hs_desc_intro_point_t *alice_ip; 2387 ed25519_keypair_t signing_kp; 2388 ed25519_keypair_generate(&signing_kp, 0); 2389 alice_ip = hs_helper_build_intro_point(&signing_kp, now, "1.2.3.4", 0, 2390 &x_ip->auth_key_kp, 2391 &x_ip->enc_key_kp); 2392 2393 /* Create Alice's intro and rend circuits */ 2394 origin_circuit_t *intro_circ = origin_circuit_new(); 2395 intro_circ->cpath = tor_malloc_zero(sizeof(crypt_path_t)); 2396 intro_circ->cpath->prev = intro_circ->cpath; 2397 intro_circ->hs_ident = tor_malloc_zero(sizeof(*intro_circ->hs_ident)); 2398 origin_circuit_t rend_circ; 2399 TO_CIRCUIT(&rend_circ)->ccontrol = NULL; 2400 rend_circ.hs_ident = tor_malloc_zero(sizeof(*rend_circ.hs_ident)); 2401 curve25519_keypair_generate(&rend_circ.hs_ident->rendezvous_client_kp, 0); 2402 memset(rend_circ.hs_ident->rendezvous_cookie, 'r', HS_REND_COOKIE_LEN); 2403 2404 /* ************************************************************ */ 2405 2406 /* Act I: 2407 * 2408 * Where Alice connects to X without onionbalance in the picture */ 2409 2410 /* Create INTRODUCE1 */ 2411 tt_assert(fast_mem_is_zero(relay_payload, sizeof(relay_payload))); 2412 retval = hs_circ_send_introduce1(intro_circ, &rend_circ, 2413 alice_ip, &x_subcred, NULL); 2414 2415 /* Check that the payload was written successfully */ 2416 tt_int_op(retval, OP_EQ, 0); 2417 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload))); 2418 tt_int_op(relay_payload_len, OP_NE, 0); 2419 2420 /* Handle the cell */ 2421 retval = hs_circ_handle_introduce2(&x_service, 2422 intro_circ, x_ip, 2423 &x_subcred, 2424 (uint8_t*)relay_payload,relay_payload_len); 2425 tt_int_op(retval, OP_EQ, 0); 2426 2427 /* ************************************************************ */ 2428 2429 /* Act II: 2430 * 2431 * We now create an onionbalance setup with Z being the frontend and X and Y 2432 * being the backend instances. Make sure that Alice can talk with the 2433 * backend instance X even tho she thinks she is talking to the frontend Z. 2434 */ 2435 2436 /* Now configure the X instance to do onionbalance with Z as the frontend */ 2437 x_service.config.ob_master_pubkeys = smartlist_new(); 2438 smartlist_add(x_service.config.ob_master_pubkeys, 2439 &z_identity_keypair.pubkey); 2440 2441 /* Create descriptors for x and load next descriptor with the x's 2442 * subcredential so that it can accept connections for itself. */ 2443 x_service.desc_current = service_descriptor_new(); 2444 memset(x_service.desc_current->desc->subcredential.subcred, 'C',SUBCRED_LEN); 2445 x_service.desc_next = service_descriptor_new(); 2446 memcpy(&x_service.desc_next->desc->subcredential, &x_subcred, SUBCRED_LEN); 2447 2448 /* Refresh OB keys */ 2449 hs_ob_refresh_keys(&x_service); 2450 2451 /* Create INTRODUCE1 from Alice to X through Z */ 2452 memset(relay_payload, 0, sizeof(relay_payload)); 2453 retval = hs_circ_send_introduce1(intro_circ, &rend_circ, 2454 alice_ip, &z_subcred, NULL); 2455 2456 /* Check that the payload was written successfully */ 2457 tt_int_op(retval, OP_EQ, 0); 2458 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload))); 2459 tt_int_op(relay_payload_len, OP_NE, 0); 2460 2461 /* Deliver INTRODUCE1 to X even tho it carries Z's subcredential */ 2462 replaycache_free(x_service.state.replay_cache_rend_cookie); 2463 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0); 2464 2465 retval = hs_circ_handle_introduce2(&x_service, 2466 intro_circ, x_ip, 2467 &z_subcred, 2468 (uint8_t*)relay_payload, relay_payload_len); 2469 tt_int_op(retval, OP_EQ, 0); 2470 2471 replaycache_free(x_ip->replay_cache); 2472 x_ip->replay_cache = replaycache_new(0, 0); 2473 2474 replaycache_free(x_service.state.replay_cache_rend_cookie); 2475 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0); 2476 2477 /* ************************************************************ */ 2478 2479 /* Act III: 2480 * 2481 * Now send a direct INTRODUCE cell from Alice to X using X's subcredential 2482 * and check that it succeeds even with onionbalance enabled. 2483 */ 2484 2485 /* Refresh OB keys (just to check for memleaks) */ 2486 hs_ob_refresh_keys(&x_service); 2487 2488 /* Create INTRODUCE1 from Alice to X using X's subcred. */ 2489 memset(relay_payload, 0, sizeof(relay_payload)); 2490 retval = hs_circ_send_introduce1(intro_circ, &rend_circ, 2491 alice_ip, &x_subcred, NULL); 2492 2493 /* Check that the payload was written successfully */ 2494 tt_int_op(retval, OP_EQ, 0); 2495 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload))); 2496 tt_int_op(relay_payload_len, OP_NE, 0); 2497 2498 /* Send INTRODUCE1 to X with X's subcredential (should succeed) */ 2499 replaycache_free(x_service.state.replay_cache_rend_cookie); 2500 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0); 2501 2502 retval = hs_circ_handle_introduce2(&x_service, 2503 intro_circ, x_ip, 2504 &x_subcred, 2505 (uint8_t*)relay_payload, relay_payload_len); 2506 tt_int_op(retval, OP_EQ, 0); 2507 2508 /* We haven't encountered any errors yet, so all the introduction request 2509 * error metrics should be 0 */ 2510 const smartlist_t *entries = metrics_store_get_all( 2511 x_service.metrics.store, "tor_hs_intro_rejected_intro_req_count"); 2512 const metrics_store_entry_t *entry = NULL; 2513 2514 for (size_t i = 0; i < hs_metrics_intro_req_error_reasons_size; ++i) { 2515 entry = metrics_store_find_entry_with_label( 2516 entries, 2517 metrics_format_label("reason", hs_metrics_intro_req_error_reasons[i])); 2518 tt_assert(entry); 2519 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 0); 2520 } 2521 2522 /* ************************************************************ */ 2523 2524 /* Act IV: 2525 * 2526 * Test cases where the INTRO2 cell should not be able to decode. 2527 */ 2528 2529 /* Try sending the exact same INTRODUCE2 cell again and see that the intro 2530 * point replay cache triggers: */ 2531 setup_full_capture_of_logs(LOG_WARN); 2532 retval = hs_circ_handle_introduce2(&x_service, 2533 intro_circ, x_ip, 2534 &x_subcred, 2535 (uint8_t*)relay_payload, relay_payload_len); 2536 tt_int_op(retval, OP_EQ, -1); 2537 expect_log_msg_containing("with the same ENCRYPTED section"); 2538 teardown_capture_of_logs(); 2539 entry = metrics_store_find_entry_with_label( 2540 entries, 2541 metrics_format_label("reason", HS_METRICS_ERR_INTRO_REQ_INTRODUCE2)); 2542 tt_assert(entry); 2543 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 1); 2544 2545 /* Now cleanup the intro point replay cache but not the service replay cache 2546 and see that this one triggers this time. */ 2547 replaycache_free(x_ip->replay_cache); 2548 x_ip->replay_cache = replaycache_new(0, 0); 2549 setup_full_capture_of_logs(LOG_INFO); 2550 retval = hs_circ_handle_introduce2(&x_service, 2551 intro_circ, x_ip, 2552 &x_subcred, 2553 (uint8_t*)relay_payload, relay_payload_len); 2554 tt_int_op(retval, OP_EQ, -1); 2555 expect_log_msg_containing("with same REND_COOKIE"); 2556 teardown_capture_of_logs(); 2557 2558 entry = metrics_store_find_entry_with_label( 2559 entries, metrics_format_label( 2560 "reason", HS_METRICS_ERR_INTRO_REQ_INTRODUCE2_REPLAY)); 2561 tt_assert(entry); 2562 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 1); 2563 2564 /* Now just to make sure cleanup both replay caches and make sure that the 2565 cell gets through */ 2566 replaycache_free(x_ip->replay_cache); 2567 x_ip->replay_cache = replaycache_new(0, 0); 2568 replaycache_free(x_service.state.replay_cache_rend_cookie); 2569 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0); 2570 retval = hs_circ_handle_introduce2(&x_service, 2571 intro_circ, x_ip, 2572 &x_subcred, 2573 (uint8_t*)relay_payload, relay_payload_len); 2574 tt_int_op(retval, OP_EQ, 0); 2575 2576 /* This time, the error metric was *not* incremented */ 2577 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 1); 2578 2579 /* As a final thing, create an INTRODUCE1 cell from Alice to X using Y's 2580 * subcred (should fail since Y is just another instance and not the frontend 2581 * service!) */ 2582 memset(relay_payload, 0, sizeof(relay_payload)); 2583 retval = hs_circ_send_introduce1(intro_circ, &rend_circ, 2584 alice_ip, &y_subcred, NULL); 2585 tt_int_op(retval, OP_EQ, 0); 2586 2587 /* Check that the payload was written successfully */ 2588 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload))); 2589 tt_int_op(relay_payload_len, OP_NE, 0); 2590 2591 retval = hs_circ_handle_introduce2(&x_service, 2592 intro_circ, x_ip, 2593 &y_subcred, 2594 (uint8_t*)relay_payload, relay_payload_len); 2595 2596 tt_int_op(retval, OP_EQ, -1); 2597 entry = metrics_store_find_entry_with_label( 2598 entries, 2599 metrics_format_label("reason", HS_METRICS_ERR_INTRO_REQ_INTRODUCE2)); 2600 tt_assert(entry); 2601 tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 2); 2602 2603 done: 2604 /* Start cleaning up X */ 2605 replaycache_free(x_service.state.replay_cache_rend_cookie); 2606 smartlist_free(x_service.config.ob_master_pubkeys); 2607 tor_free(x_service.state.ob_subcreds); 2608 service_descriptor_free(x_service.desc_current); 2609 service_descriptor_free(x_service.desc_next); 2610 hs_metrics_service_free(&x_service); 2611 service_intro_point_free(x_ip); 2612 2613 /* Clean up Alice */ 2614 hs_desc_intro_point_free(alice_ip); 2615 tor_free(rend_circ.hs_ident); 2616 2617 if (fake_node) { 2618 tor_free(fake_node->ri->onion_curve25519_pkey); 2619 tor_free(fake_node->ri); 2620 tor_free(fake_node); 2621 } 2622 2623 UNMOCK(build_state_get_exit_node); 2624 UNMOCK(relay_send_command_from_edge_); 2625 UNMOCK(node_get_link_specifier_smartlist); 2626 UNMOCK(launch_rendezvous_point_circuit); 2627 } 2628 2629 static void 2630 test_cannot_upload_descriptors(void *arg) 2631 { 2632 int ret; 2633 time_t now; 2634 hs_service_t *service; 2635 2636 (void) arg; 2637 2638 hs_init(); 2639 MOCK(get_or_state, 2640 get_or_state_replacement); 2641 MOCK(networkstatus_get_reasonably_live_consensus, 2642 mock_networkstatus_get_reasonably_live_consensus); 2643 2644 dummy_state = or_state_new(); 2645 2646 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC", 2647 &mock_ns.valid_after); 2648 tt_int_op(ret, OP_EQ, 0); 2649 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC", 2650 &mock_ns.fresh_until); 2651 tt_int_op(ret, OP_EQ, 0); 2652 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after); 2653 2654 update_approx_time(mock_ns.valid_after + 1); 2655 now = mock_ns.valid_after + 1; 2656 2657 /* Create a service with no descriptor. It's added to the global map. */ 2658 service = hs_service_new(get_options()); 2659 tt_assert(service); 2660 service->config.version = HS_VERSION_THREE; 2661 ed25519_secret_key_generate(&service->keys.identity_sk, 0); 2662 ed25519_public_key_generate(&service->keys.identity_pk, 2663 &service->keys.identity_sk); 2664 /* Register service to global map. */ 2665 ret = register_service(get_hs_service_map(), service); 2666 tt_int_op(ret, OP_EQ, 0); 2667 /* But first, build our descriptor. */ 2668 build_all_descriptors(now); 2669 2670 /* 1. Testing missing intro points reason. */ 2671 { 2672 digest256map_t *cur = service->desc_current->intro_points.map; 2673 digest256map_t *tmp = digest256map_new(); 2674 service->desc_current->intro_points.map = tmp; 2675 service->desc_current->missing_intro_points = 1; 2676 setup_full_capture_of_logs(LOG_INFO); 2677 run_upload_descriptor_event(now); 2678 digest256map_free(tmp, tor_free_); 2679 service->desc_current->intro_points.map = cur; 2680 expect_log_msg_containing( 2681 "Service [scrubbed] can't upload its current descriptor: " 2682 "Missing intro points"); 2683 teardown_capture_of_logs(); 2684 /* Reset. */ 2685 service->desc_current->missing_intro_points = 0; 2686 } 2687 2688 /* 2. Testing non established intro points. */ 2689 { 2690 setup_full_capture_of_logs(LOG_INFO); 2691 run_upload_descriptor_event(now); 2692 expect_log_msg_containing( 2693 "Service [scrubbed] can't upload its current descriptor: " 2694 "Intro circuits aren't yet all established (0/3)."); 2695 teardown_capture_of_logs(); 2696 } 2697 2698 /* We need to pass the established circuit tests and thus from now on, we 2699 * MOCK this to return 3 intro points. */ 2700 MOCK(count_desc_circuit_established, mock_count_desc_circuit_established); 2701 num_intro_points = 3; 2702 2703 /* 3. Testing non established intro points. */ 2704 { 2705 service->desc_current->next_upload_time = now + 1000; 2706 setup_full_capture_of_logs(LOG_INFO); 2707 run_upload_descriptor_event(now); 2708 expect_log_msg_containing( 2709 "Service [scrubbed] can't upload its current descriptor: " 2710 "Next upload time is"); 2711 teardown_capture_of_logs(); 2712 /* Reset. */ 2713 service->desc_current->next_upload_time = 0; 2714 } 2715 2716 /* 4. Testing missing live consensus. */ 2717 { 2718 MOCK(networkstatus_get_reasonably_live_consensus, 2719 mock_networkstatus_get_reasonably_live_consensus_null); 2720 setup_full_capture_of_logs(LOG_INFO); 2721 run_upload_descriptor_event(now); 2722 expect_log_msg_containing( 2723 "Service [scrubbed] can't upload its current descriptor: " 2724 "No reasonably live consensus"); 2725 teardown_capture_of_logs(); 2726 /* Reset. */ 2727 MOCK(networkstatus_get_reasonably_live_consensus, 2728 mock_networkstatus_get_reasonably_live_consensus); 2729 } 2730 2731 /* 5. Test missing minimum directory information. */ 2732 { 2733 MOCK(router_have_minimum_dir_info, 2734 mock_router_have_minimum_dir_info_false); 2735 setup_full_capture_of_logs(LOG_INFO); 2736 run_upload_descriptor_event(now); 2737 expect_log_msg_containing( 2738 "Service [scrubbed] can't upload its current descriptor: " 2739 "Not enough directory information"); 2740 teardown_capture_of_logs(); 2741 2742 /* Running it again shouldn't trigger anything due to rate limitation. */ 2743 setup_full_capture_of_logs(LOG_INFO); 2744 run_upload_descriptor_event(now); 2745 expect_no_log_entry(); 2746 teardown_capture_of_logs(); 2747 UNMOCK(router_have_minimum_dir_info); 2748 } 2749 2750 /* Increase time and redo test (5) in order to test the rate limiting. */ 2751 update_approx_time(mock_ns.valid_after + 61); 2752 { 2753 MOCK(router_have_minimum_dir_info, 2754 mock_router_have_minimum_dir_info_false); 2755 setup_full_capture_of_logs(LOG_INFO); 2756 run_upload_descriptor_event(now); 2757 expect_log_msg_containing( 2758 "Service [scrubbed] can't upload its current descriptor: " 2759 "Not enough directory information"); 2760 teardown_capture_of_logs(); 2761 UNMOCK(router_have_minimum_dir_info); 2762 } 2763 2764 done: 2765 hs_free_all(); 2766 UNMOCK(count_desc_circuit_established); 2767 UNMOCK(networkstatus_get_reasonably_live_consensus); 2768 UNMOCK(get_or_state); 2769 } 2770 2771 struct testcase_t hs_service_tests[] = { 2772 { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK, 2773 NULL, NULL }, 2774 { "load_keys", test_load_keys, TT_FORK, 2775 NULL, NULL }, 2776 { "client_filename_is_valid", test_client_filename_is_valid, TT_FORK, 2777 NULL, NULL }, 2778 { "parse_authorized_client", test_parse_authorized_client, TT_FORK, 2779 NULL, NULL }, 2780 { "load_keys_with_client_auth", test_load_keys_with_client_auth, TT_FORK, 2781 NULL, NULL }, 2782 { "access_service", test_access_service, TT_FORK, 2783 NULL, NULL }, 2784 { "service_intro_point", test_service_intro_point, TT_FORK, 2785 NULL, NULL }, 2786 { "helper_functions", test_helper_functions, TT_FORK, 2787 NULL, NULL }, 2788 { "intro_circuit_opened", test_intro_circuit_opened, TT_FORK, 2789 NULL, NULL }, 2790 { "intro_established", test_intro_established, TT_FORK, 2791 NULL, NULL }, 2792 { "closing_intro_circs", test_closing_intro_circs, TT_FORK, 2793 NULL, NULL }, 2794 { "rdv_circuit_opened", test_rdv_circuit_opened, TT_FORK, 2795 NULL, NULL }, 2796 { "bad_introduce2", test_bad_introduce2, TT_FORK, 2797 NULL, NULL }, 2798 { "service_event", test_service_event, TT_FORK, 2799 NULL, NULL }, 2800 { "rotate_descriptors", test_rotate_descriptors, TT_FORK, 2801 NULL, NULL }, 2802 { "build_update_descriptors", test_build_update_descriptors, TT_FORK, 2803 NULL, NULL }, 2804 { "build_descriptors", test_build_descriptors, TT_FORK, 2805 NULL, NULL }, 2806 { "upload_descriptors", test_upload_descriptors, TT_FORK, 2807 NULL, NULL }, 2808 { "cannot_upload_descriptors", test_cannot_upload_descriptors, TT_FORK, 2809 NULL, NULL }, 2810 { "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK, 2811 NULL, NULL }, 2812 { "authorized_client_config_equal", test_authorized_client_config_equal, 2813 TT_FORK, NULL, NULL }, 2814 { "export_client_circuit_id", test_export_client_circuit_id, TT_FORK, 2815 NULL, NULL }, 2816 { "intro2_handling", test_intro2_handling, TT_FORK, NULL, NULL }, 2817 2818 END_OF_TESTCASES 2819 };