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