Merge branch 'maint-0.4.5' into release-0.4.5
[tor.git] / src / test / test_hs_service.c
blob66e8e2f473ceef0723b4b8575756e90202084297
1 /* Copyright (c) 2016-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file test_hs_service.c
6 * \brief Test hidden service functionality.
7 */
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
26 #include "test/test.h"
27 #include "test/test_helpers.h"
28 #include "test/log_test_helpers.h"
29 #include "test/rend_test_helpers.h"
30 #include "test/hs_test_helpers.h"
32 #include "core/or/or.h"
33 #include "app/config/config.h"
34 #include "app/config/statefile.h"
35 #include "core/crypto/hs_ntor.h"
36 #include "core/mainloop/connection.h"
37 #include "core/mainloop/mainloop.h"
38 #include "core/or/circuitbuild.h"
39 #include "core/or/circuitlist.h"
40 #include "core/or/circuituse.h"
41 #include "core/or/connection_edge.h"
42 #include "core/or/edge_connection_st.h"
43 #include "core/or/relay.h"
44 #include "core/or/versions.h"
45 #include "feature/dirauth/dirvote.h"
46 #include "feature/dirauth/shared_random_state.h"
47 #include "feature/dirauth/voting_schedule.h"
48 #include "feature/hs/hs_circuit.h"
49 #include "feature/hs/hs_circuitmap.h"
50 #include "feature/hs/hs_client.h"
51 #include "feature/hs/hs_common.h"
52 #include "feature/hs/hs_config.h"
53 #include "feature/hs/hs_ident.h"
54 #include "feature/hs/hs_ob.h"
55 #include "feature/hs/hs_cell.h"
56 #include "feature/hs/hs_intropoint.h"
57 #include "feature/hs/hs_metrics.h"
58 #include "feature/hs/hs_service.h"
59 #include "feature/nodelist/networkstatus.h"
60 #include "feature/nodelist/nodelist.h"
61 #include "feature/rend/rendservice.h"
62 #include "lib/crypt_ops/crypto_rand.h"
63 #include "lib/fs/dir.h"
65 #include "core/or/cpath_build_state_st.h"
66 #include "core/or/crypt_path_st.h"
67 #include "core/or/crypt_path.h"
68 #include "feature/nodelist/networkstatus_st.h"
69 #include "feature/nodelist/node_st.h"
70 #include "core/or/origin_circuit_st.h"
71 #include "app/config/or_state_st.h"
72 #include "feature/nodelist/routerinfo_st.h"
74 /* Trunnel */
75 #include "trunnel/hs/cell_establish_intro.h"
77 #ifdef HAVE_SYS_STAT_H
78 #include <sys/stat.h>
79 #endif
80 #ifdef HAVE_UNISTD_H
81 #include <unistd.h>
82 #endif
84 static networkstatus_t mock_ns;
86 static networkstatus_t *
87 mock_networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
89 (void) now;
90 (void) flavor;
91 return &mock_ns;
94 static networkstatus_t *
95 mock_networkstatus_get_reasonably_live_consensus_null(time_t now, int flavor)
97 (void) now;
98 (void) flavor;
99 return NULL;
102 static or_state_t *dummy_state = NULL;
104 /* Mock function to get fake or state (used for rev counters) */
105 static or_state_t *
106 get_or_state_replacement(void)
108 return dummy_state;
111 /* Mock function because we are not trying to test the close circuit that does
112 * an awful lot of checks on the circuit object. */
113 static void
114 mock_circuit_mark_for_close(circuit_t *circ, int reason, int line,
115 const char *file)
117 (void) circ;
118 (void) reason;
119 (void) line;
120 (void) file;
121 return;
124 static size_t relay_payload_len;
125 static char relay_payload[RELAY_PAYLOAD_SIZE];
127 static int
128 mock_relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
129 uint8_t relay_command, const char *payload,
130 size_t payload_len,
131 crypt_path_t *cpath_layer,
132 const char *filename, int lineno)
134 (void) stream_id;
135 (void) circ;
136 (void) relay_command;
137 (void) payload;
138 (void) payload_len;
139 (void) cpath_layer;
140 (void) filename;
141 (void) lineno;
143 memcpy(relay_payload, payload, payload_len);
144 relay_payload_len = payload_len;
146 return 0;
149 static unsigned int num_intro_points = 0;
150 static unsigned int
151 mock_count_desc_circuit_established(const hs_service_descriptor_t *desc)
153 (void) desc;
154 return num_intro_points;
157 static int
158 mock_router_have_minimum_dir_info_false(void)
160 return 0;
163 /* Helper: from a set of options in conf, configure a service which will add
164 * it to the staging list of the HS subsystem. */
165 static int
166 helper_config_service(const char *conf)
168 int ret = 0;
169 or_options_t *options = NULL;
170 tt_assert(conf);
171 options = helper_parse_options(conf);
172 tt_assert(options);
173 ret = hs_config_service_all(options, 0);
174 done:
175 or_options_free(options);
176 return ret;
179 /* Test: Ensure that setting up rendezvous circuits works correctly. */
180 static void
181 test_e2e_rend_circuit_setup(void *arg)
183 ed25519_public_key_t service_pk;
184 origin_circuit_t *or_circ;
185 int retval;
187 /** In this test we create a v3 prop224 service-side rendezvous circuit.
188 * We simulate an HS ntor key exchange with a client, and check that
189 * the circuit was setup correctly and is ready to accept rendezvous data */
191 (void) arg;
193 /* Now make dummy circuit */
195 or_circ = origin_circuit_new();
197 or_circ->base_.purpose = CIRCUIT_PURPOSE_S_CONNECT_REND;
199 or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
200 or_circ->build_state->is_internal = 1;
202 /* prop224: Setup hs conn identifier on the stream */
203 ed25519_secret_key_t sk;
204 tt_int_op(0, OP_EQ, ed25519_secret_key_generate(&sk, 0));
205 tt_int_op(0, OP_EQ, ed25519_public_key_generate(&service_pk, &sk));
207 or_circ->hs_ident = hs_ident_circuit_new(&service_pk);
209 TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN;
212 /* Check number of hops */
213 retval = cpath_get_n_hops(&or_circ->cpath);
214 tt_int_op(retval, OP_EQ, 0);
216 /* Setup the circuit: do the ntor key exchange */
218 uint8_t ntor_key_seed[DIGEST256_LEN] = {2};
219 retval = hs_circuit_setup_e2e_rend_circ(or_circ, ntor_key_seed,
220 sizeof(ntor_key_seed), 1);
221 tt_int_op(retval, OP_EQ, 0);
224 /* See that a hop was added to the circuit's cpath */
225 retval = cpath_get_n_hops(&or_circ->cpath);
226 tt_int_op(retval, OP_EQ, 1);
228 /* Check the digest algo */
229 tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
230 OP_EQ, DIGEST_SHA3_256);
231 tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
232 OP_EQ, DIGEST_SHA3_256);
233 tt_assert(or_circ->cpath->pvt_crypto.f_crypto);
234 tt_assert(or_circ->cpath->pvt_crypto.b_crypto);
236 /* Ensure that circ purpose was changed */
237 tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED);
239 done:
240 circuit_free_(TO_CIRCUIT(or_circ));
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)
249 origin_circuit_t *circ = NULL;
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));
264 return circ;
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)
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));
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);
281 done:
282 return client;
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)
290 hs_service_authorized_client_t *client_out;
292 tor_assert(client);
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);
298 return client_out;
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)
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);
321 done:
322 return service;
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)
331 if (!service)
332 return;
334 remove_service(get_hs_service_map(), service);
336 hs_service_free(service);
339 /* Helper: Return a newly allocated service object with clients. */
340 static hs_service_t *
341 helper_create_service_with_clients(int num_clients)
343 int i;
344 hs_service_t *service = helper_create_service();
345 tt_assert(service);
346 service->config.is_client_auth_enabled = 1;
347 service->config.clients = smartlist_new();
349 for (i = 0; i < num_clients; i++) {
350 hs_service_authorized_client_t *client;
351 client = helper_create_authorized_client();
352 smartlist_add(service->config.clients, client);
355 done:
356 return service;
359 /* Helper: Return a newly allocated service intro point with two link
360 * specifiers, one IPv4 and one legacy ID set to As. */
361 static hs_service_intro_point_t *
362 helper_create_service_ip(void)
364 link_specifier_t *ls;
365 hs_service_intro_point_t *ip = service_intro_point_new(NULL);
366 tor_assert(ip);
367 /* Add a first unused link specifier. */
368 ls = link_specifier_new();
369 link_specifier_set_ls_type(ls, LS_IPV4);
370 smartlist_add(ip->base.link_specifiers, ls);
371 /* Add a second link specifier used by a test. */
372 ls = link_specifier_new();
373 link_specifier_set_ls_type(ls, LS_LEGACY_ID);
374 memset(link_specifier_getarray_un_legacy_id(ls), 'A',
375 link_specifier_getlen_un_legacy_id(ls));
376 smartlist_add(ip->base.link_specifiers, ls);
378 return ip;
381 static void
382 test_load_keys(void *arg)
384 int ret;
385 char *conf = NULL;
386 char *hsdir_v2 = tor_strdup(get_fname("hs2"));
387 char *hsdir_v3 = tor_strdup(get_fname("hs3"));
388 char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
390 (void) arg;
392 /* We'll register two services, a v2 and a v3, then we'll load keys and
393 * validate that both are in a correct state. */
395 hs_init();
397 #define conf_fmt \
398 "HiddenServiceDir %s\n" \
399 "HiddenServiceVersion %d\n" \
400 "HiddenServicePort 65535\n"
402 /* v2 service. */
403 tor_asprintf(&conf, conf_fmt, hsdir_v2, HS_VERSION_TWO);
404 ret = helper_config_service(conf);
405 tor_free(conf);
406 tt_int_op(ret, OP_EQ, 0);
407 /* This one should now be registered into the v2 list. */
408 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 0);
409 tt_int_op(rend_num_services(), OP_EQ, 1);
411 /* v3 service. */
412 tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
413 ret = helper_config_service(conf);
414 tor_free(conf);
415 tt_int_op(ret, OP_EQ, 0);
416 /* It's in staging? */
417 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
419 #undef conf_fmt
421 /* Load the keys for these. After that, the v3 service should be registered
422 * in the global map. */
423 hs_service_load_all_keys();
424 tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
425 hs_service_t *s = get_first_service();
426 tt_assert(s);
428 /* Ok we have the service object. Validate few things. */
429 tt_assert(!fast_mem_is_zero(s->onion_address, sizeof(s->onion_address)));
430 tt_int_op(hs_address_is_valid(s->onion_address), OP_EQ, 1);
431 tt_assert(!fast_mem_is_zero((char *) s->keys.identity_sk.seckey,
432 ED25519_SECKEY_LEN));
433 tt_assert(!fast_mem_is_zero((char *) s->keys.identity_pk.pubkey,
434 ED25519_PUBKEY_LEN));
435 /* Check onion address from identity key. */
436 hs_build_address(&s->keys.identity_pk, s->config.version, addr);
437 tt_int_op(hs_address_is_valid(addr), OP_EQ, 1);
438 tt_str_op(addr, OP_EQ, s->onion_address);
440 /* Check that the is_client_auth_enabled is not set. */
441 tt_assert(!s->config.is_client_auth_enabled);
443 done:
444 tor_free(hsdir_v2);
445 tor_free(hsdir_v3);
446 hs_free_all();
449 static void
450 test_client_filename_is_valid(void *arg)
452 (void) arg;
454 /* Valid file name. */
455 tt_assert(client_filename_is_valid("a.auth"));
456 /* Valid file name with special character. */
457 tt_assert(client_filename_is_valid("a-.auth"));
458 /* Invalid extension. */
459 tt_assert(!client_filename_is_valid("a.ath"));
460 /* Nothing before the extension. */
461 tt_assert(!client_filename_is_valid(".auth"));
463 done:
467 static void
468 test_parse_authorized_client(void *arg)
470 hs_service_authorized_client_t *client = NULL;
472 (void) arg;
474 /* Valid authorized client. */
475 client = parse_authorized_client(
476 "descriptor:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
477 tt_assert(client);
479 /* Wrong number of fields. */
480 tt_assert(!parse_authorized_client("a:b:c:d:e"));
481 /* Wrong auth type. */
482 tt_assert(!parse_authorized_client(
483 "x:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
484 /* Wrong key type. */
485 tt_assert(!parse_authorized_client(
486 "descriptor:x:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
487 /* Some malformed string. */
488 tt_assert(!parse_authorized_client("descriptor:x25519:aa=="));
489 tt_assert(!parse_authorized_client("descriptor:"));
490 tt_assert(!parse_authorized_client("descriptor:x25519"));
491 tt_assert(!parse_authorized_client("descriptor:x25519:"));
492 tt_assert(!parse_authorized_client(""));
494 done:
495 service_authorized_client_free(client);
498 static char *
499 mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out)
501 char *ret = NULL;
503 (void) flags;
504 (void) stat_out;
506 if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
507 "authorized_clients" PATH_SEPARATOR
508 "client1.auth"))) {
509 ret = tor_strdup("descriptor:x25519:"
510 "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
511 goto done;
514 if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
515 "authorized_clients" PATH_SEPARATOR
516 "dummy.xxx"))) {
517 ret = tor_strdup("descriptor:x25519:"
518 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
519 goto done;
522 if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
523 "authorized_clients" PATH_SEPARATOR
524 "client2.auth"))) {
525 ret = tor_strdup("descriptor:x25519:"
526 "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta");
527 goto done;
530 done:
531 return ret;
534 static smartlist_t *
535 mock_tor_listdir(const char *dirname)
537 smartlist_t *file_list = smartlist_new();
539 (void) dirname;
541 smartlist_add(file_list, tor_strdup("client1.auth"));
542 smartlist_add(file_list, tor_strdup("dummy.xxx"));
543 smartlist_add(file_list, tor_strdup("client2.auth"));
545 return file_list;
548 static void
549 test_load_keys_with_client_auth(void *arg)
551 int ret;
552 char *conf = NULL;
553 smartlist_t *pubkey_b32_list = smartlist_new();
554 char *hsdir_v3 = tor_strdup(get_fname("hs3"));
555 hs_service_t *service;
557 (void) arg;
559 hs_init();
560 smartlist_add(pubkey_b32_list, tor_strdup(
561 "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
562 smartlist_add(pubkey_b32_list, tor_strdup(
563 "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta"));
565 #define conf_fmt \
566 "HiddenServiceDir %s\n" \
567 "HiddenServiceVersion %d\n" \
568 "HiddenServicePort 65534\n"
570 tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
571 ret = helper_config_service(conf);
572 tor_free(conf);
573 tt_int_op(ret, OP_EQ, 0);
574 /* It's in staging? */
575 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
577 #undef conf_fmt
579 MOCK(read_file_to_str, mock_read_file_to_str);
580 MOCK(tor_listdir, mock_tor_listdir);
582 /* Load the keys for these. After that, the v3 service should be registered
583 * in the global map. */
584 hs_service_load_all_keys();
585 tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
587 service = get_first_service();
588 tt_assert(service);
589 tt_assert(service->config.clients);
590 tt_int_op(smartlist_len(service->config.clients), OP_EQ,
591 smartlist_len(pubkey_b32_list));
593 /* Test that the is_client_auth_enabled flag is set. */
594 tt_assert(service->config.is_client_auth_enabled);
596 /* Test that the keys in clients are correct. */
597 SMARTLIST_FOREACH_BEGIN(pubkey_b32_list, char *, pubkey_b32) {
599 curve25519_public_key_t pubkey;
600 /* This flag will be set if the key is found in clients. */
601 int is_found = 0;
602 base32_decode((char *) pubkey.public_key, sizeof(pubkey.public_key),
603 pubkey_b32, strlen(pubkey_b32));
605 SMARTLIST_FOREACH_BEGIN(service->config.clients,
606 hs_service_authorized_client_t *, client) {
607 if (tor_memeq(&pubkey, &client->client_pk, sizeof(pubkey))) {
608 is_found = 1;
609 break;
611 } SMARTLIST_FOREACH_END(client);
613 tt_assert(is_found);
615 } SMARTLIST_FOREACH_END(pubkey_b32);
617 done:
618 SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s));
619 smartlist_free(pubkey_b32_list);
620 tor_free(hsdir_v3);
621 hs_free_all();
622 UNMOCK(read_file_to_str);
623 UNMOCK(tor_listdir);
626 static void
627 test_access_service(void *arg)
629 int ret;
630 char *conf = NULL;
631 char *hsdir_v3 = tor_strdup(get_fname("hs3"));
632 hs_service_ht *global_map;
633 hs_service_t *s = NULL;
635 (void) arg;
637 /* We'll register two services, a v2 and a v3, then we'll load keys and
638 * validate that both are in a correct state. */
640 hs_init();
642 #define conf_fmt \
643 "HiddenServiceDir %s\n" \
644 "HiddenServiceVersion %d\n" \
645 "HiddenServicePort 65535\n"
647 /* v3 service. */
648 tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
649 ret = helper_config_service(conf);
650 tor_free(conf);
651 tt_int_op(ret, OP_EQ, 0);
652 /* It's in staging? */
653 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
655 /* Load the keys for these. After that, the v3 service should be registered
656 * in the global map. */
657 hs_service_load_all_keys();
658 tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
659 s = get_first_service();
660 tt_assert(s);
661 global_map = get_hs_service_map();
662 tt_assert(global_map);
664 /* From here, we'll try the service accessors. */
665 hs_service_t *query = find_service(global_map, &s->keys.identity_pk);
666 tt_assert(query);
667 tt_mem_op(query, OP_EQ, s, sizeof(hs_service_t));
668 /* Remove service, check if it actually works and then put it back. */
669 remove_service(global_map, s);
670 hs_metrics_service_free(s);
671 tt_int_op(get_hs_service_map_size(), OP_EQ, 0);
672 query = find_service(global_map, &s->keys.identity_pk);
673 tt_ptr_op(query, OP_EQ, NULL);
675 /* Register back the service in the map. */
676 ret = register_service(global_map, s);
677 tt_int_op(ret, OP_EQ, 0);
678 tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
679 /* Twice should fail. */
680 hs_metrics_service_free(s); /* Avoid BUG() on metrics init. */
681 ret = register_service(global_map, s);
682 tt_int_op(ret, OP_EQ, -1);
683 /* Remove service from map so we don't double free on cleanup. */
684 remove_service(global_map, s);
685 tt_int_op(get_hs_service_map_size(), OP_EQ, 0);
686 query = find_service(global_map, &s->keys.identity_pk);
687 tt_ptr_op(query, OP_EQ, NULL);
688 /* Let's try to remove twice for fun. */
689 setup_full_capture_of_logs(LOG_WARN);
690 remove_service(global_map, s);
691 expect_log_msg_containing("Could not find service in the global map");
692 teardown_capture_of_logs();
694 done:
695 hs_service_free(s);
696 tor_free(hsdir_v3);
697 hs_free_all();
700 /** Test that we can create intro point objects, index them and find them */
701 static void
702 test_service_intro_point(void *arg)
704 hs_service_t *service = NULL;
705 hs_service_intro_point_t *ip = NULL;
707 (void) arg;
709 update_approx_time(1481621834);
711 /* Test simple creation of an object. */
713 time_t now = approx_time();
714 ip = helper_create_service_ip();
715 tt_assert(ip);
716 /* Make sure the authentication keypair is not zeroes. */
717 tt_int_op(fast_mem_is_zero((const char *) &ip->auth_key_kp,
718 sizeof(ed25519_keypair_t)), OP_EQ, 0);
719 /* The introduce2_max MUST be in that range. */
720 tt_u64_op(ip->introduce2_max, OP_GE,
721 INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS);
722 tt_u64_op(ip->introduce2_max, OP_LE,
723 INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS);
724 /* Time to expire MUST also be in that range. We subtract 500 seconds
725 * because there could be a gap between setting now and the time taken in
726 * service_intro_point_new. On ARM and other older CPUs, it can be
727 * surprisingly slow... */
728 tt_u64_op(ip->time_to_expire, OP_GE,
729 now + INTRO_POINT_LIFETIME_MIN_SECONDS - 500);
730 /* We add 500 seconds, because this time we're testing against the
731 * maximum allowed time. */
732 tt_u64_op(ip->time_to_expire, OP_LE,
733 now + INTRO_POINT_LIFETIME_MAX_SECONDS + 500);
734 tt_assert(ip->replay_cache);
735 tt_assert(ip->base.link_specifiers);
736 /* By default, this is NOT a legacy object. */
737 tt_int_op(ip->base.is_only_legacy, OP_EQ, 0);
740 /* Test functions that uses a service intropoints map with that previously
741 * created object (non legacy). */
743 ed25519_public_key_t garbage = { {0} };
744 hs_service_intro_point_t *query;
746 service = hs_service_new(get_options());
747 tt_assert(service);
748 service->desc_current = service_descriptor_new();
749 tt_assert(service->desc_current);
750 /* Add intropoint to descriptor map. */
751 service_intro_point_add(service->desc_current->intro_points.map, ip);
752 query = service_intro_point_find(service, &ip->auth_key_kp.pubkey);
753 tt_mem_op(query, OP_EQ, ip, sizeof(hs_service_intro_point_t));
754 query = service_intro_point_find(service, &garbage);
755 tt_ptr_op(query, OP_EQ, NULL);
757 /* While at it, can I find the descriptor with the intro point? */
758 hs_service_descriptor_t *desc_lookup =
759 service_desc_find_by_intro(service, ip);
760 tt_mem_op(service->desc_current, OP_EQ, desc_lookup,
761 sizeof(hs_service_descriptor_t));
763 /* Remove object from service descriptor and make sure it is out. */
764 service_intro_point_remove(service, ip);
765 query = service_intro_point_find(service, &ip->auth_key_kp.pubkey);
766 tt_ptr_op(query, OP_EQ, NULL);
769 done:
770 /* If the test succeed, this object is no longer referenced in the service
771 * so we can free it without use after free. Else, it might explode because
772 * it's still in the service descriptor map. */
773 service_intro_point_free(ip);
774 hs_service_free(service);
777 static node_t mock_node;
778 static const node_t *
779 mock_node_get_by_id(const char *digest)
781 (void) digest;
782 memset(mock_node.identity, 'A', DIGEST_LEN);
783 /* Only return the matching identity of As */
784 if (!tor_memcmp(mock_node.identity, digest, DIGEST_LEN)) {
785 return &mock_node;
787 return NULL;
790 static void
791 test_helper_functions(void *arg)
793 int ret;
794 hs_service_t *service = NULL;
795 hs_service_intro_point_t *ip = NULL;
796 hs_ident_circuit_t ident;
798 (void) arg;
800 MOCK(node_get_by_id, mock_node_get_by_id);
802 hs_service_init();
803 time_t now = time(NULL);
804 update_approx_time(now);
806 service = helper_create_service();
808 ip = helper_create_service_ip();
809 /* Immediately add the intro point to the service so the free service at the
810 * end cleans it as well. */
811 service_intro_point_add(service->desc_current->intro_points.map, ip);
813 /* Setup the circuit identifier. */
814 ed25519_pubkey_copy(&ident.intro_auth_pk, &ip->auth_key_kp.pubkey);
815 ed25519_pubkey_copy(&ident.identity_pk, &service->keys.identity_pk);
817 /* Testing get_objects_from_ident(). */
819 hs_service_t *s_lookup = NULL;
820 hs_service_intro_point_t *ip_lookup = NULL;
821 hs_service_descriptor_t *desc_lookup = NULL;
823 get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup);
824 tt_mem_op(s_lookup, OP_EQ, service, sizeof(hs_service_t));
825 tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t));
826 tt_mem_op(desc_lookup, OP_EQ, service->desc_current,
827 sizeof(hs_service_descriptor_t));
828 /* Reset */
829 s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL;
831 /* NULL parameter should work. */
832 get_objects_from_ident(&ident, NULL, &ip_lookup, &desc_lookup);
833 tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t));
834 tt_mem_op(desc_lookup, OP_EQ, service->desc_current,
835 sizeof(hs_service_descriptor_t));
836 /* Reset. */
837 s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL;
839 /* Break the ident and we should find nothing. */
840 memset(&ident, 0, sizeof(ident));
841 get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup);
842 tt_ptr_op(s_lookup, OP_EQ, NULL);
843 tt_ptr_op(ip_lookup, OP_EQ, NULL);
844 tt_ptr_op(desc_lookup, OP_EQ, NULL);
847 /* Testing get_node_from_intro_point() */
849 const node_t *node = get_node_from_intro_point(ip);
850 tt_ptr_op(node, OP_EQ, &mock_node);
851 SMARTLIST_FOREACH_BEGIN(ip->base.link_specifiers,
852 link_specifier_t *, ls) {
853 if (link_specifier_get_ls_type(ls) == LS_LEGACY_ID) {
854 /* Change legacy id in link specifier which is not the mock node. */
855 memset(link_specifier_getarray_un_legacy_id(ls), 'B',
856 link_specifier_getlen_un_legacy_id(ls));
858 } SMARTLIST_FOREACH_END(ls);
859 node = get_node_from_intro_point(ip);
860 tt_ptr_op(node, OP_EQ, NULL);
863 /* Testing can_service_launch_intro_circuit() */
865 /* Put the start of the retry period back in time, we should be allowed.
866 * to launch intro circuit. */
867 service->state.num_intro_circ_launched = 2;
868 service->state.intro_circ_retry_started_time =
869 (now - INTRO_CIRC_RETRY_PERIOD - 1);
870 ret = can_service_launch_intro_circuit(service, now);
871 tt_int_op(ret, OP_EQ, 1);
872 tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now);
873 tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0);
874 /* Call it again, we should still be allowed because we are under
875 * MAX_INTRO_CIRCS_PER_PERIOD which been set to 0 previously. */
876 ret = can_service_launch_intro_circuit(service, now);
877 tt_int_op(ret, OP_EQ, 1);
878 tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now);
879 tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0);
880 /* Too many intro circuit launched means we are not allowed. */
881 service->state.num_intro_circ_launched = 20;
882 ret = can_service_launch_intro_circuit(service, now);
883 tt_int_op(ret, OP_EQ, 0);
886 /* Testing intro_point_should_expire(). */
888 /* Just some basic test of the current state. */
889 tt_u64_op(ip->introduce2_max, OP_GE,
890 INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS);
891 tt_u64_op(ip->introduce2_max, OP_LE,
892 INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS);
893 tt_u64_op(ip->time_to_expire, OP_GE,
894 now + INTRO_POINT_LIFETIME_MIN_SECONDS);
895 tt_u64_op(ip->time_to_expire, OP_LE,
896 now + INTRO_POINT_LIFETIME_MAX_SECONDS);
898 /* This newly created IP from above shouldn't expire now. */
899 ret = intro_point_should_expire(ip, now);
900 tt_int_op(ret, OP_EQ, 0);
901 /* Maximum number of INTRODUCE2 cell reached, it should expire. */
902 ip->introduce2_count = INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS + 1;
903 ret = intro_point_should_expire(ip, now);
904 tt_int_op(ret, OP_EQ, 1);
905 ip->introduce2_count = 0;
906 /* It should expire if time to expire has been reached. */
907 ip->time_to_expire = now - 1000;
908 ret = intro_point_should_expire(ip, now);
909 tt_int_op(ret, OP_EQ, 1);
912 done:
913 /* This will free the service and all objects associated to it. */
914 if (service) {
915 remove_service(get_hs_service_map(), service);
916 hs_service_free(service);
918 hs_service_free_all();
919 UNMOCK(node_get_by_id);
922 /** Test that we do the right operations when an intro circuit opens */
923 static void
924 test_intro_circuit_opened(void *arg)
926 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
927 hs_service_t *service = NULL;
928 origin_circuit_t *circ = NULL;
930 (void) arg;
932 hs_init();
933 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
934 MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
936 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
937 flags);
939 /* No service associated with this circuit. */
940 setup_full_capture_of_logs(LOG_WARN);
941 hs_service_circuit_has_opened(circ);
942 expect_log_msg_containing("Unknown service identity key");
943 teardown_capture_of_logs();
945 /* Set a service for this circuit. */
947 service = helper_create_service();
948 ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
949 &service->keys.identity_pk);
951 /* No intro point associated with this circuit. */
952 setup_full_capture_of_logs(LOG_WARN);
953 hs_service_circuit_has_opened(circ);
954 expect_log_msg_containing("Unknown introduction point auth key");
955 teardown_capture_of_logs();
958 /* Set an IP object now for this circuit. */
960 hs_service_intro_point_t *ip = helper_create_service_ip();
961 service_intro_point_add(service->desc_current->intro_points.map, ip);
962 /* Update ident to contain the intro point auth key. */
963 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
964 &ip->auth_key_kp.pubkey);
967 /* This one should go all the way. */
968 setup_full_capture_of_logs(LOG_INFO);
969 hs_service_circuit_has_opened(circ);
970 expect_log_msg_containing("Introduction circuit 0 established for service");
971 teardown_capture_of_logs();
973 done:
974 circuit_free_(TO_CIRCUIT(circ));
975 if (service) {
976 remove_service(get_hs_service_map(), service);
977 hs_service_free(service);
979 hs_free_all();
980 UNMOCK(circuit_mark_for_close_);
981 UNMOCK(relay_send_command_from_edge_);
984 /** Test the operations we do on a circuit after we learn that we successfully
985 * established an intro point on it */
986 static void
987 test_intro_established(void *arg)
989 int ret;
990 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
991 uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
992 origin_circuit_t *circ = NULL;
993 hs_service_t *service = NULL;
994 hs_service_intro_point_t *ip = NULL;
996 (void) arg;
998 hs_init();
999 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
1001 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
1002 flags);
1003 tt_assert(circ);
1005 /* Test a wrong purpose. */
1006 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO;
1007 setup_full_capture_of_logs(LOG_WARN);
1008 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
1009 tt_int_op(ret, OP_EQ, -1);
1010 expect_log_msg_containing("Received an INTRO_ESTABLISHED cell on a "
1011 "non introduction circuit of purpose");
1012 teardown_capture_of_logs();
1014 /* Back to normal. */
1015 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
1017 /* No service associated to it. */
1018 setup_full_capture_of_logs(LOG_WARN);
1019 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
1020 tt_int_op(ret, OP_EQ, -1);
1021 expect_log_msg_containing("Unknown service identity key");
1022 teardown_capture_of_logs();
1024 /* Set a service for this circuit. */
1025 service = helper_create_service();
1026 ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
1027 &service->keys.identity_pk);
1028 /* No introduction point associated to it. */
1029 setup_full_capture_of_logs(LOG_WARN);
1030 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
1031 tt_int_op(ret, OP_EQ, -1);
1032 expect_log_msg_containing("Introduction circuit established without an "
1033 "intro point object on circuit");
1034 teardown_capture_of_logs();
1036 /* Set an IP object now for this circuit. */
1038 ip = helper_create_service_ip();
1039 service_intro_point_add(service->desc_current->intro_points.map, ip);
1040 /* Update ident to contain the intro point auth key. */
1041 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
1042 &ip->auth_key_kp.pubkey);
1045 /* Send an empty payload. INTRO_ESTABLISHED cells are basically zeroes. */
1046 ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
1047 tt_int_op(ret, OP_EQ, 0);
1048 tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_INTRO);
1050 done:
1051 if (circ)
1052 circuit_free_(TO_CIRCUIT(circ));
1053 if (service) {
1054 remove_service(get_hs_service_map(), service);
1055 hs_service_free(service);
1057 hs_free_all();
1058 UNMOCK(circuit_mark_for_close_);
1061 /** Check the operations we do on a rendezvous circuit after we learn it's
1062 * open */
1063 static void
1064 test_rdv_circuit_opened(void *arg)
1066 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
1067 origin_circuit_t *circ = NULL;
1068 hs_service_t *service = NULL;
1070 (void) arg;
1072 hs_init();
1073 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
1074 MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
1076 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND, flags);
1077 crypto_rand((char *) circ->hs_ident->rendezvous_cookie, REND_COOKIE_LEN);
1078 crypto_rand((char *) circ->hs_ident->rendezvous_handshake_info,
1079 sizeof(circ->hs_ident->rendezvous_handshake_info));
1081 /* No service associated with this circuit. */
1082 setup_full_capture_of_logs(LOG_WARN);
1083 hs_service_circuit_has_opened(circ);
1084 expect_log_msg_containing("Unknown service identity key");
1085 teardown_capture_of_logs();
1086 /* This should be set to a non zero timestamp. */
1087 tt_u64_op(TO_CIRCUIT(circ)->timestamp_dirty, OP_NE, 0);
1089 /* Set a service for this circuit. */
1090 service = helper_create_service();
1091 ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
1092 &service->keys.identity_pk);
1093 /* Should be all good. */
1094 hs_service_circuit_has_opened(circ);
1095 tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED);
1097 done:
1098 circuit_free_(TO_CIRCUIT(circ));
1099 if (service) {
1100 remove_service(get_hs_service_map(), service);
1101 hs_service_free(service);
1103 hs_free_all();
1104 UNMOCK(circuit_mark_for_close_);
1105 UNMOCK(relay_send_command_from_edge_);
1108 static void
1109 mock_assert_circuit_ok(const circuit_t *c)
1111 (void) c;
1112 return;
1115 /** Test for the general mechanism for closing intro circs.
1116 * Also a way to identify that #23603 has been fixed. */
1117 static void
1118 test_closing_intro_circs(void *arg)
1120 hs_service_t *service = NULL;
1121 hs_service_intro_point_t *ip = NULL, *entry = NULL;
1122 origin_circuit_t *intro_circ = NULL, *tmp_circ;
1123 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
1125 (void) arg;
1127 MOCK(assert_circuit_ok, mock_assert_circuit_ok);
1129 hs_init();
1131 /* Initialize service */
1132 service = helper_create_service();
1133 /* Initialize intro point */
1134 ip = helper_create_service_ip();
1135 tt_assert(ip);
1136 service_intro_point_add(service->desc_current->intro_points.map, ip);
1138 /* Initialize intro circuit */
1139 intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags);
1140 intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk);
1141 /* Register circuit in the circuitmap . */
1142 hs_circuitmap_register_intro_circ_v3_service_side(intro_circ,
1143 &ip->auth_key_kp.pubkey);
1144 tmp_circ =
1145 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
1146 tt_ptr_op(tmp_circ, OP_EQ, intro_circ);
1148 /* Pretend that intro point has failed too much */
1149 ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES+1;
1151 /* Now pretend we are freeing this intro circuit. We want to see that our
1152 * destructor is not gonna kill our intro point structure since that's the
1153 * job of the cleanup routine. */
1154 circuit_free_(TO_CIRCUIT(intro_circ));
1155 intro_circ = NULL;
1156 entry = service_intro_point_find(service, &ip->auth_key_kp.pubkey);
1157 tt_assert(entry);
1158 /* The free should also remove the circuit from the circuitmap. */
1159 tmp_circ =
1160 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
1161 tt_assert(!tmp_circ);
1163 /* Now pretend that a new intro point circ was launched and opened. Check
1164 * that the intro point will be established correctly. */
1165 intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags);
1166 intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk);
1167 ed25519_pubkey_copy(&intro_circ->hs_ident->intro_auth_pk,
1168 &ip->auth_key_kp.pubkey);
1169 /* Register circuit in the circuitmap . */
1170 hs_circuitmap_register_intro_circ_v3_service_side(intro_circ,
1171 &ip->auth_key_kp.pubkey);
1172 tmp_circ =
1173 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
1174 tt_ptr_op(tmp_circ, OP_EQ, intro_circ);
1175 tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_EQ, 0);
1176 circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_INTERNAL);
1177 tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_NE, 0);
1178 /* At this point, we should not be able to find it in the circuitmap. */
1179 tmp_circ =
1180 hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
1181 tt_assert(!tmp_circ);
1183 done:
1184 if (intro_circ) {
1185 circuit_free_(TO_CIRCUIT(intro_circ));
1187 /* Frees the service object. */
1188 if (service) {
1189 remove_service(get_hs_service_map(), service);
1190 hs_service_free(service);
1192 hs_free_all();
1193 UNMOCK(assert_circuit_ok);
1196 /** Test sending and receiving introduce2 cells */
1197 static void
1198 test_bad_introduce2(void *arg)
1200 int ret;
1201 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
1202 uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
1203 origin_circuit_t *circ = NULL;
1204 hs_service_t *service = NULL;
1205 hs_service_intro_point_t *ip = NULL;
1207 (void) arg;
1209 hs_init();
1210 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
1211 MOCK(get_or_state,
1212 get_or_state_replacement);
1214 dummy_state = or_state_new();
1216 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags);
1217 tt_assert(circ);
1219 /* Test a wrong purpose. */
1220 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
1221 setup_full_capture_of_logs(LOG_WARN);
1222 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
1223 tt_int_op(ret, OP_EQ, -1);
1224 expect_log_msg_containing("Received an INTRODUCE2 cell on a "
1225 "non introduction circuit of purpose");
1226 teardown_capture_of_logs();
1228 /* Back to normal. */
1229 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO;
1231 /* No service associated to it. */
1232 setup_full_capture_of_logs(LOG_WARN);
1233 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
1234 tt_int_op(ret, OP_EQ, -1);
1235 expect_log_msg_containing("Unknown service identity key");
1236 teardown_capture_of_logs();
1238 /* Set a service for this circuit. */
1239 service = helper_create_service();
1240 ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
1241 &service->keys.identity_pk);
1242 /* No introduction point associated to it. */
1243 setup_full_capture_of_logs(LOG_WARN);
1244 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
1245 tt_int_op(ret, OP_EQ, -1);
1246 expect_log_msg_containing("Unknown introduction auth key when handling "
1247 "an INTRODUCE2 cell on circuit");
1248 teardown_capture_of_logs();
1250 /* Set an IP object now for this circuit. */
1252 ip = helper_create_service_ip();
1253 service_intro_point_add(service->desc_current->intro_points.map, ip);
1254 /* Update ident to contain the intro point auth key. */
1255 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
1256 &ip->auth_key_kp.pubkey);
1259 /* This will fail because receiving an INTRODUCE2 cell implies a valid cell
1260 * and then launching circuits so let's not do that and instead test that
1261 * behaviour differently. */
1262 ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
1263 tt_int_op(ret, OP_EQ, -1);
1264 tt_u64_op(ip->introduce2_count, OP_EQ, 0);
1266 done:
1267 or_state_free(dummy_state);
1268 dummy_state = NULL;
1269 if (circ)
1270 circuit_free_(TO_CIRCUIT(circ));
1271 if (service) {
1272 remove_service(get_hs_service_map(), service);
1273 hs_service_free(service);
1275 hs_free_all();
1276 UNMOCK(circuit_mark_for_close_);
1279 /** Test basic hidden service housekeeping operations (maintaining intro
1280 * points, etc) */
1281 static void
1282 test_service_event(void *arg)
1284 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
1285 time_t now = time(NULL);
1286 hs_service_t *service;
1287 origin_circuit_t *circ = NULL;
1289 (void) arg;
1291 hs_init();
1292 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
1294 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags);
1296 /* Set a service for this circuit. */
1297 service = helper_create_service();
1298 tt_assert(service);
1299 ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
1300 &service->keys.identity_pk);
1302 /* Currently this consists of cleaning invalid intro points. So adding IPs
1303 * here that should get cleaned up. */
1305 hs_service_intro_point_t *ip = helper_create_service_ip();
1306 service_intro_point_add(service->desc_current->intro_points.map, ip);
1307 /* This run will remove the IP because we have no circuits nor node_t
1308 * associated with it. */
1309 run_housekeeping_event(now);
1310 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1311 OP_EQ, 0);
1312 /* We'll trigger a removal because we've reached our maximum amount of
1313 * times we should retry a circuit. For this, we need to have a node_t
1314 * that matches the identity of this IP. */
1315 routerinfo_t ri;
1316 memset(&ri, 0, sizeof(ri));
1317 ip = helper_create_service_ip();
1318 service_intro_point_add(service->desc_current->intro_points.map, ip);
1319 memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN);
1320 /* This triggers a node_t creation. */
1321 tt_assert(nodelist_set_routerinfo(&ri, NULL));
1322 ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
1323 run_housekeeping_event(now);
1324 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1325 OP_EQ, 0);
1326 /* No removal but no circuit so this means the IP object will stay in the
1327 * descriptor map so we can retry it. */
1328 ip = helper_create_service_ip();
1329 service_intro_point_add(service->desc_current->intro_points.map, ip);
1330 run_housekeeping_event(now);
1331 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1332 OP_EQ, 1);
1333 /* Remove the IP object at once for the next test. */
1334 ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
1335 run_housekeeping_event(now);
1336 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1337 OP_EQ, 0);
1338 /* Now, we'll create an IP with a registered circuit. The IP object
1339 * shouldn't go away. */
1340 ip = helper_create_service_ip();
1341 service_intro_point_add(service->desc_current->intro_points.map, ip);
1342 ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
1343 &ip->auth_key_kp.pubkey);
1344 hs_circuitmap_register_intro_circ_v3_service_side(
1345 circ, &ip->auth_key_kp.pubkey);
1346 run_housekeeping_event(now);
1347 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1348 OP_EQ, 1);
1349 /* We'll mangle the IP object to expire. */
1350 ip->time_to_expire = now;
1351 run_housekeeping_event(now);
1352 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1353 OP_EQ, 0);
1356 done:
1357 hs_circuitmap_remove_circuit(TO_CIRCUIT(circ));
1358 circuit_free_(TO_CIRCUIT(circ));
1359 if (service) {
1360 remove_service(get_hs_service_map(), service);
1361 hs_service_free(service);
1363 hs_free_all();
1364 UNMOCK(circuit_mark_for_close_);
1367 /** Test that we rotate descriptors correctly. */
1368 static void
1369 test_rotate_descriptors(void *arg)
1371 int ret;
1372 time_t next_rotation_time, now;
1373 hs_service_t *service = NULL;
1374 hs_service_descriptor_t *desc_next;
1376 (void) arg;
1378 dummy_state = or_state_new();
1380 hs_init();
1381 MOCK(get_or_state, get_or_state_replacement);
1382 MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
1383 MOCK(networkstatus_get_reasonably_live_consensus,
1384 mock_networkstatus_get_reasonably_live_consensus);
1386 /* Descriptor rotation happens with a consensus with a new SRV. */
1388 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
1389 &mock_ns.valid_after);
1390 tt_int_op(ret, OP_EQ, 0);
1391 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
1392 &mock_ns.fresh_until);
1393 tt_int_op(ret, OP_EQ, 0);
1394 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
1396 update_approx_time(mock_ns.valid_after+1);
1397 now = mock_ns.valid_after+1;
1399 /* Create a service with a default descriptor and state. It's added to the
1400 * global map. */
1401 service = helper_create_service();
1402 service_descriptor_free(service->desc_current);
1403 service->desc_current = NULL;
1404 /* This triggers a build for both descriptors. The time now is only used in
1405 * the descriptor certificate which is important to be now else the decoding
1406 * will complain that the cert has expired if we use valid_after. */
1407 build_all_descriptors(now);
1408 tt_assert(service->desc_current);
1409 tt_assert(service->desc_next);
1411 /* Tweak our service next rotation time so we can use a custom time. */
1412 service->state.next_rotation_time = next_rotation_time =
1413 mock_ns.valid_after + (11 * 60 * 60);
1415 /* Nothing should happen, we are not at a new SRV. Our next rotation time
1416 * should be untouched. */
1417 rotate_all_descriptors(mock_ns.valid_after);
1418 tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
1419 tt_assert(service->desc_current);
1420 tt_assert(service->desc_next);
1421 tt_u64_op(service->desc_current->time_period_num, OP_EQ,
1422 hs_get_previous_time_period_num(0));
1423 tt_u64_op(service->desc_next->time_period_num, OP_EQ,
1424 hs_get_time_period_num(0));
1425 /* Keep a reference so we can compare it after rotation to the current. */
1426 desc_next = service->desc_next;
1428 /* Going right after a new SRV. */
1429 ret = parse_rfc1123_time("Sat, 27 Oct 1985 01:00:00 UTC",
1430 &mock_ns.valid_after);
1431 tt_int_op(ret, OP_EQ, 0);
1432 ret = parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC",
1433 &mock_ns.fresh_until);
1434 tt_int_op(ret, OP_EQ, 0);
1435 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
1437 update_approx_time(mock_ns.valid_after+1);
1438 now = mock_ns.valid_after+1;
1440 /* Note down what to expect for the next rotation time which is 01:00 + 23h
1441 * meaning 00:00:00. */
1442 next_rotation_time = mock_ns.valid_after + (23 * 60 * 60);
1443 /* We should have our next rotation time modified, our current descriptor
1444 * cleaned up and the next descriptor becoming the current. */
1445 rotate_all_descriptors(mock_ns.valid_after);
1446 tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
1447 tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
1448 tt_assert(service->desc_next == NULL);
1450 /* A second time should do nothing. */
1451 rotate_all_descriptors(mock_ns.valid_after);
1452 tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
1453 tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
1454 tt_assert(service->desc_next == NULL);
1456 build_all_descriptors(now);
1457 tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
1458 tt_u64_op(service->desc_current->time_period_num, OP_EQ,
1459 hs_get_time_period_num(0));
1460 tt_u64_op(service->desc_next->time_period_num, OP_EQ,
1461 hs_get_next_time_period_num(0));
1462 tt_assert(service->desc_next);
1464 done:
1465 if (service) {
1466 remove_service(get_hs_service_map(), service);
1467 hs_service_free(service);
1469 hs_free_all();
1470 UNMOCK(get_or_state);
1471 UNMOCK(circuit_mark_for_close_);
1472 UNMOCK(networkstatus_get_reasonably_live_consensus);
1475 /** Test building descriptors: picking intro points, setting up their link
1476 * specifiers, etc. */
1477 static void
1478 test_build_update_descriptors(void *arg)
1480 int ret;
1481 node_t *node;
1482 hs_service_t *service = NULL;
1483 hs_service_intro_point_t *ip_cur, *ip_next;
1484 routerinfo_t ri;
1486 (void) arg;
1488 hs_init();
1490 MOCK(get_or_state,
1491 get_or_state_replacement);
1492 MOCK(networkstatus_get_reasonably_live_consensus,
1493 mock_networkstatus_get_reasonably_live_consensus);
1495 dummy_state = or_state_new();
1497 ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC",
1498 &mock_ns.valid_after);
1499 tt_int_op(ret, OP_EQ, 0);
1500 ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC",
1501 &mock_ns.fresh_until);
1502 tt_int_op(ret, OP_EQ, 0);
1503 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
1505 update_approx_time(mock_ns.valid_after+1);
1507 time_t now = mock_ns.valid_after+1;
1509 /* Create a service without a current descriptor to trigger a build. */
1510 service = helper_create_service();
1511 tt_assert(service);
1512 /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */
1513 service_descriptor_free(service->desc_current);
1514 service->desc_current = NULL;
1516 /* We have a fresh service so this should trigger a build for both
1517 * descriptors for specific time period that we'll test. */
1518 build_all_descriptors(now);
1519 /* Check *current* descriptor. */
1520 tt_assert(service->desc_current);
1521 tt_assert(service->desc_current->desc);
1522 tt_assert(service->desc_current->intro_points.map);
1523 /* The current time period is the one expected when starting at 03:00. */
1524 tt_u64_op(service->desc_current->time_period_num, OP_EQ,
1525 hs_get_time_period_num(0));
1526 /* This should be untouched, the update descriptor process changes it. */
1527 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0);
1529 /* Check *next* descriptor. */
1530 tt_assert(service->desc_next);
1531 tt_assert(service->desc_next->desc);
1532 tt_assert(service->desc_next->intro_points.map);
1533 tt_assert(service->desc_current != service->desc_next);
1534 tt_u64_op(service->desc_next->time_period_num, OP_EQ,
1535 hs_get_next_time_period_num(0));
1536 /* This should be untouched, the update descriptor process changes it. */
1537 tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0);
1539 /* Time to test the update of those descriptors. At first, we have no node
1540 * in the routerlist so this will find NO suitable node for the IPs. */
1541 setup_full_capture_of_logs(LOG_INFO);
1542 update_all_descriptors_intro_points(now);
1543 expect_log_msg_containing("Unable to find a suitable node to be an "
1544 "introduction point for service");
1545 teardown_capture_of_logs();
1546 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1547 OP_EQ, 0);
1548 tt_int_op(digest256map_size(service->desc_next->intro_points.map),
1549 OP_EQ, 0);
1551 /* Now, we'll setup a node_t. */
1553 curve25519_secret_key_t curve25519_secret_key;
1555 memset(&ri, 0, sizeof(routerinfo_t));
1557 tor_addr_parse(&ri.ipv4_addr, "127.0.0.1");
1558 ri.ipv4_orport = 1337;
1559 ri.purpose = ROUTER_PURPOSE_GENERAL;
1560 /* Ugly yes but we never free the "ri" object so this just makes things
1561 * easier. */
1562 ri.protocol_list = (char *) "HSDir=1-2 LinkAuth=3";
1563 summarize_protover_flags(&ri.pv, ri.protocol_list, NULL);
1564 ret = curve25519_secret_key_generate(&curve25519_secret_key, 0);
1565 tt_int_op(ret, OP_EQ, 0);
1566 ri.onion_curve25519_pkey =
1567 tor_malloc_zero(sizeof(curve25519_public_key_t));
1568 ri.onion_pkey = tor_malloc_zero(140);
1569 curve25519_public_key_generate(ri.onion_curve25519_pkey,
1570 &curve25519_secret_key);
1571 memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN);
1572 /* Setup ed25519 identity */
1573 ed25519_keypair_t kp1;
1574 ed25519_keypair_generate(&kp1, 0);
1575 ri.cache_info.signing_key_cert = tor_malloc_zero(sizeof(tor_cert_t));
1576 tt_assert(ri.cache_info.signing_key_cert);
1577 ed25519_pubkey_copy(&ri.cache_info.signing_key_cert->signing_key,
1578 &kp1.pubkey);
1579 nodelist_set_routerinfo(&ri, NULL);
1580 node = node_get_mutable_by_id(ri.cache_info.identity_digest);
1581 tt_assert(node);
1582 node->is_running = node->is_valid = node->is_fast = node->is_stable = 1;
1585 /* We have to set this, or the lack of microdescriptors for these
1586 * nodes will make them unusable. */
1587 get_options_mutable()->UseMicrodescriptors = 0;
1589 /* We expect to pick only one intro point from the node above. */
1590 setup_full_capture_of_logs(LOG_INFO);
1591 update_all_descriptors_intro_points(now);
1592 tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */
1593 tor_free(node->ri->cache_info.signing_key_cert);
1594 tor_free(node->ri->onion_pkey);
1595 expect_log_msg_containing("just picked 1 intro points and wanted 3 for next "
1596 "descriptor. It currently has 0 intro points. "
1597 "Launching ESTABLISH_INTRO circuit shortly.");
1598 teardown_capture_of_logs();
1599 tt_int_op(digest256map_size(service->desc_current->intro_points.map),
1600 OP_EQ, 1);
1601 tt_int_op(digest256map_size(service->desc_next->intro_points.map),
1602 OP_EQ, 1);
1603 /* Get the IP object. Because we don't have the auth key of the IP, we can't
1604 * query it so get the first element in the map. */
1606 void *obj = NULL;
1607 const uint8_t *key;
1608 digest256map_iter_t *iter =
1609 digest256map_iter_init(service->desc_current->intro_points.map);
1610 digest256map_iter_get(iter, &key, &obj);
1611 tt_assert(obj);
1612 ip_cur = obj;
1613 /* Get also the IP from the next descriptor. We'll make sure it's not the
1614 * same object as in the current descriptor. */
1615 iter = digest256map_iter_init(service->desc_next->intro_points.map);
1616 digest256map_iter_get(iter, &key, &obj);
1617 tt_assert(obj);
1618 ip_next = obj;
1620 tt_mem_op(ip_cur, OP_NE, ip_next, sizeof(hs_desc_intro_point_t));
1622 /* We won't test the service IP object because there is a specific test
1623 * already for this but we'll make sure that the state is coherent.*/
1625 /* Three link specifiers are mandatory so make sure we do have them. */
1626 tt_int_op(smartlist_len(ip_cur->base.link_specifiers), OP_EQ, 3);
1627 /* Make sure we have a valid encryption keypair generated when we pick an
1628 * intro point in the update process. */
1629 tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.seckey.secret_key,
1630 CURVE25519_SECKEY_LEN));
1631 tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.pubkey.public_key,
1632 CURVE25519_PUBKEY_LEN));
1633 tt_u64_op(ip_cur->time_to_expire, OP_GE, now +
1634 INTRO_POINT_LIFETIME_MIN_SECONDS);
1635 tt_u64_op(ip_cur->time_to_expire, OP_LE, now +
1636 INTRO_POINT_LIFETIME_MAX_SECONDS);
1638 /* Now, we will try to set up a service after a new time period has started
1639 * and see if it behaves as expected. */
1641 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
1642 &mock_ns.valid_after);
1643 tt_int_op(ret, OP_EQ, 0);
1644 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
1645 &mock_ns.fresh_until);
1646 tt_int_op(ret, OP_EQ, 0);
1648 update_approx_time(mock_ns.valid_after+1);
1649 now = mock_ns.valid_after+1;
1651 /* Create a service without a current descriptor to trigger a build. */
1652 service = helper_create_service();
1653 tt_assert(service);
1654 /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */
1655 service_descriptor_free(service->desc_current);
1656 service->desc_current = NULL;
1658 /* We have a fresh service so this should trigger a build for both
1659 * descriptors for specific time period that we'll test. */
1660 build_all_descriptors(now);
1661 /* Check *current* descriptor. */
1662 tt_assert(service->desc_current);
1663 tt_assert(service->desc_current->desc);
1664 tt_assert(service->desc_current->intro_points.map);
1665 /* This should be for the previous time period. */
1666 tt_u64_op(service->desc_current->time_period_num, OP_EQ,
1667 hs_get_previous_time_period_num(0));
1668 /* This should be untouched, the update descriptor process changes it. */
1669 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0);
1671 /* Check *next* descriptor. */
1672 tt_assert(service->desc_next);
1673 tt_assert(service->desc_next->desc);
1674 tt_assert(service->desc_next->intro_points.map);
1675 tt_assert(service->desc_current != service->desc_next);
1676 tt_u64_op(service->desc_next->time_period_num, OP_EQ,
1677 hs_get_time_period_num(0));
1678 /* This should be untouched, the update descriptor process changes it. */
1679 tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0);
1681 /* Let's remove the next descriptor to simulate a rotation. */
1682 service_descriptor_free(service->desc_next);
1683 service->desc_next = NULL;
1685 build_all_descriptors(now);
1686 /* Check *next* descriptor. */
1687 tt_assert(service->desc_next);
1688 tt_assert(service->desc_next->desc);
1689 tt_assert(service->desc_next->intro_points.map);
1690 tt_assert(service->desc_current != service->desc_next);
1691 tt_u64_op(service->desc_next->time_period_num, OP_EQ,
1692 hs_get_next_time_period_num(0));
1693 /* This should be untouched, the update descriptor process changes it. */
1694 tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0);
1696 done:
1697 if (service) {
1698 remove_service(get_hs_service_map(), service);
1699 hs_service_free(service);
1701 hs_free_all();
1702 nodelist_free_all();
1705 /** Test building descriptors. We use this separate function instead of
1706 * using test_build_update_descriptors because that function is too complex
1707 * and also too interactive. */
1708 static void
1709 test_build_descriptors(void *arg)
1711 int ret;
1712 time_t now = time(NULL);
1713 hs_service_t *last_service = NULL;
1715 (void) arg;
1717 hs_init();
1719 MOCK(get_or_state,
1720 get_or_state_replacement);
1721 MOCK(networkstatus_get_reasonably_live_consensus,
1722 mock_networkstatus_get_reasonably_live_consensus);
1724 dummy_state = or_state_new();
1726 ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC",
1727 &mock_ns.valid_after);
1728 tt_int_op(ret, OP_EQ, 0);
1729 ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC",
1730 &mock_ns.fresh_until);
1731 tt_int_op(ret, OP_EQ, 0);
1732 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
1734 /* Generate a valid number of fake auth clients when a client authorization
1735 * is disabled. */
1737 hs_service_t *service = helper_create_service();
1738 last_service = service;
1739 service_descriptor_free(service->desc_current);
1740 service->desc_current = NULL;
1742 build_all_descriptors(now);
1743 tt_assert(service->desc_current);
1744 tt_assert(service->desc_current->desc);
1746 hs_desc_superencrypted_data_t *superencrypted;
1747 superencrypted = &service->desc_current->desc->superencrypted_data;
1748 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16);
1750 helper_destroy_service(service);
1751 last_service = NULL;
1754 /* Generate a valid number of fake auth clients when the number of
1755 * clients is zero. */
1757 hs_service_t *service = helper_create_service_with_clients(0);
1758 last_service = service;
1759 service_descriptor_free(service->desc_current);
1760 service->desc_current = NULL;
1762 build_all_descriptors(now);
1763 hs_desc_superencrypted_data_t *superencrypted;
1764 superencrypted = &service->desc_current->desc->superencrypted_data;
1765 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16);
1767 helper_destroy_service(service);
1768 last_service = NULL;
1771 /* Generate a valid number of fake auth clients when the number of
1772 * clients is not a multiple of 16. */
1774 hs_service_t *service = helper_create_service_with_clients(20);
1775 last_service = service;
1776 service_descriptor_free(service->desc_current);
1777 service->desc_current = NULL;
1779 build_all_descriptors(now);
1780 hs_desc_superencrypted_data_t *superencrypted;
1781 superencrypted = &service->desc_current->desc->superencrypted_data;
1782 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32);
1784 helper_destroy_service(service);
1785 last_service = NULL;
1788 /* Do not generate any fake desc client when the number of clients is
1789 * a multiple of 16 but not zero. */
1791 hs_service_t *service = helper_create_service_with_clients(32);
1792 last_service = service;
1793 service_descriptor_free(service->desc_current);
1794 service->desc_current = NULL;
1796 build_all_descriptors(now);
1797 hs_desc_superencrypted_data_t *superencrypted;
1798 superencrypted = &service->desc_current->desc->superencrypted_data;
1799 tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32);
1801 helper_destroy_service(service);
1802 last_service = NULL;
1805 done:
1806 helper_destroy_service(last_service);
1807 hs_free_all();
1810 static void
1811 test_upload_descriptors(void *arg)
1813 int ret;
1814 time_t now;
1815 hs_service_t *service;
1817 (void) arg;
1819 hs_init();
1820 MOCK(get_or_state,
1821 get_or_state_replacement);
1822 MOCK(networkstatus_get_reasonably_live_consensus,
1823 mock_networkstatus_get_reasonably_live_consensus);
1825 dummy_state = or_state_new();
1827 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
1828 &mock_ns.valid_after);
1829 tt_int_op(ret, OP_EQ, 0);
1830 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
1831 &mock_ns.fresh_until);
1832 tt_int_op(ret, OP_EQ, 0);
1833 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
1835 update_approx_time(mock_ns.valid_after+1);
1836 now = mock_ns.valid_after+1;
1838 /* Create a service with no descriptor. It's added to the global map. */
1839 service = hs_service_new(get_options());
1840 tt_assert(service);
1841 service->config.version = HS_VERSION_THREE;
1842 ed25519_secret_key_generate(&service->keys.identity_sk, 0);
1843 ed25519_public_key_generate(&service->keys.identity_pk,
1844 &service->keys.identity_sk);
1845 /* Register service to global map. */
1846 ret = register_service(get_hs_service_map(), service);
1847 tt_int_op(ret, OP_EQ, 0);
1848 /* But first, build our descriptor. */
1849 build_all_descriptors(now);
1851 /* Nothing should happen because we have 0 introduction circuit established
1852 * and we want (by default) 3 intro points. */
1853 run_upload_descriptor_event(now);
1854 /* If no upload happened, this should be untouched. */
1855 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0);
1856 /* We'll simulate that we've opened our intro point circuit and that we only
1857 * want one intro point. */
1858 service->config.num_intro_points = 1;
1860 /* Set our next upload time after now which will skip the upload. */
1861 service->desc_current->next_upload_time = now + 1000;
1862 run_upload_descriptor_event(now);
1863 /* If no upload happened, this should be untouched. */
1864 tt_u64_op(service->desc_current->next_upload_time, OP_EQ, now + 1000);
1866 done:
1867 hs_free_all();
1868 UNMOCK(get_or_state);
1871 /** Global vars used by test_rendezvous1_parsing() */
1872 static char rend1_payload[RELAY_PAYLOAD_SIZE];
1873 static size_t rend1_payload_len = 0;
1875 /** Mock for relay_send_command_from_edge() to send a RENDEZVOUS1 cell. Instead
1876 * of sending it to the network, instead save it to the global `rend1_payload`
1877 * variable so that we can inspect it in the test_rendezvous1_parsing()
1878 * test. */
1879 static int
1880 mock_relay_send_rendezvous1(streamid_t stream_id, circuit_t *circ,
1881 uint8_t relay_command, const char *payload,
1882 size_t payload_len,
1883 crypt_path_t *cpath_layer,
1884 const char *filename, int lineno)
1886 (void) stream_id;
1887 (void) circ;
1888 (void) relay_command;
1889 (void) cpath_layer;
1890 (void) filename;
1891 (void) lineno;
1893 memcpy(rend1_payload, payload, payload_len);
1894 rend1_payload_len = payload_len;
1896 return 0;
1899 /** Send a RENDEZVOUS1 as a service, and parse it as a client. */
1900 static void
1901 test_rendezvous1_parsing(void *arg)
1903 int retval;
1904 static const char *test_addr =
1905 "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion";
1906 hs_service_t *service = NULL;
1907 origin_circuit_t *service_circ = NULL;
1908 origin_circuit_t *client_circ = NULL;
1909 ed25519_keypair_t ip_auth_kp;
1910 curve25519_keypair_t ephemeral_kp;
1911 curve25519_keypair_t client_kp;
1912 curve25519_keypair_t ip_enc_kp;
1913 int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
1915 (void) arg;
1917 MOCK(relay_send_command_from_edge_, mock_relay_send_rendezvous1);
1920 /* Let's start by setting up the service that will start the rend */
1921 service = tor_malloc_zero(sizeof(hs_service_t));
1922 ed25519_secret_key_generate(&service->keys.identity_sk, 0);
1923 ed25519_public_key_generate(&service->keys.identity_pk,
1924 &service->keys.identity_sk);
1925 memcpy(service->onion_address, test_addr, sizeof(service->onion_address));
1926 tt_assert(service);
1930 /* Now let's set up the service rendezvous circuit and its keys. */
1931 service_circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND,
1932 flags);
1933 tor_free(service_circ->hs_ident);
1934 hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys;
1935 uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN];
1936 curve25519_keypair_generate(&ip_enc_kp, 0);
1937 curve25519_keypair_generate(&ephemeral_kp, 0);
1938 curve25519_keypair_generate(&client_kp, 0);
1939 ed25519_keypair_generate(&ip_auth_kp, 0);
1940 retval = hs_ntor_service_get_rendezvous1_keys(&ip_auth_kp.pubkey,
1941 &ip_enc_kp,
1942 &ephemeral_kp,
1943 &client_kp.pubkey,
1944 &hs_ntor_rend_cell_keys);
1945 tt_int_op(retval, OP_EQ, 0);
1947 memset(rendezvous_cookie, 2, sizeof(rendezvous_cookie));
1948 service_circ->hs_ident =
1949 create_rp_circuit_identifier(service, rendezvous_cookie,
1950 &ephemeral_kp.pubkey,
1951 &hs_ntor_rend_cell_keys);
1954 /* Send out the RENDEZVOUS1 and make sure that our mock func worked */
1955 tt_assert(fast_mem_is_zero(rend1_payload, 32));
1956 hs_circ_service_rp_has_opened(service, service_circ);
1957 tt_assert(!fast_mem_is_zero(rend1_payload, 32));
1958 tt_int_op(rend1_payload_len, OP_EQ, HS_LEGACY_RENDEZVOUS_CELL_SIZE);
1960 /******************************/
1962 /** Now let's create the client rendezvous circuit */
1963 client_circ =
1964 helper_create_origin_circuit(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED,
1965 flags);
1966 /* fix up its circ ident */
1967 ed25519_pubkey_copy(&client_circ->hs_ident->intro_auth_pk,
1968 &ip_auth_kp.pubkey);
1969 memcpy(&client_circ->hs_ident->rendezvous_client_kp,
1970 &client_kp, sizeof(client_circ->hs_ident->rendezvous_client_kp));
1971 memcpy(&client_circ->hs_ident->intro_enc_pk.public_key,
1972 &ip_enc_kp.pubkey.public_key,
1973 sizeof(client_circ->hs_ident->intro_enc_pk.public_key));
1975 /* Now parse the rendezvous2 circuit and make sure it was fine. We are
1976 * skipping 20 bytes off its payload, since that's the rendezvous cookie
1977 * which is only present in REND1. */
1978 retval = handle_rendezvous2(client_circ,
1979 (uint8_t*)rend1_payload+20,
1980 rend1_payload_len-20);
1981 tt_int_op(retval, OP_EQ, 0);
1983 /* TODO: We are only simulating client/service here. We could also simulate
1984 * the rendezvous point by plugging in rend_mid_establish_rendezvous(). We
1985 * would need an extra circuit and some more stuff but it's doable. */
1987 done:
1988 circuit_free_(TO_CIRCUIT(service_circ));
1989 circuit_free_(TO_CIRCUIT(client_circ));
1990 hs_service_free(service);
1991 hs_free_all();
1992 UNMOCK(relay_send_command_from_edge_);
1995 static void
1996 test_authorized_client_config_equal(void *arg)
1998 int ret;
1999 hs_service_config_t *config1, *config2;
2001 (void) arg;
2003 config1 = tor_malloc_zero(sizeof(*config1));
2004 config2 = tor_malloc_zero(sizeof(*config2));
2006 /* Both configs are empty. */
2008 config1->clients = smartlist_new();
2009 config2->clients = smartlist_new();
2011 ret = service_authorized_client_config_equal(config1, config2);
2012 tt_int_op(ret, OP_EQ, 1);
2014 service_clear_config(config1);
2015 service_clear_config(config2);
2018 /* Both configs have exactly the same client config. */
2020 config1->clients = smartlist_new();
2021 config2->clients = smartlist_new();
2023 hs_service_authorized_client_t *client1, *client2;
2024 client1 = helper_create_authorized_client();
2025 client2 = helper_create_authorized_client();
2027 smartlist_add(config1->clients, client1);
2028 smartlist_add(config1->clients, client2);
2030 /* We should swap the order of clients here to test that the order
2031 * does not matter. */
2032 smartlist_add(config2->clients, helper_clone_authorized_client(client2));
2033 smartlist_add(config2->clients, helper_clone_authorized_client(client1));
2035 ret = service_authorized_client_config_equal(config1, config2);
2036 tt_int_op(ret, OP_EQ, 1);
2038 service_clear_config(config1);
2039 service_clear_config(config2);
2042 /* The numbers of clients in both configs are not equal. */
2044 config1->clients = smartlist_new();
2045 config2->clients = smartlist_new();
2047 hs_service_authorized_client_t *client1, *client2;
2048 client1 = helper_create_authorized_client();
2049 client2 = helper_create_authorized_client();
2051 smartlist_add(config1->clients, client1);
2052 smartlist_add(config1->clients, client2);
2054 smartlist_add(config2->clients, helper_clone_authorized_client(client1));
2056 ret = service_authorized_client_config_equal(config1, config2);
2057 tt_int_op(ret, OP_EQ, 0);
2059 service_clear_config(config1);
2060 service_clear_config(config2);
2063 /* The first config has two distinct clients while the second config
2064 * has two clients but they are duplicate. */
2066 config1->clients = smartlist_new();
2067 config2->clients = smartlist_new();
2069 hs_service_authorized_client_t *client1, *client2;
2070 client1 = helper_create_authorized_client();
2071 client2 = helper_create_authorized_client();
2073 smartlist_add(config1->clients, client1);
2074 smartlist_add(config1->clients, client2);
2076 smartlist_add(config2->clients, helper_clone_authorized_client(client1));
2077 smartlist_add(config2->clients, helper_clone_authorized_client(client1));
2079 ret = service_authorized_client_config_equal(config1, config2);
2080 tt_int_op(ret, OP_EQ, 0);
2082 service_clear_config(config1);
2083 service_clear_config(config2);
2086 /* Both configs have totally distinct clients. */
2088 config1->clients = smartlist_new();
2089 config2->clients = smartlist_new();
2091 hs_service_authorized_client_t *client1, *client2, *client3, *client4;
2092 client1 = helper_create_authorized_client();
2093 client2 = helper_create_authorized_client();
2094 client3 = helper_create_authorized_client();
2095 client4 = helper_create_authorized_client();
2097 smartlist_add(config1->clients, client1);
2098 smartlist_add(config1->clients, client2);
2100 smartlist_add(config2->clients, client3);
2101 smartlist_add(config2->clients, client4);
2103 ret = service_authorized_client_config_equal(config1, config2);
2104 tt_int_op(ret, OP_EQ, 0);
2106 service_clear_config(config1);
2107 service_clear_config(config2);
2110 done:
2111 tor_free(config1);
2112 tor_free(config2);
2115 /** Test that client circuit ID gets correctly exported */
2116 static void
2117 test_export_client_circuit_id(void *arg)
2119 origin_circuit_t *or_circ = NULL;
2120 size_t sz;
2121 char *cp1=NULL, *cp2=NULL;
2122 connection_t *conn = NULL;
2124 (void) arg;
2126 MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2128 hs_service_init();
2130 /* Create service */
2131 hs_service_t *service = helper_create_service();
2132 /* Check that export circuit ID detection works */
2133 service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_NONE;
2134 tt_int_op(0, OP_EQ,
2135 hs_service_exports_circuit_id(&service->keys.identity_pk));
2136 service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_HAPROXY;
2137 tt_int_op(1, OP_EQ,
2138 hs_service_exports_circuit_id(&service->keys.identity_pk));
2140 /* Create client connection */
2141 conn = test_conn_get_connection(AP_CONN_STATE_CIRCUIT_WAIT, CONN_TYPE_AP, 0);
2143 /* Create client edge conn hs_ident */
2144 edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
2145 edge_conn->hs_ident = hs_ident_edge_conn_new(&service->keys.identity_pk);
2146 edge_conn->hs_ident->orig_virtual_port = 42;
2148 /* Create rend circuit */
2149 or_circ = origin_circuit_new();
2150 or_circ->base_.purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
2151 edge_conn->on_circuit = TO_CIRCUIT(or_circ);
2152 or_circ->global_identifier = 666;
2154 /* Export circuit ID */
2155 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
2157 /* Check contents */
2158 cp1 = buf_get_contents(conn->outbuf, &sz);
2159 tt_str_op(cp1, OP_EQ,
2160 "PROXY TCP6 fc00:dead:beef:4dad::0:29a ::1 666 42\r\n");
2162 /* Change circ GID and see that the reported circuit ID also changes */
2163 or_circ->global_identifier = 22;
2165 /* check changes */
2166 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
2167 cp2 = buf_get_contents(conn->outbuf, &sz);
2168 tt_str_op(cp1, OP_NE, cp2);
2169 tor_free(cp1);
2171 /* Check that GID with UINT32_MAX works. */
2172 or_circ->global_identifier = UINT32_MAX;
2174 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
2175 cp1 = buf_get_contents(conn->outbuf, &sz);
2176 tt_str_op(cp1, OP_EQ,
2177 "PROXY TCP6 fc00:dead:beef:4dad::ffff:ffff ::1 65535 42\r\n");
2178 tor_free(cp1);
2180 /* Check that GID with UINT16_MAX works. */
2181 or_circ->global_identifier = UINT16_MAX;
2183 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
2184 cp1 = buf_get_contents(conn->outbuf, &sz);
2185 tt_str_op(cp1, OP_EQ,
2186 "PROXY TCP6 fc00:dead:beef:4dad::0:ffff ::1 65535 42\r\n");
2187 tor_free(cp1);
2189 /* Check that GID with UINT16_MAX + 7 works. */
2190 or_circ->global_identifier = UINT16_MAX + 7;
2192 export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
2193 cp1 = buf_get_contents(conn->outbuf, &sz);
2194 tt_str_op(cp1, OP_EQ, "PROXY TCP6 fc00:dead:beef:4dad::1:6 ::1 6 42\r\n");
2196 done:
2197 UNMOCK(connection_write_to_buf_impl_);
2198 circuit_free_(TO_CIRCUIT(or_circ));
2199 connection_free_minimal(conn);
2200 hs_service_free(service);
2201 tor_free(cp1);
2202 tor_free(cp2);
2205 static smartlist_t *
2206 mock_node_get_link_specifier_smartlist(const node_t *node, bool direct_conn)
2208 (void) node;
2209 (void) direct_conn;
2211 smartlist_t *lspecs = smartlist_new();
2212 link_specifier_t *ls_legacy = link_specifier_new();
2213 smartlist_add(lspecs, ls_legacy);
2215 return lspecs;
2218 static node_t *fake_node = NULL;
2220 static const node_t *
2221 mock_build_state_get_exit_node(cpath_build_state_t *state)
2223 (void) state;
2225 if (!fake_node) {
2226 curve25519_secret_key_t seckey;
2227 curve25519_secret_key_generate(&seckey, 0);
2229 fake_node = tor_malloc_zero(sizeof(node_t));
2230 fake_node->ri = tor_malloc_zero(sizeof(routerinfo_t));
2231 fake_node->ri->onion_curve25519_pkey =
2232 tor_malloc_zero(sizeof(curve25519_public_key_t));
2233 curve25519_public_key_generate(fake_node->ri->onion_curve25519_pkey,
2234 &seckey);
2237 return fake_node;
2240 static void
2241 mock_launch_rendezvous_point_circuit(const hs_service_t *service,
2242 const hs_service_intro_point_t *ip,
2243 const hs_cell_introduce2_data_t *data)
2245 (void) service;
2246 (void) ip;
2247 (void) data;
2248 return;
2252 * Test that INTRO2 cells are handled well by onion services in the normal
2253 * case and also when onionbalance is enabled.
2255 static void
2256 test_intro2_handling(void *arg)
2258 (void)arg;
2260 MOCK(build_state_get_exit_node, mock_build_state_get_exit_node);
2261 MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
2262 MOCK(node_get_link_specifier_smartlist,
2263 mock_node_get_link_specifier_smartlist);
2264 MOCK(launch_rendezvous_point_circuit, mock_launch_rendezvous_point_circuit);
2266 memset(relay_payload, 0, sizeof(relay_payload));
2268 int retval;
2269 time_t now = 0101010101;
2270 update_approx_time(now);
2272 /** OK this is the play:
2274 * In Act I, we have a standalone onion service X (without onionbalance
2275 * enabled). We test that X can properly handle INTRO2 cells sent by a
2276 * client Alice.
2278 * In Act II, we create an onionbalance setup with frontend being Z which
2279 * includes instances X and Y. We then setup onionbalance on X and test that
2280 * Alice who addresses Z can communicate with X through INTRO2 cells.
2282 * In Act III, we test that Alice can also communicate with X
2283 * directly even tho onionbalance is enabled.
2285 * And finally in Act IV, we check various cases where the INTRO2 cell
2286 * should not go through because the subcredentials don't line up
2287 * (e.g. Alice sends INTRO2 to X using Y's subcredential).
2290 /** Let's start with some setup! Create the instances and the frontend
2291 service, create Alice, etc: */
2293 /* Create instance X */
2294 hs_service_t x_service;
2295 memset(&x_service, 0, sizeof(hs_service_t));
2296 /* Disable onionbalance */
2297 x_service.config.ob_master_pubkeys = NULL;
2298 x_service.state.replay_cache_rend_cookie = replaycache_new(0,0);
2300 /* Create subcredential for x: */
2301 ed25519_keypair_t x_identity_keypair;
2302 hs_subcredential_t x_subcred;
2303 ed25519_keypair_generate(&x_identity_keypair, 0);
2304 hs_helper_get_subcred_from_identity_keypair(&x_identity_keypair,
2305 &x_subcred);
2307 /* Create the x instance's intro point */
2308 hs_service_intro_point_t *x_ip = NULL;
2310 curve25519_secret_key_t seckey;
2311 curve25519_public_key_t pkey;
2312 curve25519_secret_key_generate(&seckey, 0);
2313 curve25519_public_key_generate(&pkey, &seckey);
2315 node_t intro_node;
2316 memset(&intro_node, 0, sizeof(intro_node));
2317 routerinfo_t ri;
2318 memset(&ri, 0, sizeof(routerinfo_t));
2319 ri.onion_curve25519_pkey = &pkey;
2320 intro_node.ri = &ri;
2322 x_ip = service_intro_point_new(&intro_node);
2325 /* Create z frontend's subcredential */
2326 ed25519_keypair_t z_identity_keypair;
2327 hs_subcredential_t z_subcred;
2328 ed25519_keypair_generate(&z_identity_keypair, 0);
2329 hs_helper_get_subcred_from_identity_keypair(&z_identity_keypair,
2330 &z_subcred);
2332 /* Create y instance's subcredential */
2333 ed25519_keypair_t y_identity_keypair;
2334 hs_subcredential_t y_subcred;
2335 ed25519_keypair_generate(&y_identity_keypair, 0);
2336 hs_helper_get_subcred_from_identity_keypair(&y_identity_keypair,
2337 &y_subcred);
2339 /* Create Alice's intro point */
2340 hs_desc_intro_point_t *alice_ip;
2341 ed25519_keypair_t signing_kp;
2342 ed25519_keypair_generate(&signing_kp, 0);
2343 alice_ip = hs_helper_build_intro_point(&signing_kp, now, "1.2.3.4", 0,
2344 &x_ip->auth_key_kp,
2345 &x_ip->enc_key_kp);
2347 /* Create Alice's intro and rend circuits */
2348 origin_circuit_t *intro_circ = origin_circuit_new();
2349 intro_circ->cpath = tor_malloc_zero(sizeof(crypt_path_t));
2350 intro_circ->cpath->prev = intro_circ->cpath;
2351 intro_circ->hs_ident = tor_malloc_zero(sizeof(*intro_circ->hs_ident));
2352 origin_circuit_t rend_circ;
2353 rend_circ.hs_ident = tor_malloc_zero(sizeof(*rend_circ.hs_ident));
2354 curve25519_keypair_generate(&rend_circ.hs_ident->rendezvous_client_kp, 0);
2355 memset(rend_circ.hs_ident->rendezvous_cookie, 'r', HS_REND_COOKIE_LEN);
2357 /* ************************************************************ */
2359 /* Act I:
2361 * Where Alice connects to X without onionbalance in the picture */
2363 /* Create INTRODUCE1 */
2364 tt_assert(fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
2365 retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
2366 alice_ip, &x_subcred);
2368 /* Check that the payload was written successfully */
2369 tt_int_op(retval, OP_EQ, 0);
2370 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
2371 tt_int_op(relay_payload_len, OP_NE, 0);
2373 /* Handle the cell */
2374 retval = hs_circ_handle_introduce2(&x_service,
2375 intro_circ, x_ip,
2376 &x_subcred,
2377 (uint8_t*)relay_payload,relay_payload_len);
2378 tt_int_op(retval, OP_EQ, 0);
2380 /* ************************************************************ */
2382 /* Act II:
2384 * We now create an onionbalance setup with Z being the frontend and X and Y
2385 * being the backend instances. Make sure that Alice can talk with the
2386 * backend instance X even tho she thinks she is talking to the frontend Z.
2389 /* Now configure the X instance to do onionbalance with Z as the frontend */
2390 x_service.config.ob_master_pubkeys = smartlist_new();
2391 smartlist_add(x_service.config.ob_master_pubkeys,
2392 &z_identity_keypair.pubkey);
2394 /* Create descriptors for x and load next descriptor with the x's
2395 * subcredential so that it can accept connections for itself. */
2396 x_service.desc_current = service_descriptor_new();
2397 memset(x_service.desc_current->desc->subcredential.subcred, 'C',SUBCRED_LEN);
2398 x_service.desc_next = service_descriptor_new();
2399 memcpy(&x_service.desc_next->desc->subcredential, &x_subcred, SUBCRED_LEN);
2401 /* Refresh OB keys */
2402 hs_ob_refresh_keys(&x_service);
2404 /* Create INTRODUCE1 from Alice to X through Z */
2405 memset(relay_payload, 0, sizeof(relay_payload));
2406 retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
2407 alice_ip, &z_subcred);
2409 /* Check that the payload was written successfully */
2410 tt_int_op(retval, OP_EQ, 0);
2411 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
2412 tt_int_op(relay_payload_len, OP_NE, 0);
2414 /* Deliver INTRODUCE1 to X even tho it carries Z's subcredential */
2415 replaycache_free(x_service.state.replay_cache_rend_cookie);
2416 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
2418 retval = hs_circ_handle_introduce2(&x_service,
2419 intro_circ, x_ip,
2420 &z_subcred,
2421 (uint8_t*)relay_payload, relay_payload_len);
2422 tt_int_op(retval, OP_EQ, 0);
2424 replaycache_free(x_ip->replay_cache);
2425 x_ip->replay_cache = replaycache_new(0, 0);
2427 replaycache_free(x_service.state.replay_cache_rend_cookie);
2428 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
2430 /* ************************************************************ */
2432 /* Act III:
2434 * Now send a direct INTRODUCE cell from Alice to X using X's subcredential
2435 * and check that it succeeds even with onionbalance enabled.
2438 /* Refresh OB keys (just to check for memleaks) */
2439 hs_ob_refresh_keys(&x_service);
2441 /* Create INTRODUCE1 from Alice to X using X's subcred. */
2442 memset(relay_payload, 0, sizeof(relay_payload));
2443 retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
2444 alice_ip, &x_subcred);
2446 /* Check that the payload was written successfully */
2447 tt_int_op(retval, OP_EQ, 0);
2448 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
2449 tt_int_op(relay_payload_len, OP_NE, 0);
2451 /* Send INTRODUCE1 to X with X's subcredential (should succeed) */
2452 replaycache_free(x_service.state.replay_cache_rend_cookie);
2453 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
2455 retval = hs_circ_handle_introduce2(&x_service,
2456 intro_circ, x_ip,
2457 &x_subcred,
2458 (uint8_t*)relay_payload, relay_payload_len);
2459 tt_int_op(retval, OP_EQ, 0);
2461 /* ************************************************************ */
2463 /* Act IV:
2465 * Test cases where the INTRO2 cell should not be able to decode.
2468 /* Try sending the exact same INTRODUCE2 cell again and see that the intro
2469 * point replay cache triggers: */
2470 setup_full_capture_of_logs(LOG_WARN);
2471 retval = hs_circ_handle_introduce2(&x_service,
2472 intro_circ, x_ip,
2473 &x_subcred,
2474 (uint8_t*)relay_payload, relay_payload_len);
2475 tt_int_op(retval, OP_EQ, -1);
2476 expect_log_msg_containing("with the same ENCRYPTED section");
2477 teardown_capture_of_logs();
2479 /* Now cleanup the intro point replay cache but not the service replay cache
2480 and see that this one triggers this time. */
2481 replaycache_free(x_ip->replay_cache);
2482 x_ip->replay_cache = replaycache_new(0, 0);
2483 setup_full_capture_of_logs(LOG_INFO);
2484 retval = hs_circ_handle_introduce2(&x_service,
2485 intro_circ, x_ip,
2486 &x_subcred,
2487 (uint8_t*)relay_payload, relay_payload_len);
2488 tt_int_op(retval, OP_EQ, -1);
2489 expect_log_msg_containing("with same REND_COOKIE");
2490 teardown_capture_of_logs();
2492 /* Now just to make sure cleanup both replay caches and make sure that the
2493 cell gets through */
2494 replaycache_free(x_ip->replay_cache);
2495 x_ip->replay_cache = replaycache_new(0, 0);
2496 replaycache_free(x_service.state.replay_cache_rend_cookie);
2497 x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
2498 retval = hs_circ_handle_introduce2(&x_service,
2499 intro_circ, x_ip,
2500 &x_subcred,
2501 (uint8_t*)relay_payload, relay_payload_len);
2502 tt_int_op(retval, OP_EQ, 0);
2504 /* As a final thing, create an INTRODUCE1 cell from Alice to X using Y's
2505 * subcred (should fail since Y is just another instance and not the frontend
2506 * service!) */
2507 memset(relay_payload, 0, sizeof(relay_payload));
2508 retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
2509 alice_ip, &y_subcred);
2510 tt_int_op(retval, OP_EQ, 0);
2512 /* Check that the payload was written successfully */
2513 tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
2514 tt_int_op(relay_payload_len, OP_NE, 0);
2516 retval = hs_circ_handle_introduce2(&x_service,
2517 intro_circ, x_ip,
2518 &y_subcred,
2519 (uint8_t*)relay_payload, relay_payload_len);
2520 tt_int_op(retval, OP_EQ, -1);
2522 done:
2523 /* Start cleaning up X */
2524 replaycache_free(x_service.state.replay_cache_rend_cookie);
2525 smartlist_free(x_service.config.ob_master_pubkeys);
2526 tor_free(x_service.state.ob_subcreds);
2527 service_descriptor_free(x_service.desc_current);
2528 service_descriptor_free(x_service.desc_next);
2529 service_intro_point_free(x_ip);
2531 /* Clean up Alice */
2532 hs_desc_intro_point_free(alice_ip);
2533 tor_free(rend_circ.hs_ident);
2535 if (fake_node) {
2536 tor_free(fake_node->ri->onion_curve25519_pkey);
2537 tor_free(fake_node->ri);
2538 tor_free(fake_node);
2541 UNMOCK(build_state_get_exit_node);
2542 UNMOCK(relay_send_command_from_edge_);
2543 UNMOCK(node_get_link_specifier_smartlist);
2544 UNMOCK(launch_rendezvous_point_circuit);
2547 static void
2548 test_cannot_upload_descriptors(void *arg)
2550 int ret;
2551 time_t now;
2552 hs_service_t *service;
2554 (void) arg;
2556 hs_init();
2557 MOCK(get_or_state,
2558 get_or_state_replacement);
2559 MOCK(networkstatus_get_reasonably_live_consensus,
2560 mock_networkstatus_get_reasonably_live_consensus);
2562 dummy_state = or_state_new();
2564 ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
2565 &mock_ns.valid_after);
2566 tt_int_op(ret, OP_EQ, 0);
2567 ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
2568 &mock_ns.fresh_until);
2569 tt_int_op(ret, OP_EQ, 0);
2570 dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
2572 update_approx_time(mock_ns.valid_after + 1);
2573 now = mock_ns.valid_after + 1;
2575 /* Create a service with no descriptor. It's added to the global map. */
2576 service = hs_service_new(get_options());
2577 tt_assert(service);
2578 service->config.version = HS_VERSION_THREE;
2579 ed25519_secret_key_generate(&service->keys.identity_sk, 0);
2580 ed25519_public_key_generate(&service->keys.identity_pk,
2581 &service->keys.identity_sk);
2582 /* Register service to global map. */
2583 ret = register_service(get_hs_service_map(), service);
2584 tt_int_op(ret, OP_EQ, 0);
2585 /* But first, build our descriptor. */
2586 build_all_descriptors(now);
2588 /* 1. Testing missing intro points reason. */
2590 digest256map_t *cur = service->desc_current->intro_points.map;
2591 digest256map_t *tmp = digest256map_new();
2592 service->desc_current->intro_points.map = tmp;
2593 service->desc_current->missing_intro_points = 1;
2594 setup_full_capture_of_logs(LOG_INFO);
2595 run_upload_descriptor_event(now);
2596 digest256map_free(tmp, tor_free_);
2597 service->desc_current->intro_points.map = cur;
2598 expect_log_msg_containing(
2599 "Service [scrubbed] can't upload its current descriptor: "
2600 "Missing intro points");
2601 teardown_capture_of_logs();
2602 /* Reset. */
2603 service->desc_current->missing_intro_points = 0;
2606 /* 2. Testing non established intro points. */
2608 setup_full_capture_of_logs(LOG_INFO);
2609 run_upload_descriptor_event(now);
2610 expect_log_msg_containing(
2611 "Service [scrubbed] can't upload its current descriptor: "
2612 "Intro circuits aren't yet all established (0/3).");
2613 teardown_capture_of_logs();
2616 /* We need to pass the established circuit tests and thus from now on, we
2617 * MOCK this to return 3 intro points. */
2618 MOCK(count_desc_circuit_established, mock_count_desc_circuit_established);
2619 num_intro_points = 3;
2621 /* 3. Testing non established intro points. */
2623 service->desc_current->next_upload_time = now + 1000;
2624 setup_full_capture_of_logs(LOG_INFO);
2625 run_upload_descriptor_event(now);
2626 expect_log_msg_containing(
2627 "Service [scrubbed] can't upload its current descriptor: "
2628 "Next upload time is");
2629 teardown_capture_of_logs();
2630 /* Reset. */
2631 service->desc_current->next_upload_time = 0;
2634 /* 4. Testing missing live consensus. */
2636 MOCK(networkstatus_get_reasonably_live_consensus,
2637 mock_networkstatus_get_reasonably_live_consensus_null);
2638 setup_full_capture_of_logs(LOG_INFO);
2639 run_upload_descriptor_event(now);
2640 expect_log_msg_containing(
2641 "Service [scrubbed] can't upload its current descriptor: "
2642 "No reasonably live consensus");
2643 teardown_capture_of_logs();
2644 /* Reset. */
2645 MOCK(networkstatus_get_reasonably_live_consensus,
2646 mock_networkstatus_get_reasonably_live_consensus);
2649 /* 5. Test missing minimum directory information. */
2651 MOCK(router_have_minimum_dir_info,
2652 mock_router_have_minimum_dir_info_false);
2653 setup_full_capture_of_logs(LOG_INFO);
2654 run_upload_descriptor_event(now);
2655 expect_log_msg_containing(
2656 "Service [scrubbed] can't upload its current descriptor: "
2657 "Not enough directory information");
2658 teardown_capture_of_logs();
2660 /* Running it again shouldn't trigger anything due to rate limitation. */
2661 setup_full_capture_of_logs(LOG_INFO);
2662 run_upload_descriptor_event(now);
2663 expect_no_log_entry();
2664 teardown_capture_of_logs();
2665 UNMOCK(router_have_minimum_dir_info);
2668 /* Increase time and redo test (5) in order to test the rate limiting. */
2669 update_approx_time(mock_ns.valid_after + 61);
2671 MOCK(router_have_minimum_dir_info,
2672 mock_router_have_minimum_dir_info_false);
2673 setup_full_capture_of_logs(LOG_INFO);
2674 run_upload_descriptor_event(now);
2675 expect_log_msg_containing(
2676 "Service [scrubbed] can't upload its current descriptor: "
2677 "Not enough directory information");
2678 teardown_capture_of_logs();
2679 UNMOCK(router_have_minimum_dir_info);
2682 done:
2683 hs_free_all();
2684 UNMOCK(count_desc_circuit_established);
2685 UNMOCK(networkstatus_get_reasonably_live_consensus);
2686 UNMOCK(get_or_state);
2689 struct testcase_t hs_service_tests[] = {
2690 { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK,
2691 NULL, NULL },
2692 { "load_keys", test_load_keys, TT_FORK,
2693 NULL, NULL },
2694 { "client_filename_is_valid", test_client_filename_is_valid, TT_FORK,
2695 NULL, NULL },
2696 { "parse_authorized_client", test_parse_authorized_client, TT_FORK,
2697 NULL, NULL },
2698 { "load_keys_with_client_auth", test_load_keys_with_client_auth, TT_FORK,
2699 NULL, NULL },
2700 { "access_service", test_access_service, TT_FORK,
2701 NULL, NULL },
2702 { "service_intro_point", test_service_intro_point, TT_FORK,
2703 NULL, NULL },
2704 { "helper_functions", test_helper_functions, TT_FORK,
2705 NULL, NULL },
2706 { "intro_circuit_opened", test_intro_circuit_opened, TT_FORK,
2707 NULL, NULL },
2708 { "intro_established", test_intro_established, TT_FORK,
2709 NULL, NULL },
2710 { "closing_intro_circs", test_closing_intro_circs, TT_FORK,
2711 NULL, NULL },
2712 { "rdv_circuit_opened", test_rdv_circuit_opened, TT_FORK,
2713 NULL, NULL },
2714 { "bad_introduce2", test_bad_introduce2, TT_FORK,
2715 NULL, NULL },
2716 { "service_event", test_service_event, TT_FORK,
2717 NULL, NULL },
2718 { "rotate_descriptors", test_rotate_descriptors, TT_FORK,
2719 NULL, NULL },
2720 { "build_update_descriptors", test_build_update_descriptors, TT_FORK,
2721 NULL, NULL },
2722 { "build_descriptors", test_build_descriptors, TT_FORK,
2723 NULL, NULL },
2724 { "upload_descriptors", test_upload_descriptors, TT_FORK,
2725 NULL, NULL },
2726 { "cannot_upload_descriptors", test_cannot_upload_descriptors, TT_FORK,
2727 NULL, NULL },
2728 { "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK,
2729 NULL, NULL },
2730 { "authorized_client_config_equal", test_authorized_client_config_equal,
2731 TT_FORK, NULL, NULL },
2732 { "export_client_circuit_id", test_export_client_circuit_id, TT_FORK,
2733 NULL, NULL },
2734 { "intro2_handling", test_intro2_handling, TT_FORK, NULL, NULL },
2736 END_OF_TESTCASES