Line data Source code
1 : /* Copyright (c) 2001-2004, Roger Dingledine.
2 : * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 : /* See LICENSE for licensing information */
5 :
6 : #define RENDCOMMON_PRIVATE
7 : #define GEOIP_PRIVATE
8 : #define CONNECTION_PRIVATE
9 : #define CONFIG_PRIVATE
10 : #define RENDCACHE_PRIVATE
11 : #define DIRCACHE_PRIVATE
12 :
13 : #include "core/or/or.h"
14 : #include "app/config/config.h"
15 : #include "core/mainloop/connection.h"
16 : #include "feature/dircache/consdiffmgr.h"
17 : #include "feature/dircommon/directory.h"
18 : #include "feature/dircache/dircache.h"
19 : #include "test/test.h"
20 : #include "lib/compress/compress.h"
21 : #include "feature/relay/relay_config.h"
22 : #include "feature/relay/router.h"
23 : #include "feature/nodelist/authcert.h"
24 : #include "feature/nodelist/dirlist.h"
25 : #include "feature/nodelist/routerlist.h"
26 : #include "feature/nodelist/microdesc.h"
27 : #include "test/test_helpers.h"
28 : #include "feature/nodelist/nodelist.h"
29 : #include "feature/client/entrynodes.h"
30 : #include "feature/dirparse/authcert_parse.h"
31 : #include "feature/dirparse/sigcommon.h"
32 : #include "feature/nodelist/networkstatus.h"
33 : #include "core/proto/proto_http.h"
34 : #include "lib/geoip/geoip.h"
35 : #include "feature/stats/geoip_stats.h"
36 : #include "feature/dircache/dirserv.h"
37 : #include "feature/dirauth/dirvote.h"
38 : #include "test/log_test_helpers.h"
39 : #include "feature/dirauth/voting_schedule.h"
40 :
41 : #include "feature/dircommon/dir_connection_st.h"
42 : #include "feature/dirclient/dir_server_st.h"
43 : #include "feature/nodelist/networkstatus_st.h"
44 : #include "feature/nodelist/routerinfo_st.h"
45 : #include "feature/nodelist/routerlist_st.h"
46 :
47 : #ifdef _WIN32
48 : /* For mkdir() */
49 : #include <direct.h>
50 : #else
51 : #include <dirent.h>
52 : #endif /* defined(_WIN32) */
53 :
54 : #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
55 : DISABLE_GCC_WARNING("-Woverlength-strings")
56 : /* We allow huge string constants in the unit tests, but not in the code
57 : * at large. */
58 : #endif
59 : #include "vote_descriptors.inc"
60 : #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
61 : ENABLE_GCC_WARNING("-Woverlength-strings")
62 : #endif
63 :
64 : #define NOT_FOUND "HTTP/1.0 404 Not found\r\n\r\n"
65 : #define BAD_REQUEST "HTTP/1.0 400 Bad request\r\n\r\n"
66 : #define SERVER_BUSY "HTTP/1.0 503 Directory busy, try again later\r\n\r\n"
67 : #define TOO_OLD "HTTP/1.0 404 Consensus is too old\r\n\r\n"
68 : #define NOT_ENOUGH_CONSENSUS_SIGNATURES "HTTP/1.0 404 " \
69 : "Consensus not signed by sufficient number of requested authorities\r\n\r\n"
70 :
71 : #define consdiffmgr_add_consensus consdiffmgr_add_consensus_nulterm
72 :
73 : static int
74 55 : mock_ignore_signature_token(const char *digest,
75 : ssize_t digest_len,
76 : struct directory_token_t *tok,
77 : crypto_pk_t *pkey,
78 : int flags,
79 : const char *doctype)
80 : {
81 55 : (void)digest;
82 55 : (void)digest_len;
83 55 : (void)tok;
84 55 : (void)pkey;
85 55 : (void)flags;
86 55 : (void)doctype;
87 55 : return 0;
88 : }
89 :
90 : static dir_connection_t *
91 56 : new_dir_conn(void)
92 : {
93 56 : dir_connection_t *conn = dir_connection_new(AF_INET);
94 56 : tor_addr_from_ipv4h(&conn->base_.addr, 0x7f000001);
95 56 : TO_CONN(conn)->address = tor_strdup("127.0.0.1");
96 56 : return conn;
97 : }
98 :
99 : static void
100 1 : test_dir_handle_get_bad_request(void *data)
101 : {
102 1 : dir_connection_t *conn = NULL;
103 1 : char *header = NULL;
104 1 : (void) data;
105 :
106 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
107 :
108 1 : conn = new_dir_conn();
109 1 : tt_int_op(directory_handle_command_get(conn, "", NULL, 0), OP_EQ, 0);
110 :
111 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
112 : NULL, NULL, 1, 0);
113 :
114 1 : tt_str_op(header, OP_EQ, BAD_REQUEST);
115 :
116 1 : done:
117 1 : UNMOCK(connection_write_to_buf_impl_);
118 1 : connection_free_minimal(TO_CONN(conn));
119 1 : tor_free(header);
120 1 : }
121 :
122 : static void
123 1 : test_dir_handle_get_v1_command_not_found(void *data)
124 : {
125 1 : dir_connection_t *conn = NULL;
126 1 : char *header = NULL;
127 1 : (void) data;
128 :
129 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
130 :
131 1 : conn = new_dir_conn();
132 :
133 : // no frontpage configured
134 1 : tt_ptr_op(relay_get_dirportfrontpage(), OP_EQ, NULL);
135 :
136 : /* V1 path */
137 1 : tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
138 : OP_EQ, 0);
139 :
140 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
141 : NULL, NULL, 1, 0);
142 :
143 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
144 :
145 1 : done:
146 1 : UNMOCK(connection_write_to_buf_impl_);
147 1 : connection_free_minimal(TO_CONN(conn));
148 1 : tor_free(header);
149 1 : }
150 :
151 : static const char*
152 2 : mock_get_dirportfrontpage(void)
153 : {
154 2 : return "HELLO FROM FRONTPAGE";
155 : }
156 :
157 : static void
158 1 : test_dir_handle_get_v1_command(void *data)
159 : {
160 1 : dir_connection_t *conn = NULL;
161 1 : char *header = NULL;
162 1 : char *body = NULL;
163 1 : size_t body_used = 0, body_len = 0;
164 1 : const char *exp_body = NULL;
165 1 : (void) data;
166 :
167 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
168 1 : MOCK(relay_get_dirportfrontpage, mock_get_dirportfrontpage);
169 :
170 1 : exp_body = relay_get_dirportfrontpage();
171 1 : body_len = strlen(exp_body);
172 :
173 1 : conn = new_dir_conn();
174 1 : tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
175 : OP_EQ, 0);
176 :
177 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
178 : &body, &body_used, body_len+1, 0);
179 :
180 1 : tt_assert(header);
181 1 : tt_assert(body);
182 :
183 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
184 1 : tt_assert(strstr(header, "Content-Type: text/html\r\n"));
185 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
186 1 : tt_assert(strstr(header, "Content-Length: 20\r\n"));
187 :
188 1 : tt_int_op(body_used, OP_EQ, strlen(body));
189 1 : tt_str_op(body, OP_EQ, exp_body);
190 :
191 1 : done:
192 1 : UNMOCK(connection_write_to_buf_impl_);
193 1 : UNMOCK(relay_get_dirportfrontpage);
194 1 : connection_free_minimal(TO_CONN(conn));
195 1 : tor_free(header);
196 1 : tor_free(body);
197 1 : }
198 :
199 : static void
200 1 : test_dir_handle_get_not_found(void *data)
201 : {
202 1 : dir_connection_t *conn = NULL;
203 1 : char *header = NULL;
204 1 : (void) data;
205 :
206 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
207 :
208 1 : conn = new_dir_conn();
209 :
210 : /* Unrecognized path */
211 1 : tt_int_op(directory_handle_command_get(conn, GET("/anything"), NULL, 0),
212 : OP_EQ, 0);
213 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
214 : NULL, NULL, 1, 0);
215 :
216 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
217 :
218 1 : done:
219 1 : UNMOCK(connection_write_to_buf_impl_);
220 1 : connection_free_minimal(TO_CONN(conn));
221 1 : tor_free(header);
222 1 : }
223 :
224 : static void
225 1 : test_dir_handle_get_robots_txt(void *data)
226 : {
227 1 : dir_connection_t *conn = NULL;
228 1 : char *header = NULL;
229 1 : char *body = NULL;
230 1 : size_t body_used = 0;
231 1 : (void) data;
232 :
233 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
234 :
235 1 : conn = new_dir_conn();
236 :
237 1 : tt_int_op(directory_handle_command_get(conn, GET("/tor/robots.txt"),
238 : NULL, 0), OP_EQ, 0);
239 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
240 : &body, &body_used, 29, 0);
241 :
242 1 : tt_assert(header);
243 1 : tt_assert(body);
244 :
245 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
246 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
247 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
248 1 : tt_assert(strstr(header, "Content-Length: 28\r\n"));
249 :
250 1 : tt_int_op(body_used, OP_EQ, strlen(body));
251 1 : tt_str_op(body, OP_EQ, "User-agent: *\r\nDisallow: /\r\n");
252 :
253 1 : done:
254 1 : UNMOCK(connection_write_to_buf_impl_);
255 1 : connection_free_minimal(TO_CONN(conn));
256 1 : tor_free(header);
257 1 : tor_free(body);
258 1 : }
259 :
260 : static const routerinfo_t * dhg_tests_router_get_my_routerinfo(void);
261 : ATTR_UNUSED static int dhg_tests_router_get_my_routerinfo_called = 0;
262 :
263 : static routerinfo_t *mock_routerinfo;
264 :
265 : static const routerinfo_t *
266 12 : dhg_tests_router_get_my_routerinfo(void)
267 : {
268 12 : if (!mock_routerinfo) {
269 2 : mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
270 : }
271 :
272 12 : return mock_routerinfo;
273 : }
274 :
275 : #define MICRODESC_GET(digest) GET("/tor/micro/d/" digest)
276 : static void
277 1 : test_dir_handle_get_micro_d_not_found(void *data)
278 : {
279 1 : dir_connection_t *conn = NULL;
280 1 : char *header = NULL;
281 1 : (void) data;
282 :
283 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
284 :
285 : #define B64_256_1 "8/Pz8/u7vz8/Pz+7vz8/Pz+7u/Pz8/P7u/Pz8/P7u78"
286 : #define B64_256_2 "zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMw"
287 1 : conn = new_dir_conn();
288 :
289 1 : const char *req = MICRODESC_GET(B64_256_1 "-" B64_256_2);
290 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
291 :
292 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
293 : NULL, NULL, 1, 0);
294 :
295 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
296 :
297 1 : done:
298 1 : UNMOCK(connection_write_to_buf_impl_);
299 :
300 1 : connection_free_minimal(TO_CONN(conn));
301 1 : tor_free(header);
302 1 : }
303 :
304 : static or_options_t *mock_options = NULL;
305 : static void
306 22 : init_mock_options(void)
307 : {
308 22 : mock_options = options_new();
309 22 : mock_options->TestingTorNetwork = 1;
310 22 : mock_options->DataDirectory = tor_strdup(get_fname_rnd("datadir_tmp"));
311 22 : mock_options->CacheDirectory = tor_strdup(mock_options->DataDirectory);
312 22 : check_private_dir(mock_options->DataDirectory, CPD_CREATE, NULL);
313 22 : }
314 :
315 : static const or_options_t *
316 56 : mock_get_options(void)
317 : {
318 56 : tor_assert(mock_options);
319 56 : return mock_options;
320 : }
321 :
322 : static const char microdesc[] =
323 : "onion-key\n"
324 : "-----BEGIN RSA PUBLIC KEY-----\n"
325 : "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
326 : "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
327 : "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
328 : "-----END RSA PUBLIC KEY-----\n"
329 : "ntor-onion-key QlrOXAa8j3LD31LESsPm/lIKFBwevk2oXdqJcd9SEUc=\n";
330 :
331 : static void
332 1 : test_dir_handle_get_micro_d(void *data)
333 : {
334 1 : dir_connection_t *conn = NULL;
335 1 : microdesc_cache_t *mc = NULL ;
336 1 : smartlist_t *list = NULL;
337 1 : char digest[DIGEST256_LEN];
338 1 : char digest_base64[128];
339 1 : char path[80];
340 1 : char *header = NULL;
341 1 : char *body = NULL;
342 1 : size_t body_used = 0;
343 1 : (void) data;
344 :
345 1 : MOCK(get_options, mock_get_options);
346 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
347 :
348 : /* SETUP */
349 1 : init_mock_options();
350 :
351 : /* Add microdesc to cache */
352 1 : crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
353 1 : base64_encode_nopad(digest_base64, sizeof(digest_base64),
354 : (uint8_t *) digest, DIGEST256_LEN);
355 :
356 1 : mc = get_microdesc_cache();
357 1 : list = microdescs_add_to_cache(mc, microdesc, NULL, SAVED_NOWHERE, 0,
358 : time(NULL), NULL);
359 1 : tt_int_op(1, OP_EQ, smartlist_len(list));
360 :
361 : /* Make the request */
362 1 : conn = new_dir_conn();
363 :
364 1 : tor_snprintf(path, sizeof(path), MICRODESC_GET("%s"), digest_base64);
365 1 : tt_int_op(directory_handle_command_get(conn, path, NULL, 0), OP_EQ, 0);
366 :
367 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
368 : &body, &body_used, strlen(microdesc)+1, 0);
369 :
370 1 : tt_assert(header);
371 1 : tt_assert(body);
372 :
373 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
374 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
375 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
376 :
377 1 : tt_int_op(body_used, OP_EQ, strlen(body));
378 1 : tt_str_op(body, OP_EQ, microdesc);
379 :
380 1 : done:
381 1 : UNMOCK(get_options);
382 1 : UNMOCK(connection_write_to_buf_impl_);
383 :
384 1 : or_options_free(mock_options); mock_options = NULL;
385 1 : connection_free_minimal(TO_CONN(conn));
386 1 : tor_free(header);
387 1 : tor_free(body);
388 1 : smartlist_free(list);
389 1 : microdesc_free_all();
390 1 : }
391 :
392 : static void
393 1 : test_dir_handle_get_micro_d_server_busy(void *data)
394 : {
395 1 : dir_connection_t *conn = NULL;
396 1 : microdesc_cache_t *mc = NULL ;
397 1 : smartlist_t *list = NULL;
398 1 : char digest[DIGEST256_LEN];
399 1 : char digest_base64[128];
400 1 : char path[80];
401 1 : char *header = NULL;
402 1 : (void) data;
403 :
404 1 : MOCK(get_options, mock_get_options);
405 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
406 :
407 : /* SETUP */
408 1 : init_mock_options();
409 :
410 : /* Add microdesc to cache */
411 1 : crypto_digest256(digest, microdesc, strlen(microdesc), DIGEST_SHA256);
412 1 : base64_encode_nopad(digest_base64, sizeof(digest_base64),
413 : (uint8_t *) digest, DIGEST256_LEN);
414 :
415 1 : mc = get_microdesc_cache();
416 1 : list = microdescs_add_to_cache(mc, microdesc, NULL, SAVED_NOWHERE, 0,
417 : time(NULL), NULL);
418 1 : tt_int_op(1, OP_EQ, smartlist_len(list));
419 :
420 : //Make it busy
421 1 : mock_options->CountPrivateBandwidth = 1;
422 :
423 : /* Make the request */
424 1 : conn = new_dir_conn();
425 :
426 1 : tor_snprintf(path, sizeof(path), MICRODESC_GET("%s"), digest_base64);
427 1 : tt_int_op(directory_handle_command_get(conn, path, NULL, 0), OP_EQ, 0);
428 :
429 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
430 : NULL, NULL, 1, 0);
431 :
432 1 : tt_str_op(SERVER_BUSY, OP_EQ, header);
433 :
434 1 : done:
435 1 : UNMOCK(get_options);
436 1 : UNMOCK(connection_write_to_buf_impl_);
437 :
438 1 : or_options_free(mock_options); mock_options = NULL;
439 1 : connection_free_minimal(TO_CONN(conn));
440 1 : tor_free(header);
441 1 : smartlist_free(list);
442 1 : microdesc_free_all();
443 1 : }
444 :
445 : #define BRIDGES_PATH "/tor/networkstatus-bridges"
446 : static void
447 1 : test_dir_handle_get_networkstatus_bridges_not_found_without_auth(void *data)
448 : {
449 1 : dir_connection_t *conn = NULL;
450 1 : char *header = NULL;
451 1 : (void) data;
452 :
453 1 : MOCK(get_options, mock_get_options);
454 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
455 :
456 : /* SETUP */
457 1 : init_mock_options();
458 1 : mock_options->BridgeAuthoritativeDir = 1;
459 1 : mock_options->BridgePassword_AuthDigest_ = tor_strdup("digest");
460 :
461 1 : conn = new_dir_conn();
462 1 : TO_CONN(conn)->linked = 1;
463 :
464 1 : const char *req = GET(BRIDGES_PATH);
465 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
466 :
467 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
468 : NULL, NULL, 1, 0);
469 :
470 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
471 :
472 1 : done:
473 1 : UNMOCK(get_options);
474 1 : UNMOCK(connection_write_to_buf_impl_);
475 1 : or_options_free(mock_options); mock_options = NULL;
476 1 : connection_free_minimal(TO_CONN(conn));
477 1 : tor_free(header);
478 1 : }
479 :
480 : static void
481 1 : test_dir_handle_get_networkstatus_bridges(void *data)
482 : {
483 1 : dir_connection_t *conn = NULL;
484 1 : char *header = NULL;
485 1 : (void) data;
486 :
487 1 : MOCK(get_options, mock_get_options);
488 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
489 :
490 : /* SETUP */
491 1 : init_mock_options();
492 1 : mock_options->BridgeAuthoritativeDir = 1;
493 1 : mock_options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN);
494 1 : crypto_digest256(mock_options->BridgePassword_AuthDigest_,
495 : "abcdefghijklm12345", 18, DIGEST_SHA256);
496 :
497 1 : conn = new_dir_conn();
498 1 : TO_CONN(conn)->linked = 1;
499 :
500 1 : const char *req = "GET " BRIDGES_PATH " HTTP/1.0\r\n"
501 : "Authorization: Basic abcdefghijklm12345\r\n\r\n";
502 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
503 :
504 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
505 : NULL, NULL, 1, 0);
506 :
507 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
508 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
509 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
510 1 : tt_assert(strstr(header, "Content-Length: 0\r\n"));
511 :
512 1 : done:
513 1 : UNMOCK(get_options);
514 1 : UNMOCK(connection_write_to_buf_impl_);
515 1 : or_options_free(mock_options); mock_options = NULL;
516 1 : connection_free_minimal(TO_CONN(conn));
517 1 : tor_free(header);
518 1 : }
519 :
520 : static void
521 1 : test_dir_handle_get_networkstatus_bridges_not_found_wrong_auth(void *data)
522 : {
523 1 : dir_connection_t *conn = NULL;
524 1 : char *header = NULL;
525 1 : (void) data;
526 :
527 1 : MOCK(get_options, mock_get_options);
528 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
529 :
530 : /* SETUP */
531 1 : init_mock_options();
532 1 : mock_options->BridgeAuthoritativeDir = 1;
533 1 : mock_options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN);
534 1 : crypto_digest256(mock_options->BridgePassword_AuthDigest_,
535 : "abcdefghijklm12345", 18, DIGEST_SHA256);
536 :
537 1 : conn = new_dir_conn();
538 1 : TO_CONN(conn)->linked = 1;
539 :
540 1 : const char *req = "GET " BRIDGES_PATH " HTTP/1.0\r\n"
541 : "Authorization: Basic NOTSAMEDIGEST\r\n\r\n";
542 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
543 :
544 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
545 : NULL, NULL, 1, 0);
546 :
547 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
548 :
549 1 : done:
550 1 : UNMOCK(get_options);
551 1 : UNMOCK(connection_write_to_buf_impl_);
552 1 : or_options_free(mock_options); mock_options = NULL;
553 1 : connection_free_minimal(TO_CONN(conn));
554 1 : tor_free(header);
555 1 : }
556 :
557 : #define SERVER_DESC_GET(id) GET("/tor/server/" id)
558 : static void
559 1 : test_dir_handle_get_server_descriptors_not_found(void* data)
560 : {
561 1 : dir_connection_t *conn = NULL;
562 1 : char *header = NULL;
563 1 : (void) data;
564 :
565 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
566 :
567 1 : conn = new_dir_conn();
568 :
569 1 : const char *req = SERVER_DESC_GET("invalid");
570 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
571 :
572 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
573 : NULL, NULL, 1, 0);
574 :
575 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
576 1 : tt_ptr_op(conn->spool, OP_EQ, NULL);
577 :
578 1 : done:
579 1 : UNMOCK(connection_write_to_buf_impl_);
580 1 : or_options_free(mock_options); mock_options = NULL;
581 1 : connection_free_minimal(TO_CONN(conn));
582 1 : tor_free(header);
583 1 : }
584 :
585 : static void
586 1 : test_dir_handle_get_server_descriptors_all(void* data)
587 : {
588 1 : dir_connection_t *conn = NULL;
589 1 : char *header = NULL;
590 1 : char *body = NULL;
591 1 : size_t body_used = 0;
592 1 : (void) data;
593 :
594 : /* Setup fake routerlist. */
595 1 : helper_setup_fake_routerlist();
596 :
597 : //TODO: change to router_get_my_extrainfo when testing "extra" path
598 1 : MOCK(router_get_my_routerinfo,
599 : dhg_tests_router_get_my_routerinfo);
600 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
601 :
602 : // We are one of the routers
603 1 : routerlist_t *our_routerlist = router_get_routerlist();
604 1 : tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
605 1 : mock_routerinfo = smartlist_get(our_routerlist->routers, 0);
606 1 : set_server_identity_key(mock_routerinfo->identity_pkey);
607 1 : mock_routerinfo->cache_info.published_on = time(NULL);
608 :
609 : /* Treat "all" requests as if they were unencrypted */
610 1 : mock_routerinfo->cache_info.send_unencrypted = 1;
611 :
612 1 : conn = new_dir_conn();
613 :
614 1 : const char *req = SERVER_DESC_GET("all");
615 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
616 :
617 : //TODO: Is this a BUG?
618 : //It requires strlen(signed_descriptor_len)+1 as body_len but returns a body
619 : //which is smaller than that by annotation_len bytes
620 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
621 : &body, &body_used,
622 : 1024*1024, 0);
623 :
624 1 : tt_assert(header);
625 1 : tt_assert(body);
626 :
627 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
628 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
629 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
630 :
631 : //TODO: Is this a BUG?
632 : //This is what should be expected: tt_int_op(body_used, OP_EQ, strlen(body));
633 1 : tt_int_op(body_used, OP_EQ,
634 : mock_routerinfo->cache_info.signed_descriptor_len);
635 :
636 1 : tt_str_op(body, OP_EQ, mock_routerinfo->cache_info.signed_descriptor_body +
637 : mock_routerinfo->cache_info.annotations_len);
638 1 : tt_ptr_op(conn->spool, OP_EQ, NULL);
639 :
640 1 : done:
641 1 : UNMOCK(router_get_my_routerinfo);
642 1 : UNMOCK(connection_write_to_buf_impl_);
643 1 : connection_free_minimal(TO_CONN(conn));
644 1 : tor_free(header);
645 1 : tor_free(body);
646 :
647 1 : routerlist_free_all();
648 1 : nodelist_free_all();
649 1 : entry_guards_free_all();
650 1 : }
651 :
652 : static char
653 : TEST_DESCRIPTOR[] =
654 : "@uploaded-at 2014-06-08 19:20:11\n"
655 : "@source \"127.0.0.1\"\n"
656 : "router test000a 127.0.0.1 5000 0 7000\n"
657 : "platform Tor 0.2.5.3-alpha-dev on Linux\n"
658 : "protocols Link 1 2 Circuit 1\n"
659 : "published 2014-06-08 19:20:11\n"
660 : "fingerprint C7E7 CCB8 179F 8CC3 7F5C 8A04 2B3A 180B 934B 14BA\n"
661 : "uptime 0\n"
662 : "bandwidth 1073741824 1073741824 0\n"
663 : "extra-info-digest 67A152A4C7686FB07664F872620635F194D76D95\n"
664 : "caches-extra-info\n"
665 : "onion-key\n"
666 : "-----BEGIN RSA PUBLIC KEY-----\n"
667 : "MIGJAoGBAOuBUIEBARMkkka/TGyaQNgUEDLP0KG7sy6KNQTNOlZHUresPr/vlVjo\n"
668 : "HPpLMfu9M2z18c51YX/muWwY9x4MyQooD56wI4+AqXQcJRwQfQlPn3Ay82uZViA9\n"
669 : "DpBajRieLlKKkl145KjArpD7F5BVsqccvjErgFYXvhhjSrx7BVLnAgMBAAE=\n"
670 : "-----END RSA PUBLIC KEY-----\n"
671 : "signing-key\n"
672 : "-----BEGIN RSA PUBLIC KEY-----\n"
673 : "MIGJAoGBAN6NLnSxWQnFXxqZi5D3b0BMgV6y9NJLGjYQVP+eWtPZWgqyv4zeYsqv\n"
674 : "O9y6c5lvxyUxmNHfoAbe/s8f2Vf3/YaC17asAVSln4ktrr3e9iY74a9RMWHv1Gzk\n"
675 : "3042nMcqj3PEhRN0PoLkcOZNjjmNbaqki6qy9bWWZDNTdo+uI44dAgMBAAE=\n"
676 : "-----END RSA PUBLIC KEY-----\n"
677 : "hidden-service-dir\n"
678 : "contact auth0@test.test\n"
679 : "ntor-onion-key pK4bs08ERYN591jj7ca17Rn9Q02TIEfhnjR6hSq+fhU=\n"
680 : "reject *:*\n"
681 : "router-signature\n"
682 : "-----BEGIN SIGNATURE-----\n"
683 : "rx88DuM3Y7tODlHNDDEVzKpwh3csaG1or+T4l2Xs1oq3iHHyPEtB6QTLYrC60trG\n"
684 : "aAPsj3DEowGfjga1b248g2dtic8Ab+0exfjMm1RHXfDam5TXXZU3A0wMyoHjqHuf\n"
685 : "eChGPgFNUvEc+5YtD27qEDcUjcinYztTs7/dzxBT4PE=\n"
686 : "-----END SIGNATURE-----\n";
687 :
688 : static void
689 1 : test_dir_handle_get_server_descriptors_authority(void* data)
690 : {
691 1 : dir_connection_t *conn = NULL;
692 1 : char *header = NULL;
693 1 : char *body = NULL;
694 1 : size_t body_used = 0;
695 1 : crypto_pk_t *identity_pkey = pk_generate(0);
696 1 : (void) data;
697 :
698 1 : MOCK(router_get_my_routerinfo,
699 : dhg_tests_router_get_my_routerinfo);
700 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
701 :
702 : /* init mock */
703 1 : router_get_my_routerinfo();
704 1 : crypto_pk_get_digest(identity_pkey,
705 1 : mock_routerinfo->cache_info.identity_digest);
706 :
707 : // the digest is mine (the channel is unnecrypted, so we must allow sending)
708 1 : set_server_identity_key(identity_pkey);
709 1 : mock_routerinfo->cache_info.send_unencrypted = 1;
710 :
711 : /* Setup descriptor */
712 1 : long annotation_len = strstr(TEST_DESCRIPTOR, "router ") - TEST_DESCRIPTOR;
713 2 : mock_routerinfo->cache_info.signed_descriptor_body =
714 1 : tor_strdup(TEST_DESCRIPTOR);
715 1 : mock_routerinfo->cache_info.signed_descriptor_len =
716 1 : strlen(TEST_DESCRIPTOR) - annotation_len;
717 1 : mock_routerinfo->cache_info.annotations_len = annotation_len;
718 1 : mock_routerinfo->cache_info.published_on = time(NULL);
719 :
720 1 : conn = new_dir_conn();
721 :
722 1 : const char *req = SERVER_DESC_GET("authority");
723 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
724 :
725 : //TODO: Is this a BUG?
726 : //It requires strlen(TEST_DESCRIPTOR)+1 as body_len but returns a body which
727 : //is smaller than that by annotation_len bytes
728 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
729 1 : &body, &body_used, strlen(TEST_DESCRIPTOR)+1, 0);
730 :
731 1 : tt_assert(header);
732 1 : tt_assert(body);
733 :
734 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
735 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
736 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
737 :
738 1 : tt_int_op(body_used, OP_EQ, strlen(body));
739 :
740 1 : tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
741 1 : tt_ptr_op(conn->spool, OP_EQ, NULL);
742 :
743 1 : done:
744 1 : UNMOCK(router_get_my_routerinfo);
745 1 : UNMOCK(connection_write_to_buf_impl_);
746 1 : tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
747 1 : tor_free(mock_routerinfo);
748 1 : connection_free_minimal(TO_CONN(conn));
749 1 : tor_free(header);
750 1 : tor_free(body);
751 1 : crypto_pk_free(identity_pkey);
752 1 : }
753 :
754 : static void
755 1 : test_dir_handle_get_server_descriptors_fp(void* data)
756 : {
757 1 : dir_connection_t *conn = NULL;
758 1 : char *header = NULL;
759 1 : char *body = NULL;
760 1 : size_t body_used = 0;
761 1 : crypto_pk_t *identity_pkey = pk_generate(0);
762 1 : (void) data;
763 :
764 1 : MOCK(router_get_my_routerinfo,
765 : dhg_tests_router_get_my_routerinfo);
766 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
767 :
768 : /* init mock */
769 1 : router_get_my_routerinfo();
770 1 : crypto_pk_get_digest(identity_pkey,
771 1 : mock_routerinfo->cache_info.identity_digest);
772 :
773 : // the digest is mine (the channel is unnecrypted, so we must allow sending)
774 1 : set_server_identity_key(identity_pkey);
775 1 : mock_routerinfo->cache_info.send_unencrypted = 1;
776 :
777 : /* Setup descriptor */
778 1 : long annotation_len = strstr(TEST_DESCRIPTOR, "router ") - TEST_DESCRIPTOR;
779 2 : mock_routerinfo->cache_info.signed_descriptor_body =
780 1 : tor_strdup(TEST_DESCRIPTOR);
781 1 : mock_routerinfo->cache_info.signed_descriptor_len =
782 1 : strlen(TEST_DESCRIPTOR) - annotation_len;
783 1 : mock_routerinfo->cache_info.annotations_len = annotation_len;
784 1 : mock_routerinfo->cache_info.published_on = time(NULL);
785 :
786 1 : conn = new_dir_conn();
787 :
788 : #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
789 : #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
790 1 : const char *hex_digest = hex_str(mock_routerinfo->cache_info.identity_digest,
791 : DIGEST_LEN);
792 :
793 1 : char req[155];
794 1 : tor_snprintf(req, sizeof(req), SERVER_DESC_GET("fp/%s+" HEX1 "+" HEX2),
795 : hex_digest);
796 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
797 :
798 : //TODO: Is this a BUG?
799 : //It requires strlen(TEST_DESCRIPTOR)+1 as body_len but returns a body which
800 : //is smaller than that by annotation_len bytes
801 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
802 1 : &body, &body_used, strlen(TEST_DESCRIPTOR)+1, 0);
803 :
804 1 : tt_assert(header);
805 1 : tt_assert(body);
806 :
807 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
808 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
809 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
810 :
811 1 : tt_int_op(body_used, OP_EQ, strlen(body));
812 :
813 1 : tt_str_op(body, OP_EQ, TEST_DESCRIPTOR + annotation_len);
814 1 : tt_ptr_op(conn->spool, OP_EQ, NULL);
815 :
816 1 : done:
817 1 : UNMOCK(router_get_my_routerinfo);
818 1 : UNMOCK(connection_write_to_buf_impl_);
819 1 : tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
820 1 : tor_free(mock_routerinfo);
821 1 : connection_free_minimal(TO_CONN(conn));
822 1 : tor_free(header);
823 1 : tor_free(body);
824 1 : crypto_pk_free(identity_pkey);
825 1 : }
826 :
827 : #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
828 : #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
829 :
830 : static void
831 1 : test_dir_handle_get_server_descriptors_d(void* data)
832 : {
833 1 : dir_connection_t *conn = NULL;
834 1 : char *header = NULL;
835 1 : char *body = NULL;
836 1 : size_t body_used = 0;
837 1 : crypto_pk_t *identity_pkey = pk_generate(0);
838 1 : (void) data;
839 :
840 : /* Setup fake routerlist. */
841 1 : helper_setup_fake_routerlist();
842 :
843 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
844 :
845 : /* Get one router's signed_descriptor_digest */
846 1 : routerlist_t *our_routerlist = router_get_routerlist();
847 1 : tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
848 1 : routerinfo_t *router = smartlist_get(our_routerlist->routers, 0);
849 1 : const char *hex_digest = hex_str(router->cache_info.signed_descriptor_digest,
850 : DIGEST_LEN);
851 :
852 1 : conn = new_dir_conn();
853 :
854 1 : char req_header[155]; /* XXX Why 155? What kind of number is that?? */
855 1 : tor_snprintf(req_header, sizeof(req_header),
856 : SERVER_DESC_GET("d/%s+" HEX1 "+" HEX2), hex_digest);
857 1 : tt_int_op(directory_handle_command_get(conn, req_header, NULL, 0), OP_EQ, 0);
858 :
859 : //TODO: Is this a BUG?
860 : //It requires strlen(signed_descriptor_len)+1 as body_len but returns a body
861 : //which is smaller than that by annotation_len bytes
862 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
863 : &body, &body_used,
864 1 : router->cache_info.signed_descriptor_len+1, 0);
865 :
866 1 : tt_assert(header);
867 1 : tt_assert(body);
868 :
869 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
870 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
871 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
872 :
873 : //TODO: Is this a BUG?
874 : //This is what should be expected:
875 : //tt_int_op(body_used, OP_EQ, strlen(body));
876 1 : tt_int_op(body_used, OP_EQ, router->cache_info.signed_descriptor_len);
877 :
878 1 : tt_str_op(body, OP_EQ, router->cache_info.signed_descriptor_body +
879 : router->cache_info.annotations_len);
880 1 : tt_ptr_op(conn->spool, OP_EQ, NULL);
881 :
882 1 : done:
883 1 : UNMOCK(connection_write_to_buf_impl_);
884 1 : tor_free(mock_routerinfo);
885 1 : connection_free_minimal(TO_CONN(conn));
886 1 : tor_free(header);
887 1 : tor_free(body);
888 1 : crypto_pk_free(identity_pkey);
889 :
890 1 : routerlist_free_all();
891 1 : nodelist_free_all();
892 1 : entry_guards_free_all();
893 1 : }
894 :
895 : static void
896 1 : test_dir_handle_get_server_descriptors_busy(void* data)
897 : {
898 1 : dir_connection_t *conn = NULL;
899 1 : char *header = NULL;
900 1 : crypto_pk_t *identity_pkey = pk_generate(0);
901 1 : (void) data;
902 :
903 : /* Setup fake routerlist. */
904 1 : helper_setup_fake_routerlist();
905 :
906 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
907 :
908 : //Make it busy
909 1 : MOCK(get_options, mock_get_options);
910 1 : init_mock_options();
911 1 : mock_options->CountPrivateBandwidth = 1;
912 :
913 : /* Get one router's signed_descriptor_digest */
914 1 : routerlist_t *our_routerlist = router_get_routerlist();
915 1 : tt_int_op(smartlist_len(our_routerlist->routers), OP_GE, 1);
916 1 : routerinfo_t *router = smartlist_get(our_routerlist->routers, 0);
917 1 : const char *hex_digest = hex_str(router->cache_info.signed_descriptor_digest,
918 : DIGEST_LEN);
919 :
920 1 : conn = new_dir_conn();
921 :
922 : #define HEX1 "Fe0daff89127389bc67558691231234551193EEE"
923 : #define HEX2 "Deadbeef99999991111119999911111111f00ba4"
924 1 : char req_header[155]; /* XXX 155? Why 155? */
925 1 : tor_snprintf(req_header, sizeof(req_header),
926 : SERVER_DESC_GET("d/%s+" HEX1 "+" HEX2), hex_digest);
927 1 : tt_int_op(directory_handle_command_get(conn, req_header, NULL, 0), OP_EQ, 0);
928 :
929 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
930 : NULL, NULL, 1, 0);
931 :
932 1 : tt_assert(header);
933 1 : tt_str_op(SERVER_BUSY, OP_EQ, header);
934 :
935 1 : tt_ptr_op(conn->spool, OP_EQ, NULL);
936 :
937 1 : done:
938 1 : UNMOCK(get_options);
939 1 : UNMOCK(connection_write_to_buf_impl_);
940 1 : tor_free(mock_routerinfo);
941 1 : connection_free_minimal(TO_CONN(conn));
942 1 : tor_free(header);
943 1 : crypto_pk_free(identity_pkey);
944 :
945 1 : routerlist_free_all();
946 1 : nodelist_free_all();
947 1 : entry_guards_free_all();
948 1 : }
949 :
950 : static void
951 1 : test_dir_handle_get_server_keys_bad_req(void* data)
952 : {
953 1 : dir_connection_t *conn = NULL;
954 1 : char *header = NULL;
955 1 : (void) data;
956 :
957 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
958 :
959 1 : conn = new_dir_conn();
960 :
961 1 : const char *req = GET("/tor/keys/");
962 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
963 :
964 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
965 : NULL, NULL, 1, 0);
966 :
967 1 : tt_assert(header);
968 1 : tt_str_op(BAD_REQUEST, OP_EQ, header);
969 :
970 1 : done:
971 1 : UNMOCK(connection_write_to_buf_impl_);
972 1 : connection_free_minimal(TO_CONN(conn));
973 1 : tor_free(header);
974 1 : }
975 :
976 : static void
977 1 : test_dir_handle_get_server_keys_all_not_found(void* data)
978 : {
979 1 : dir_connection_t *conn = NULL;
980 1 : char *header = NULL;
981 1 : (void) data;
982 :
983 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
984 :
985 1 : conn = new_dir_conn();
986 :
987 1 : const char *req = GET("/tor/keys/all");
988 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
989 :
990 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
991 : NULL, NULL, 1, 0);
992 :
993 1 : tt_assert(header);
994 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
995 :
996 1 : done:
997 1 : UNMOCK(connection_write_to_buf_impl_);
998 1 : connection_free_minimal(TO_CONN(conn));
999 1 : tor_free(header);
1000 1 : }
1001 :
1002 : #define TEST_CERTIFICATE AUTHORITY_CERT_3
1003 : #define TEST_SIGNING_KEY AUTHORITY_SIGNKEY_A_DIGEST
1004 :
1005 : static const char TEST_CERT_IDENT_KEY[] =
1006 : "D867ACF56A9D229B35C25F0090BC9867E906BE69";
1007 :
1008 : static void
1009 1 : test_dir_handle_get_server_keys_all(void* data)
1010 : {
1011 1 : dir_connection_t *conn = NULL;
1012 1 : char *header = NULL;
1013 1 : char *body = NULL;
1014 1 : size_t body_used = 0;
1015 1 : const char digest[DIGEST_LEN] = "";
1016 :
1017 1 : dir_server_t *ds = NULL;
1018 1 : (void) data;
1019 :
1020 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1021 :
1022 1 : clear_dir_servers();
1023 1 : routerlist_free_all();
1024 :
1025 : /* create a trusted ds */
1026 1 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
1027 : NULL, V3_DIRINFO, 1.0);
1028 1 : tt_assert(ds);
1029 1 : dir_server_add(ds);
1030 :
1031 : /* ds v3_identity_digest is the certificate's identity_key */
1032 1 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
1033 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
1034 1 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
1035 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
1036 :
1037 1 : conn = new_dir_conn();
1038 :
1039 1 : const char *req = GET("/tor/keys/all");
1040 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1041 :
1042 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1043 1 : &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
1044 :
1045 1 : tt_assert(header);
1046 1 : tt_assert(body);
1047 :
1048 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1049 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1050 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1051 1 : tt_assert(strstr(header, "Content-Length: 1883\r\n"));
1052 :
1053 1 : tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
1054 :
1055 1 : done:
1056 1 : UNMOCK(connection_write_to_buf_impl_);
1057 1 : connection_free_minimal(TO_CONN(conn));
1058 1 : tor_free(header);
1059 1 : tor_free(body);
1060 :
1061 1 : clear_dir_servers();
1062 1 : routerlist_free_all();
1063 1 : }
1064 :
1065 : static void
1066 1 : test_dir_handle_get_server_keys_authority_not_found(void* data)
1067 : {
1068 1 : dir_connection_t *conn = NULL;
1069 1 : char *header = NULL;
1070 1 : (void) data;
1071 :
1072 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1073 :
1074 1 : conn = new_dir_conn();
1075 :
1076 1 : const char *req = GET("/tor/keys/authority");
1077 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1078 :
1079 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1080 : NULL, NULL, 1, 0);
1081 :
1082 1 : tt_assert(header);
1083 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1084 :
1085 1 : done:
1086 1 : UNMOCK(connection_write_to_buf_impl_);
1087 1 : connection_free_minimal(TO_CONN(conn));
1088 1 : tor_free(header);
1089 1 : }
1090 :
1091 : static authority_cert_t * mock_cert = NULL;
1092 :
1093 : static authority_cert_t *
1094 8 : get_my_v3_authority_cert_m(void)
1095 : {
1096 8 : tor_assert(mock_cert);
1097 8 : return mock_cert;
1098 : }
1099 :
1100 : static void
1101 1 : test_dir_handle_get_server_keys_authority(void* data)
1102 : {
1103 1 : dir_connection_t *conn = NULL;
1104 1 : char *header = NULL;
1105 1 : char *body = NULL;
1106 1 : size_t body_used = 0;
1107 1 : (void) data;
1108 :
1109 1 : mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
1110 : strlen(TEST_CERTIFICATE),
1111 : NULL);
1112 :
1113 1 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
1114 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1115 :
1116 1 : conn = new_dir_conn();
1117 :
1118 1 : const char *req = GET("/tor/keys/authority");
1119 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1120 :
1121 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1122 1 : &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
1123 :
1124 1 : tt_assert(header);
1125 1 : tt_assert(body);
1126 :
1127 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1128 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1129 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1130 1 : tt_assert(strstr(header, "Content-Length: 1883\r\n"));
1131 :
1132 1 : tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
1133 :
1134 1 : done:
1135 1 : UNMOCK(get_my_v3_authority_cert);
1136 1 : UNMOCK(connection_write_to_buf_impl_);
1137 1 : connection_free_minimal(TO_CONN(conn));
1138 1 : tor_free(header);
1139 1 : tor_free(body);
1140 1 : authority_cert_free(mock_cert); mock_cert = NULL;
1141 1 : }
1142 :
1143 : static void
1144 1 : test_dir_handle_get_server_keys_fp_not_found(void* data)
1145 : {
1146 1 : dir_connection_t *conn = NULL;
1147 1 : char *header = NULL;
1148 1 : (void) data;
1149 :
1150 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1151 :
1152 1 : conn = new_dir_conn();
1153 :
1154 1 : const char *req = GET("/tor/keys/fp/somehex");
1155 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1156 :
1157 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1158 : NULL, NULL, 1, 0);
1159 :
1160 1 : tt_assert(header);
1161 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1162 :
1163 1 : done:
1164 1 : UNMOCK(connection_write_to_buf_impl_);
1165 1 : connection_free_minimal(TO_CONN(conn));
1166 1 : tor_free(header);
1167 1 : }
1168 :
1169 : static void
1170 1 : test_dir_handle_get_server_keys_fp(void* data)
1171 : {
1172 1 : dir_connection_t *conn = NULL;
1173 1 : char *header = NULL;
1174 1 : char *body = NULL;
1175 1 : size_t body_used = 0;
1176 1 : dir_server_t *ds = NULL;
1177 1 : const char digest[DIGEST_LEN] = "";
1178 1 : (void) data;
1179 :
1180 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1181 :
1182 1 : clear_dir_servers();
1183 1 : routerlist_free_all();
1184 :
1185 : /* create a trusted ds */
1186 1 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
1187 : NULL, V3_DIRINFO, 1.0);
1188 1 : tt_assert(ds);
1189 1 : dir_server_add(ds);
1190 :
1191 : /* ds v3_identity_digest is the certificate's identity_key */
1192 1 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
1193 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
1194 :
1195 1 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
1196 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
1197 :
1198 1 : conn = new_dir_conn();
1199 1 : char req[71];
1200 1 : tor_snprintf(req, sizeof(req),
1201 : GET("/tor/keys/fp/%s"), TEST_CERT_IDENT_KEY);
1202 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1203 :
1204 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1205 1 : &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
1206 :
1207 1 : tt_assert(header);
1208 1 : tt_assert(body);
1209 :
1210 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1211 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1212 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1213 1 : tt_assert(strstr(header, "Content-Length: 1883\r\n"));
1214 :
1215 1 : tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
1216 :
1217 1 : done:
1218 1 : UNMOCK(connection_write_to_buf_impl_);
1219 1 : connection_free_minimal(TO_CONN(conn));
1220 1 : tor_free(header);
1221 1 : tor_free(body);
1222 1 : clear_dir_servers();
1223 1 : routerlist_free_all();
1224 1 : }
1225 :
1226 : static void
1227 1 : test_dir_handle_get_server_keys_sk_not_found(void* data)
1228 : {
1229 1 : dir_connection_t *conn = NULL;
1230 1 : char *header = NULL;
1231 1 : (void) data;
1232 :
1233 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1234 :
1235 1 : conn = new_dir_conn();
1236 :
1237 1 : const char *req = GET("/tor/keys/sk/somehex");
1238 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1239 :
1240 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1241 : NULL, NULL, 1, 0);
1242 :
1243 1 : tt_assert(header);
1244 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1245 :
1246 1 : done:
1247 1 : UNMOCK(connection_write_to_buf_impl_);
1248 1 : connection_free_minimal(TO_CONN(conn));
1249 1 : tor_free(header);
1250 1 : }
1251 :
1252 : static void
1253 1 : test_dir_handle_get_server_keys_sk(void* data)
1254 : {
1255 1 : dir_connection_t *conn = NULL;
1256 1 : char *header = NULL;
1257 1 : char *body = NULL;
1258 1 : size_t body_used = 0;
1259 1 : (void) data;
1260 :
1261 1 : mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
1262 : strlen(TEST_CERTIFICATE),
1263 : NULL);
1264 1 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
1265 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1266 :
1267 1 : clear_dir_servers();
1268 1 : routerlist_free_all();
1269 :
1270 1 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
1271 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
1272 :
1273 1 : conn = new_dir_conn();
1274 1 : char req[71];
1275 1 : tor_snprintf(req, sizeof(req),
1276 : GET("/tor/keys/sk/%s"), TEST_SIGNING_KEY);
1277 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1278 :
1279 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1280 1 : &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
1281 :
1282 1 : tt_assert(header);
1283 1 : tt_assert(body);
1284 :
1285 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1286 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1287 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1288 1 : tt_assert(strstr(header, "Content-Length: 1883\r\n"));
1289 :
1290 1 : tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
1291 :
1292 1 : done:
1293 1 : UNMOCK(get_my_v3_authority_cert);
1294 1 : UNMOCK(connection_write_to_buf_impl_);
1295 1 : connection_free_minimal(TO_CONN(conn));
1296 1 : authority_cert_free(mock_cert); mock_cert = NULL;
1297 1 : tor_free(header);
1298 1 : tor_free(body);
1299 1 : }
1300 :
1301 : static void
1302 1 : test_dir_handle_get_server_keys_fpsk_not_found(void* data)
1303 : {
1304 1 : dir_connection_t *conn = NULL;
1305 1 : char *header = NULL;
1306 1 : (void) data;
1307 :
1308 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1309 :
1310 1 : conn = new_dir_conn();
1311 :
1312 1 : const char *req = GET("/tor/keys/fp-sk/somehex");
1313 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1314 :
1315 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1316 : NULL, NULL, 1, 0);
1317 :
1318 1 : tt_assert(header);
1319 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1320 :
1321 1 : done:
1322 1 : UNMOCK(connection_write_to_buf_impl_);
1323 1 : connection_free_minimal(TO_CONN(conn));
1324 1 : tor_free(header);
1325 1 : }
1326 :
1327 : static void
1328 1 : test_dir_handle_get_server_keys_fpsk(void* data)
1329 : {
1330 1 : dir_connection_t *conn = NULL;
1331 1 : char *header = NULL;
1332 1 : char *body = NULL;
1333 1 : size_t body_used = 0;
1334 1 : dir_server_t *ds = NULL;
1335 1 : const char digest[DIGEST_LEN] = "";
1336 1 : (void) data;
1337 :
1338 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1339 :
1340 1 : clear_dir_servers();
1341 1 : routerlist_free_all();
1342 :
1343 : /* create a trusted ds */
1344 1 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
1345 : NULL, V3_DIRINFO, 1.0);
1346 1 : tt_assert(ds);
1347 :
1348 : /* ds v3_identity_digest is the certificate's identity_key */
1349 1 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
1350 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
1351 1 : dir_server_add(ds);
1352 :
1353 1 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
1354 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
1355 :
1356 1 : conn = new_dir_conn();
1357 :
1358 1 : char req[115];
1359 1 : tor_snprintf(req, sizeof(req),
1360 : GET("/tor/keys/fp-sk/%s-%s"),
1361 : TEST_CERT_IDENT_KEY, TEST_SIGNING_KEY);
1362 :
1363 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1364 :
1365 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1366 1 : &body, &body_used, strlen(TEST_CERTIFICATE)+1, 0);
1367 :
1368 1 : tt_assert(header);
1369 1 : tt_assert(body);
1370 :
1371 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1372 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1373 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1374 1 : tt_assert(strstr(header, "Content-Length: 1883\r\n"));
1375 :
1376 1 : tt_str_op(TEST_CERTIFICATE, OP_EQ, body);
1377 :
1378 1 : done:
1379 1 : UNMOCK(connection_write_to_buf_impl_);
1380 1 : connection_free_minimal(TO_CONN(conn));
1381 1 : tor_free(header);
1382 1 : tor_free(body);
1383 :
1384 1 : clear_dir_servers();
1385 1 : routerlist_free_all();
1386 1 : }
1387 :
1388 : static void
1389 1 : test_dir_handle_get_server_keys_busy(void* data)
1390 : {
1391 1 : dir_connection_t *conn = NULL;
1392 1 : char *header = NULL;
1393 1 : dir_server_t *ds = NULL;
1394 1 : const char digest[DIGEST_LEN] = "";
1395 1 : (void) data;
1396 :
1397 1 : clear_dir_servers();
1398 1 : routerlist_free_all();
1399 :
1400 : /* create a trusted ds */
1401 1 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
1402 : NULL, V3_DIRINFO, 1.0);
1403 1 : tt_assert(ds);
1404 :
1405 : /* ds v3_identity_digest is the certificate's identity_key */
1406 1 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
1407 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
1408 1 : dir_server_add(ds);
1409 :
1410 1 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
1411 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
1412 :
1413 1 : MOCK(get_options, mock_get_options);
1414 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1415 :
1416 : /* setup busy server */
1417 1 : init_mock_options();
1418 1 : mock_options->CountPrivateBandwidth = 1;
1419 :
1420 1 : conn = new_dir_conn();
1421 1 : char req[71];
1422 1 : tor_snprintf(req, sizeof(req), GET("/tor/keys/fp/%s"), TEST_CERT_IDENT_KEY);
1423 1 : tt_int_op(directory_handle_command_get(conn, req, NULL, 0), OP_EQ, 0);
1424 :
1425 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1426 : NULL, NULL, 1, 0);
1427 :
1428 1 : tt_assert(header);
1429 1 : tt_str_op(SERVER_BUSY, OP_EQ, header);
1430 :
1431 1 : done:
1432 1 : UNMOCK(get_options);
1433 1 : UNMOCK(connection_write_to_buf_impl_);
1434 1 : connection_free_minimal(TO_CONN(conn));
1435 1 : tor_free(header);
1436 1 : or_options_free(mock_options); mock_options = NULL;
1437 :
1438 1 : clear_dir_servers();
1439 1 : routerlist_free_all();
1440 1 : }
1441 :
1442 : static networkstatus_t *mock_ns_val = NULL;
1443 : static networkstatus_t *
1444 0 : mock_ns_get_by_flavor(consensus_flavor_t f)
1445 : {
1446 0 : (void)f;
1447 0 : return mock_ns_val;
1448 : }
1449 :
1450 : static void
1451 1 : test_dir_handle_get_status_vote_current_consensus_ns_not_enough_sigs(void* d)
1452 : {
1453 1 : dir_connection_t *conn = NULL;
1454 1 : char *header = NULL;
1455 1 : char *stats = NULL;
1456 1 : (void) d;
1457 :
1458 : /* init mock */
1459 1 : mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
1460 1 : mock_ns_val->flavor = FLAV_NS;
1461 1 : mock_ns_val->type = NS_TYPE_CONSENSUS;
1462 1 : mock_ns_val->voters = smartlist_new();
1463 1 : mock_ns_val->valid_after = time(NULL) - 1800;
1464 1 : mock_ns_val->valid_until = time(NULL) - 60;
1465 :
1466 : #define NETWORK_STATUS "some network status string"
1467 1 : consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
1468 :
1469 : /* init mock */
1470 1 : init_mock_options();
1471 :
1472 1 : MOCK(get_options, mock_get_options);
1473 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1474 1 : MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
1475 :
1476 : /* start gathering stats */
1477 1 : mock_options->DirReqStatistics = 1;
1478 1 : geoip_dirreq_stats_init(time(NULL));
1479 :
1480 1 : conn = new_dir_conn();
1481 :
1482 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1483 : GET("/tor/status-vote/current/consensus-ns/" HEX1 "+" HEX2), NULL, 0));
1484 :
1485 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1486 : NULL, NULL, 1, 0);
1487 :
1488 1 : tt_assert(header);
1489 1 : tt_str_op(NOT_ENOUGH_CONSENSUS_SIGNATURES, OP_EQ, header);
1490 :
1491 1 : stats = geoip_format_dirreq_stats(time(NULL));
1492 1 : tt_assert(stats);
1493 1 : tt_assert(strstr(stats, "not-enough-sigs=8"));
1494 :
1495 1 : done:
1496 1 : UNMOCK(networkstatus_get_latest_consensus_by_flavor);
1497 1 : UNMOCK(connection_write_to_buf_impl_);
1498 1 : UNMOCK(get_options);
1499 :
1500 1 : connection_free_minimal(TO_CONN(conn));
1501 1 : tor_free(header);
1502 1 : tor_free(stats);
1503 1 : smartlist_free(mock_ns_val->voters);
1504 1 : tor_free(mock_ns_val);
1505 1 : or_options_free(mock_options); mock_options = NULL;
1506 1 : }
1507 :
1508 : static void
1509 1 : test_dir_handle_get_status_vote_current_consensus_ns_not_found(void* data)
1510 : {
1511 1 : dir_connection_t *conn = NULL;
1512 1 : char *header = NULL;
1513 1 : char *stats = NULL;
1514 1 : (void) data;
1515 :
1516 1 : init_mock_options();
1517 :
1518 1 : MOCK(get_options, mock_get_options);
1519 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1520 :
1521 : /* start gathering stats */
1522 1 : mock_options->DirReqStatistics = 1;
1523 1 : geoip_dirreq_stats_init(time(NULL));
1524 :
1525 1 : conn = new_dir_conn();
1526 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1527 : GET("/tor/status-vote/current/consensus-ns"), NULL, 0));
1528 :
1529 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1530 : NULL, NULL, 1, 0);
1531 1 : tt_assert(header);
1532 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1533 :
1534 1 : stats = geoip_format_dirreq_stats(time(NULL));
1535 1 : tt_assert(stats);
1536 1 : tt_assert(strstr(stats, "not-found=8"));
1537 :
1538 1 : done:
1539 1 : UNMOCK(connection_write_to_buf_impl_);
1540 1 : UNMOCK(get_options);
1541 1 : connection_free_minimal(TO_CONN(conn));
1542 1 : tor_free(header);
1543 1 : tor_free(stats);
1544 1 : or_options_free(mock_options); mock_options = NULL;
1545 1 : }
1546 :
1547 : static void
1548 1 : test_dir_handle_get_status_vote_current_consensus_too_old(void *data)
1549 : {
1550 1 : dir_connection_t *conn = NULL;
1551 1 : char *header = NULL;
1552 1 : (void)data;
1553 :
1554 1 : mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
1555 1 : mock_ns_val->type = NS_TYPE_CONSENSUS;
1556 1 : mock_ns_val->flavor = FLAV_MICRODESC;
1557 1 : mock_ns_val->valid_after = time(NULL) - (24 * 60 * 60 + 1800);
1558 1 : mock_ns_val->fresh_until = time(NULL) - (24 * 60 * 60 + 900);
1559 1 : mock_ns_val->valid_until = time(NULL) - (24 * 60 * 60 + 20);
1560 :
1561 : #define NETWORK_STATUS "some network status string"
1562 1 : consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
1563 :
1564 1 : init_mock_options();
1565 :
1566 1 : MOCK(get_options, mock_get_options);
1567 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1568 1 : MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
1569 :
1570 1 : conn = new_dir_conn();
1571 :
1572 1 : setup_capture_of_logs(LOG_WARN);
1573 :
1574 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1575 : GET("/tor/status-vote/current/consensus-microdesc"), NULL, 0));
1576 :
1577 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1578 : NULL, NULL, 1, 0);
1579 1 : tt_assert(header);
1580 1 : tt_str_op(TOO_OLD, OP_EQ, header);
1581 :
1582 1 : expect_log_msg_containing("too old");
1583 :
1584 1 : tor_free(header);
1585 1 : teardown_capture_of_logs();
1586 1 : tor_free(mock_ns_val);
1587 :
1588 1 : mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
1589 1 : mock_ns_val->type = NS_TYPE_CONSENSUS;
1590 1 : mock_ns_val->flavor = FLAV_NS;
1591 1 : mock_ns_val->valid_after = time(NULL) - (24 * 60 * 60 + 1800);
1592 1 : mock_ns_val->fresh_until = time(NULL) - (24 * 60 * 60 + 900);
1593 1 : mock_ns_val->valid_until = time(NULL) - (24 * 60 * 60 + 20);
1594 :
1595 : #define NETWORK_STATUS "some network status string"
1596 1 : consdiffmgr_add_consensus(NETWORK_STATUS, mock_ns_val);
1597 :
1598 1 : setup_capture_of_logs(LOG_WARN);
1599 :
1600 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1601 : GET("/tor/status-vote/current/consensus"), NULL, 0));
1602 :
1603 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1604 : NULL, NULL, 1, 0);
1605 1 : tt_assert(header);
1606 1 : tt_str_op(TOO_OLD, OP_EQ, header);
1607 :
1608 1 : expect_no_log_entry();
1609 :
1610 1 : done:
1611 1 : teardown_capture_of_logs();
1612 1 : UNMOCK(networkstatus_get_latest_consensus_by_flavor);
1613 1 : UNMOCK(connection_write_to_buf_impl_);
1614 1 : UNMOCK(get_options);
1615 1 : connection_free_minimal(TO_CONN(conn));
1616 1 : tor_free(header);
1617 1 : tor_free(mock_ns_val);
1618 1 : or_options_free(mock_options); mock_options = NULL;
1619 1 : }
1620 :
1621 : static int dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr);
1622 : ATTR_UNUSED static int dhg_tests_geoip_get_country_by_addr_called = 0;
1623 :
1624 : int
1625 2 : dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr)
1626 : {
1627 2 : (void)addr;
1628 2 : dhg_tests_geoip_get_country_by_addr_called++;
1629 2 : return 1;
1630 : }
1631 :
1632 : static void
1633 2 : status_vote_current_consensus_ns_test(char **header, char **body,
1634 : size_t *body_len)
1635 : {
1636 2 : dir_connection_t *conn = NULL;
1637 :
1638 : #define NETWORK_STATUS "some network status string"
1639 : #if 0
1640 : common_digests_t digests;
1641 : uint8_t sha3[DIGEST256_LEN];
1642 : memset(&digests, 0x60, sizeof(digests));
1643 : memset(sha3, 0x06, sizeof(sha3));
1644 : dirserv_set_cached_consensus_networkstatus(NETWORK_STATUS, "ns", &digests,
1645 : sha3,
1646 : time(NULL));
1647 : #endif /* 0 */
1648 2 : networkstatus_t *ns = tor_malloc_zero(sizeof(networkstatus_t));
1649 2 : ns->type = NS_TYPE_CONSENSUS;
1650 2 : ns->flavor = FLAV_NS;
1651 2 : ns->valid_after = time(NULL) - 1800;
1652 2 : ns->fresh_until = time(NULL) - 900;
1653 2 : ns->valid_until = time(NULL) - 60;
1654 2 : consdiffmgr_add_consensus(NETWORK_STATUS, ns);
1655 2 : networkstatus_vote_free(ns);
1656 :
1657 2 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1658 :
1659 2 : tt_assert(mock_options);
1660 2 : mock_options->DirReqStatistics = 1;
1661 2 : geoip_dirreq_stats_init(time(NULL));
1662 :
1663 : /* init geoip database */
1664 2 : geoip_parse_entry("10,50,AB", AF_INET);
1665 2 : tt_str_op("ab", OP_EQ, geoip_get_country_name(1));
1666 :
1667 2 : conn = new_dir_conn();
1668 :
1669 2 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1670 : GET("/tor/status-vote/current/consensus-ns"), NULL, 0));
1671 :
1672 2 : fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
1673 : body, body_len, strlen(NETWORK_STATUS)+7, 0);
1674 :
1675 2 : done:
1676 2 : UNMOCK(connection_write_to_buf_impl_);
1677 2 : connection_free_minimal(TO_CONN(conn));
1678 2 : }
1679 :
1680 : static void
1681 1 : test_dir_handle_get_status_vote_current_consensus_ns(void* data)
1682 : {
1683 1 : char *header = NULL;
1684 1 : char *body = NULL, *comp_body = NULL;
1685 1 : size_t body_used = 0, comp_body_used = 0;
1686 1 : char *stats = NULL, *hist = NULL;
1687 1 : (void) data;
1688 :
1689 1 : dirserv_free_all();
1690 1 : clear_geoip_db();
1691 :
1692 1 : MOCK(geoip_get_country_by_addr,
1693 : dhg_tests_geoip_get_country_by_addr);
1694 1 : MOCK(get_options, mock_get_options);
1695 :
1696 1 : init_mock_options();
1697 :
1698 1 : status_vote_current_consensus_ns_test(&header, &comp_body, &comp_body_used);
1699 1 : tt_assert(header);
1700 :
1701 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1702 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1703 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1704 1 : tt_assert(strstr(header, "Pragma: no-cache\r\n"));
1705 :
1706 1 : compress_method_t compression = detect_compression_method(comp_body,
1707 : comp_body_used);
1708 1 : tt_int_op(ZLIB_METHOD, OP_EQ, compression);
1709 :
1710 1 : tor_uncompress(&body, &body_used, comp_body, comp_body_used,
1711 : compression, 0, LOG_PROTOCOL_WARN);
1712 :
1713 1 : tt_str_op(NETWORK_STATUS, OP_EQ, body);
1714 1 : tt_int_op(strlen(NETWORK_STATUS), OP_EQ, body_used);
1715 :
1716 1 : stats = geoip_format_dirreq_stats(time(NULL));
1717 1 : tt_assert(stats);
1718 :
1719 1 : tt_assert(strstr(stats, "ok=8"));
1720 1 : tt_assert(strstr(stats, "dirreq-v3-ips ab=8"));
1721 1 : tt_assert(strstr(stats, "dirreq-v3-reqs ab=8"));
1722 1 : tt_assert(strstr(stats, "dirreq-v3-direct-dl"
1723 : " complete=0,timeout=0,running=4"));
1724 :
1725 1 : hist = geoip_get_request_history();
1726 1 : tt_assert(hist);
1727 1 : tt_str_op("ab=8", OP_EQ, hist);
1728 :
1729 1 : done:
1730 1 : UNMOCK(geoip_get_country_by_addr);
1731 1 : UNMOCK(get_options);
1732 1 : tor_free(header);
1733 1 : tor_free(comp_body);
1734 1 : tor_free(body);
1735 1 : tor_free(stats);
1736 1 : tor_free(hist);
1737 1 : or_options_free(mock_options); mock_options = NULL;
1738 :
1739 1 : dirserv_free_all();
1740 1 : clear_geoip_db();
1741 1 : }
1742 :
1743 : static void
1744 1 : test_dir_handle_get_status_vote_current_consensus_ns_busy(void* data)
1745 : {
1746 1 : char *header = NULL;
1747 1 : char *body = NULL;
1748 1 : size_t body_used = 0;
1749 1 : char *stats = NULL;
1750 1 : (void) data;
1751 :
1752 1 : dirserv_free_all();
1753 1 : clear_geoip_db();
1754 :
1755 1 : MOCK(get_options, mock_get_options);
1756 :
1757 : // Make it busy
1758 1 : init_mock_options();
1759 1 : mock_options->CountPrivateBandwidth = 1;
1760 :
1761 1 : status_vote_current_consensus_ns_test(&header, &body, &body_used);
1762 1 : tt_assert(header);
1763 :
1764 1 : tt_str_op(SERVER_BUSY, OP_EQ, header);
1765 :
1766 1 : stats = geoip_format_dirreq_stats(time(NULL));
1767 1 : tt_assert(stats);
1768 1 : tt_assert(strstr(stats, "busy=8"));
1769 :
1770 1 : done:
1771 1 : UNMOCK(get_options);
1772 1 : tor_free(header);
1773 1 : tor_free(body);
1774 1 : or_options_free(mock_options); mock_options = NULL;
1775 :
1776 1 : tor_free(stats);
1777 1 : dirserv_free_all();
1778 1 : clear_geoip_db();
1779 1 : }
1780 :
1781 : static void
1782 1 : test_dir_handle_get_status_vote_current_not_found(void* data)
1783 : {
1784 1 : dir_connection_t *conn = NULL;
1785 1 : char *header = NULL;
1786 1 : (void) data;
1787 :
1788 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1789 :
1790 1 : conn = new_dir_conn();
1791 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1792 : GET("/tor/status-vote/current/" HEX1), NULL, 0));
1793 :
1794 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1795 : NULL, NULL, 1, 0);
1796 1 : tt_assert(header);
1797 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1798 :
1799 1 : done:
1800 1 : UNMOCK(connection_write_to_buf_impl_);
1801 1 : connection_free_minimal(TO_CONN(conn));
1802 1 : tor_free(header);
1803 1 : }
1804 :
1805 : /* What vote do we ask for, to get the vote in vote_descriptors.inc ? */
1806 : #define VOTE_DIGEST "78400095d8e834d87135cfc46235c909f0e99911"
1807 :
1808 : static void
1809 2 : status_vote_current_d_test(char **header, char **body, size_t *body_l)
1810 : {
1811 2 : dir_connection_t *conn = NULL;
1812 :
1813 2 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1814 :
1815 2 : conn = new_dir_conn();
1816 2 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1817 : GET("/tor/status-vote/current/d/" VOTE_DIGEST), NULL, 0));
1818 :
1819 2 : fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
1820 2 : body, body_l, strlen(VOTE_BODY_V3)+1, 0);
1821 2 : tt_assert(header);
1822 :
1823 2 : done:
1824 2 : UNMOCK(connection_write_to_buf_impl_);
1825 2 : connection_free_minimal(TO_CONN(conn));
1826 2 : }
1827 :
1828 : static void
1829 2 : status_vote_next_d_test(char **header, char **body, size_t *body_l)
1830 : {
1831 2 : dir_connection_t *conn = NULL;
1832 :
1833 2 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1834 :
1835 2 : conn = new_dir_conn();
1836 2 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1837 : GET("/tor/status-vote/next/d/" VOTE_DIGEST), NULL, 0));
1838 :
1839 2 : fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
1840 2 : body, body_l, strlen(VOTE_BODY_V3)+1, 0);
1841 2 : tt_assert(header);
1842 :
1843 2 : done:
1844 2 : UNMOCK(connection_write_to_buf_impl_);
1845 2 : connection_free_minimal(TO_CONN(conn));
1846 2 : }
1847 :
1848 : static void
1849 1 : test_dir_handle_get_status_vote_current_d_not_found(void* data)
1850 : {
1851 1 : char *header = NULL;
1852 1 : (void) data;
1853 :
1854 1 : status_vote_current_d_test(&header, NULL, NULL);
1855 :
1856 1 : tt_assert(header);
1857 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1858 :
1859 1 : done:
1860 1 : tor_free(header);
1861 1 : }
1862 :
1863 : static void
1864 1 : test_dir_handle_get_status_vote_next_d_not_found(void* data)
1865 : {
1866 1 : char *header = NULL;
1867 1 : (void) data;
1868 :
1869 1 : status_vote_next_d_test(&header, NULL, NULL);
1870 :
1871 1 : tt_assert(header);
1872 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1873 :
1874 1 : done:
1875 1 : UNMOCK(connection_write_to_buf_impl_);
1876 1 : tor_free(header);
1877 1 : }
1878 :
1879 : static void
1880 1 : test_dir_handle_get_status_vote_d(void* data)
1881 : {
1882 1 : char *header = NULL, *body = NULL;
1883 1 : size_t body_used = 0;
1884 1 : dir_server_t *ds = NULL;
1885 1 : const char digest[DIGEST_LEN] = "";
1886 1 : (void) data;
1887 :
1888 1 : MOCK(check_signature_token, mock_ignore_signature_token);
1889 1 : clear_dir_servers();
1890 1 : dirvote_free_all();
1891 :
1892 : /* create a trusted ds */
1893 1 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
1894 : NULL, V3_DIRINFO, 1.0);
1895 1 : tt_assert(ds);
1896 1 : dir_server_add(ds);
1897 :
1898 : /* ds v3_identity_digest is the certificate's identity_key */
1899 1 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
1900 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
1901 :
1902 1 : init_mock_options();
1903 1 : mock_options->AuthoritativeDir = 1;
1904 1 : mock_options->V3AuthoritativeDir = 1;
1905 1 : mock_options->TestingV3AuthVotingStartOffset = 0;
1906 1 : mock_options->TestingV3AuthInitialVotingInterval = 1;
1907 1 : mock_options->TestingV3AuthInitialVoteDelay = 1;
1908 1 : mock_options->TestingV3AuthInitialDistDelay = 1;
1909 :
1910 1 : time_t now = 1441223455 -1;
1911 1 : dirauth_sched_recalculate_timing(mock_options, now);
1912 :
1913 1 : const char *msg_out = NULL;
1914 1 : int status_out = 0;
1915 1 : struct pending_vote_t *pv = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
1916 : &msg_out, &status_out);
1917 1 : tt_assert(pv);
1918 :
1919 1 : status_vote_current_d_test(&header, &body, &body_used);
1920 :
1921 1 : tt_assert(header);
1922 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1923 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1924 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1925 1 : tt_assert(strstr(header, "Content-Length: 4403\r\n"));
1926 :
1927 1 : tt_str_op(VOTE_BODY_V3, OP_EQ, body);
1928 :
1929 1 : tor_free(header);
1930 1 : tor_free(body);
1931 :
1932 1 : status_vote_next_d_test(&header, &body, &body_used);
1933 :
1934 1 : tt_assert(header);
1935 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
1936 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
1937 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
1938 1 : tt_assert(strstr(header, "Content-Length: 4403\r\n"));
1939 :
1940 1 : tt_str_op(VOTE_BODY_V3, OP_EQ, body);
1941 :
1942 1 : done:
1943 1 : UNMOCK(check_signature_token);
1944 1 : tor_free(header);
1945 1 : tor_free(body);
1946 1 : or_options_free(mock_options); mock_options = NULL;
1947 :
1948 1 : clear_dir_servers();
1949 1 : dirvote_free_all();
1950 1 : routerlist_free_all();
1951 1 : }
1952 :
1953 : static void
1954 1 : test_dir_handle_get_status_vote_next_not_found(void* data)
1955 : {
1956 1 : dir_connection_t *conn = NULL;
1957 1 : char *header = NULL;
1958 1 : (void) data;
1959 :
1960 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1961 :
1962 1 : conn = new_dir_conn();
1963 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1964 : GET("/tor/status-vote/next/" HEX1), NULL, 0));
1965 :
1966 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
1967 : NULL, NULL, 1, 0);
1968 1 : tt_assert(header);
1969 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
1970 :
1971 1 : done:
1972 1 : UNMOCK(connection_write_to_buf_impl_);
1973 1 : connection_free_minimal(TO_CONN(conn));
1974 1 : tor_free(header);
1975 1 : }
1976 :
1977 : static void
1978 3 : status_vote_next_consensus_test(char **header, char **body, size_t *body_used)
1979 : {
1980 3 : dir_connection_t *conn = NULL;
1981 :
1982 3 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
1983 :
1984 3 : conn = new_dir_conn();
1985 3 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
1986 : GET("/tor/status-vote/next/consensus"), NULL, 0));
1987 :
1988 3 : fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
1989 : body, body_used, 18, 0);
1990 3 : done:
1991 3 : UNMOCK(connection_write_to_buf_impl_);
1992 3 : connection_free_minimal(TO_CONN(conn));
1993 3 : }
1994 :
1995 : static void
1996 1 : test_dir_handle_get_status_vote_next_consensus_not_found(void* data)
1997 : {
1998 1 : char *header = NULL, *body = NULL;
1999 1 : size_t body_used;
2000 1 : (void) data;
2001 :
2002 1 : status_vote_next_consensus_test(&header, &body, &body_used);
2003 :
2004 1 : tt_assert(header);
2005 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
2006 :
2007 1 : done:
2008 1 : tor_free(header);
2009 1 : tor_free(body);
2010 1 : }
2011 :
2012 : static void
2013 1 : test_dir_handle_get_status_vote_current_authority_not_found(void* data)
2014 : {
2015 1 : dir_connection_t *conn = NULL;
2016 1 : char *header = NULL;
2017 1 : (void) data;
2018 :
2019 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2020 1 : MOCK(check_signature_token, mock_ignore_signature_token);
2021 :
2022 1 : conn = new_dir_conn();
2023 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2024 : GET("/tor/status-vote/current/authority"), NULL, 0));
2025 :
2026 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2027 : NULL, NULL, 1, 0);
2028 1 : tt_assert(header);
2029 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
2030 :
2031 1 : done:
2032 1 : UNMOCK(check_signature_token);
2033 1 : UNMOCK(connection_write_to_buf_impl_);
2034 1 : connection_free_minimal(TO_CONN(conn));
2035 1 : tor_free(header);
2036 1 : }
2037 :
2038 : static void
2039 1 : test_dir_handle_get_status_vote_next_authority_not_found(void* data)
2040 : {
2041 1 : dir_connection_t *conn = NULL;
2042 1 : char *header = NULL;
2043 1 : (void) data;
2044 :
2045 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2046 1 : MOCK(check_signature_token, mock_ignore_signature_token);
2047 :
2048 1 : conn = new_dir_conn();
2049 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2050 : GET("/tor/status-vote/next/authority"), NULL, 0));
2051 :
2052 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2053 : NULL, NULL, 1, 0);
2054 1 : tt_assert(header);
2055 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
2056 :
2057 1 : done:
2058 1 : UNMOCK(check_signature_token);
2059 1 : UNMOCK(connection_write_to_buf_impl_);
2060 1 : connection_free_minimal(TO_CONN(conn));
2061 1 : tor_free(header);
2062 1 : }
2063 :
2064 : static void
2065 1 : test_dir_handle_get_status_vote_next_bandwidth_not_found(void* data)
2066 : {
2067 1 : dir_connection_t *conn = NULL;
2068 1 : char *header = NULL;
2069 1 : (void) data;
2070 :
2071 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2072 1 : MOCK(check_signature_token, mock_ignore_signature_token);
2073 1 : conn = new_dir_conn();
2074 :
2075 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2076 : GET("/tor/status-vote/next/bandwdith"), NULL, 0));
2077 :
2078 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2079 : NULL, NULL, 1, 0);
2080 1 : tt_assert(header);
2081 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
2082 :
2083 1 : done:
2084 1 : UNMOCK(check_signature_token);
2085 1 : UNMOCK(connection_write_to_buf_impl_);
2086 1 : connection_free_minimal(TO_CONN(conn));
2087 1 : tor_free(header);
2088 1 : }
2089 :
2090 : static const char* dhg_tests_dirvote_get_pending_consensus(
2091 : consensus_flavor_t flav);
2092 :
2093 : const char*
2094 2 : dhg_tests_dirvote_get_pending_consensus(consensus_flavor_t flav)
2095 : {
2096 2 : (void)flav;
2097 2 : return "pending consensus";
2098 : }
2099 :
2100 : static void
2101 1 : test_dir_handle_get_status_vote_next_consensus(void* data)
2102 : {
2103 1 : char *header = NULL, *body = NULL;
2104 1 : size_t body_used = 0;
2105 1 : (void) data;
2106 :
2107 1 : MOCK(dirvote_get_pending_consensus,
2108 : dhg_tests_dirvote_get_pending_consensus);
2109 :
2110 1 : status_vote_next_consensus_test(&header, &body, &body_used);
2111 1 : tt_assert(header);
2112 :
2113 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
2114 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
2115 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
2116 1 : tt_assert(strstr(header, "Content-Length: 17\r\n"));
2117 :
2118 1 : tt_str_op("pending consensus", OP_EQ, body);
2119 :
2120 1 : done:
2121 1 : UNMOCK(dirvote_get_pending_consensus);
2122 1 : tor_free(header);
2123 1 : tor_free(body);
2124 1 : }
2125 :
2126 : static void
2127 1 : test_dir_handle_get_status_vote_next_consensus_busy(void* data)
2128 : {
2129 1 : char *header = NULL, *body = NULL;
2130 1 : size_t body_used = 0;
2131 1 : (void) data;
2132 :
2133 1 : MOCK(get_options, mock_get_options);
2134 1 : MOCK(dirvote_get_pending_consensus,
2135 : dhg_tests_dirvote_get_pending_consensus);
2136 :
2137 : //Make it busy
2138 1 : init_mock_options();
2139 1 : mock_options->CountPrivateBandwidth = 1;
2140 :
2141 1 : status_vote_next_consensus_test(&header, &body, &body_used);
2142 :
2143 1 : tt_assert(header);
2144 1 : tt_str_op(SERVER_BUSY, OP_EQ, header);
2145 :
2146 1 : done:
2147 1 : UNMOCK(dirvote_get_pending_consensus);
2148 1 : UNMOCK(get_options);
2149 1 : tor_free(header);
2150 1 : tor_free(body);
2151 1 : or_options_free(mock_options); mock_options = NULL;
2152 1 : }
2153 :
2154 : static void
2155 3 : status_vote_next_consensus_signatures_test(char **header, char **body,
2156 : size_t *body_used)
2157 : {
2158 3 : dir_connection_t *conn = NULL;
2159 :
2160 3 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2161 :
2162 3 : conn = new_dir_conn();
2163 3 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2164 : GET("/tor/status-vote/next/consensus-signatures"), NULL, 0));
2165 :
2166 3 : fetch_from_buf_http(TO_CONN(conn)->outbuf, header, MAX_HEADERS_SIZE,
2167 : body, body_used, 22, 0);
2168 :
2169 3 : done:
2170 3 : connection_free_minimal(TO_CONN(conn));
2171 3 : UNMOCK(connection_write_to_buf_impl_);
2172 3 : }
2173 :
2174 : static void
2175 1 : test_dir_handle_get_status_vote_next_consensus_signatures_not_found(void* data)
2176 : {
2177 1 : char *header = NULL, *body = NULL;
2178 1 : size_t body_used;
2179 1 : (void) data;
2180 :
2181 1 : status_vote_next_consensus_signatures_test(&header, &body, &body_used);
2182 :
2183 1 : tt_assert(header);
2184 1 : tt_str_op(NOT_FOUND, OP_EQ, header);
2185 :
2186 1 : done:
2187 1 : tor_free(header);
2188 1 : tor_free(body);
2189 1 : }
2190 :
2191 : static const char* dhg_tests_dirvote_get_pending_detached_signatures(void);
2192 :
2193 : const char*
2194 2 : dhg_tests_dirvote_get_pending_detached_signatures(void)
2195 : {
2196 2 : return "pending detached sigs";
2197 : }
2198 :
2199 : static void
2200 1 : test_dir_handle_get_status_vote_next_consensus_signatures(void* data)
2201 : {
2202 1 : char *header = NULL, *body = NULL;
2203 1 : size_t body_used = 0;
2204 1 : (void) data;
2205 :
2206 1 : MOCK(dirvote_get_pending_detached_signatures,
2207 : dhg_tests_dirvote_get_pending_detached_signatures);
2208 :
2209 1 : status_vote_next_consensus_signatures_test(&header, &body, &body_used);
2210 1 : tt_assert(header);
2211 :
2212 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
2213 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
2214 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
2215 1 : tt_assert(strstr(header, "Content-Length: 21\r\n"));
2216 :
2217 1 : tt_str_op("pending detached sigs", OP_EQ, body);
2218 :
2219 1 : done:
2220 1 : UNMOCK(dirvote_get_pending_detached_signatures);
2221 1 : tor_free(header);
2222 1 : tor_free(body);
2223 1 : }
2224 :
2225 : static void
2226 1 : test_dir_handle_get_status_vote_next_consensus_signatures_busy(void* data)
2227 : {
2228 1 : char *header = NULL, *body = NULL;
2229 1 : size_t body_used;
2230 1 : (void) data;
2231 :
2232 1 : MOCK(dirvote_get_pending_detached_signatures,
2233 : dhg_tests_dirvote_get_pending_detached_signatures);
2234 1 : MOCK(get_options, mock_get_options);
2235 :
2236 : //Make it busy
2237 1 : init_mock_options();
2238 1 : mock_options->CountPrivateBandwidth = 1;
2239 :
2240 1 : status_vote_next_consensus_signatures_test(&header, &body, &body_used);
2241 :
2242 1 : tt_assert(header);
2243 1 : tt_str_op(SERVER_BUSY, OP_EQ, header);
2244 :
2245 1 : done:
2246 1 : UNMOCK(get_options);
2247 1 : UNMOCK(dirvote_get_pending_detached_signatures);
2248 1 : tor_free(header);
2249 1 : tor_free(body);
2250 1 : or_options_free(mock_options); mock_options = NULL;
2251 1 : }
2252 :
2253 : static void
2254 1 : test_dir_handle_get_status_vote_next_authority(void* data)
2255 : {
2256 1 : dir_connection_t *conn = NULL;
2257 1 : char *header = NULL, *body = NULL;
2258 1 : const char *msg_out = NULL;
2259 1 : int status_out = 0;
2260 1 : size_t body_used = 0;
2261 1 : dir_server_t *ds = NULL;
2262 1 : const char digest[DIGEST_LEN] = "";
2263 1 : (void) data;
2264 :
2265 1 : MOCK(check_signature_token, mock_ignore_signature_token);
2266 1 : clear_dir_servers();
2267 1 : routerlist_free_all();
2268 1 : dirvote_free_all();
2269 :
2270 1 : mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
2271 : strlen(TEST_CERTIFICATE),
2272 : NULL);
2273 :
2274 : /* create a trusted ds */
2275 1 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
2276 : NULL, V3_DIRINFO, 1.0);
2277 1 : tt_assert(ds);
2278 1 : dir_server_add(ds);
2279 :
2280 : /* ds v3_identity_digest is the certificate's identity_key */
2281 1 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
2282 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
2283 1 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
2284 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
2285 :
2286 1 : init_mock_options();
2287 1 : mock_options->AuthoritativeDir = 1;
2288 1 : mock_options->V3AuthoritativeDir = 1;
2289 1 : mock_options->TestingV3AuthVotingStartOffset = 0;
2290 1 : mock_options->TestingV3AuthInitialVotingInterval = 1;
2291 1 : mock_options->TestingV3AuthInitialVoteDelay = 1;
2292 1 : mock_options->TestingV3AuthInitialDistDelay = 1;
2293 :
2294 1 : time_t now = 1441223455 -1;
2295 1 : dirauth_sched_recalculate_timing(mock_options, now);
2296 :
2297 1 : struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
2298 : &msg_out, &status_out);
2299 1 : tt_assert(vote);
2300 :
2301 1 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
2302 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2303 :
2304 1 : conn = new_dir_conn();
2305 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2306 : GET("/tor/status-vote/next/authority"), NULL, 0));
2307 :
2308 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2309 1 : &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
2310 :
2311 1 : tt_assert(header);
2312 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
2313 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
2314 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
2315 1 : tt_assert(strstr(header, "Content-Length: 4403\r\n"));
2316 :
2317 1 : tt_str_op(VOTE_BODY_V3, OP_EQ, body);
2318 :
2319 1 : done:
2320 1 : UNMOCK(check_signature_token);
2321 1 : UNMOCK(connection_write_to_buf_impl_);
2322 1 : UNMOCK(get_my_v3_authority_cert);
2323 1 : connection_free_minimal(TO_CONN(conn));
2324 1 : tor_free(header);
2325 1 : tor_free(body);
2326 1 : authority_cert_free(mock_cert); mock_cert = NULL;
2327 1 : or_options_free(mock_options); mock_options = NULL;
2328 :
2329 1 : clear_dir_servers();
2330 1 : routerlist_free_all();
2331 1 : dirvote_free_all();
2332 1 : }
2333 :
2334 : static void
2335 1 : test_dir_handle_get_status_vote_next_bandwidth(void* data)
2336 : {
2337 1 : dir_connection_t *conn = NULL;
2338 1 : char *header = NULL, *body = NULL;
2339 1 : size_t body_used = 0;
2340 1 : (void) data;
2341 :
2342 1 : const char *content =
2343 : "1541171221\n"
2344 : "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 "
2345 : "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ "
2346 : "bw=760 nick=Test time=2018-05-08T16:13:26\n";
2347 :
2348 1 : init_mock_options();
2349 1 : MOCK(get_options, mock_get_options);
2350 1 : mock_options->V3BandwidthsFile = tor_strdup(
2351 : get_fname_rnd("V3BandwidthsFile")
2352 : );
2353 :
2354 1 : write_str_to_file(mock_options->V3BandwidthsFile, content, 0);
2355 :
2356 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2357 :
2358 1 : conn = new_dir_conn();
2359 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2360 : GET("/tor/status-vote/next/bandwidth"), NULL, 0));
2361 :
2362 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2363 : &body, &body_used, strlen(content)+1, 0);
2364 :
2365 1 : tt_assert(header);
2366 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
2367 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
2368 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
2369 1 : tt_assert(strstr(header, "Content-Length: 167\r\n"));
2370 :
2371 : /* Check cache lifetime */
2372 1 : char expbuf[RFC1123_TIME_LEN+1];
2373 1 : time_t now = approx_time();
2374 : /* BANDWIDTH_CACHE_LIFETIME is defined in dircache.c. */
2375 1 : format_rfc1123_time(expbuf, (time_t)(now + 30*60));
2376 1 : char *expires = NULL;
2377 : /* Change to 'Cache-control: max-age=%d' if using http/1.1. */
2378 1 : tor_asprintf(&expires, "Expires: %s\r\n", expbuf);
2379 1 : tt_assert(strstr(header, expires));
2380 :
2381 1 : tt_int_op(body_used, OP_EQ, strlen(body));
2382 1 : tt_str_op(content, OP_EQ, body);
2383 :
2384 1 : tor_free(header);
2385 1 : tor_free(body);
2386 :
2387 : /* Request the file using compression, the result should be the same. */
2388 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2389 : GET("/tor/status-vote/next/bandwidth.z"), NULL, 0));
2390 :
2391 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2392 : &body, &body_used, strlen(content)+1, 0);
2393 :
2394 1 : tt_assert(header);
2395 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
2396 1 : tt_assert(strstr(header, "Content-Encoding: deflate\r\n"));
2397 :
2398 : /* Since using connection_write_to_buf_mock instead of mocking
2399 : * connection_buf_add_compress, the content is not actually compressed.
2400 : * If it would, the size and content would be different than the original.
2401 : */
2402 :
2403 1 : done:
2404 1 : UNMOCK(get_options);
2405 1 : UNMOCK(connection_write_to_buf_impl_);
2406 1 : connection_free_minimal(TO_CONN(conn));
2407 1 : tor_free(header);
2408 1 : tor_free(body);
2409 1 : tor_free(expires);
2410 1 : or_options_free(mock_options);
2411 1 : }
2412 :
2413 : static void
2414 1 : test_dir_handle_get_status_vote_current_authority(void* data)
2415 : {
2416 1 : dir_connection_t *conn = NULL;
2417 1 : char *header = NULL, *body = NULL;
2418 1 : const char *msg_out = NULL;
2419 1 : int status_out = 0;
2420 1 : size_t body_used = 0;
2421 1 : const char digest[DIGEST_LEN] = "";
2422 :
2423 1 : dir_server_t *ds = NULL;
2424 1 : (void) data;
2425 :
2426 1 : MOCK(check_signature_token, mock_ignore_signature_token);
2427 1 : clear_dir_servers();
2428 1 : routerlist_free_all();
2429 1 : dirvote_free_all();
2430 :
2431 1 : mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
2432 : strlen(TEST_CERTIFICATE),
2433 : NULL);
2434 :
2435 : /* create a trusted ds */
2436 1 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
2437 : NULL, V3_DIRINFO, 1.0);
2438 1 : tt_assert(ds);
2439 1 : dir_server_add(ds);
2440 :
2441 : /* ds v3_identity_digest is the certificate's identity_key */
2442 1 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
2443 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
2444 :
2445 1 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
2446 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
2447 :
2448 1 : init_mock_options();
2449 1 : mock_options->AuthoritativeDir = 1;
2450 1 : mock_options->V3AuthoritativeDir = 1;
2451 1 : mock_options->TestingV3AuthVotingStartOffset = 0;
2452 1 : mock_options->TestingV3AuthInitialVotingInterval = 1;
2453 1 : mock_options->TestingV3AuthInitialVoteDelay = 1;
2454 1 : mock_options->TestingV3AuthInitialDistDelay = 1;
2455 :
2456 1 : time_t now = 1441223455;
2457 1 : dirauth_sched_recalculate_timing(mock_options, now-1);
2458 :
2459 1 : struct pending_vote_t *vote = dirvote_add_vote(VOTE_BODY_V3, 0, "foo",
2460 : &msg_out, &status_out);
2461 1 : tt_assert(vote);
2462 :
2463 : // move the pending vote to previous vote
2464 1 : dirvote_act(mock_options, now+1);
2465 :
2466 1 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
2467 1 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2468 :
2469 1 : conn = new_dir_conn();
2470 1 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2471 : GET("/tor/status-vote/current/authority"), NULL, 0));
2472 :
2473 1 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2474 1 : &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
2475 :
2476 1 : tt_assert(header);
2477 1 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
2478 1 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
2479 1 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
2480 1 : tt_assert(strstr(header, "Content-Length: 4403\r\n"));
2481 :
2482 1 : tt_str_op(VOTE_BODY_V3, OP_EQ, body);
2483 :
2484 1 : done:
2485 1 : UNMOCK(check_signature_token);
2486 1 : UNMOCK(connection_write_to_buf_impl_);
2487 1 : UNMOCK(get_my_v3_authority_cert);
2488 1 : connection_free_minimal(TO_CONN(conn));
2489 1 : tor_free(header);
2490 1 : tor_free(body);
2491 1 : authority_cert_free(mock_cert); mock_cert = NULL;
2492 1 : or_options_free(mock_options); mock_options = NULL;
2493 :
2494 1 : clear_dir_servers();
2495 1 : routerlist_free_all();
2496 1 : dirvote_free_all();
2497 1 : }
2498 :
2499 : /* Test that a late vote is rejected, but an on-time vote is accepted. */
2500 : static void
2501 4 : test_dir_handle_get_status_vote_too_late(void* data)
2502 : {
2503 4 : dir_connection_t *conn = NULL;
2504 4 : char *header = NULL, *body = NULL;
2505 4 : const char *msg_out = NULL;
2506 4 : int status_out = 0;
2507 4 : size_t body_used = 0;
2508 4 : const char digest[DIGEST_LEN] = "";
2509 :
2510 4 : dir_server_t *ds = NULL;
2511 4 : const char* mode = (const char *)data;
2512 :
2513 4 : MOCK(check_signature_token, mock_ignore_signature_token);
2514 4 : clear_dir_servers();
2515 4 : routerlist_free_all();
2516 4 : dirvote_free_all();
2517 :
2518 4 : mock_cert = authority_cert_parse_from_string(TEST_CERTIFICATE,
2519 : strlen(TEST_CERTIFICATE),
2520 : NULL);
2521 :
2522 : /* create a trusted ds */
2523 4 : ds = trusted_dir_server_new("ds", "127.0.0.1", 9059, 9060, NULL, digest,
2524 : NULL, V3_DIRINFO, 1.0);
2525 4 : tt_assert(ds);
2526 4 : dir_server_add(ds);
2527 :
2528 : /* ds v3_identity_digest is the certificate's identity_key */
2529 4 : base16_decode(ds->v3_identity_digest, DIGEST_LEN,
2530 : TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
2531 :
2532 4 : tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
2533 : TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
2534 :
2535 4 : init_mock_options();
2536 4 : mock_options->AuthoritativeDir = 1;
2537 4 : mock_options->V3AuthoritativeDir = 1;
2538 :
2539 4 : int base_delay = 0;
2540 4 : int vote_interval = 0;
2541 4 : int start_offset = 0;
2542 :
2543 4 : tt_assert(mode);
2544 : /* Set the required timings, see below for details */
2545 4 : if (strcmp(mode, "min") == 0) {
2546 : /* The minimum valid test network timing */
2547 : base_delay = 2;
2548 : vote_interval = 10;
2549 : start_offset = vote_interval - 5;
2550 3 : } else if (strcmp(mode, "chutney") == 0) {
2551 : /* The test network timing used by chutney */
2552 : base_delay = 4;
2553 : vote_interval = 20;
2554 : start_offset = vote_interval - 5;
2555 2 : } else if (strcmp(mode, "half-public") == 0) {
2556 : /* The short consensus failure timing used in the public network */
2557 : base_delay = 5*60;
2558 : vote_interval = 30*60;
2559 : start_offset = vote_interval - 9*60 - 5;
2560 1 : } else if (strcmp(mode, "public") == 0) {
2561 : /* The standard timing used in the public network */
2562 1 : base_delay = 5*60;
2563 1 : vote_interval = 60*60;
2564 1 : start_offset = vote_interval - 9*60 - 5;
2565 : }
2566 :
2567 4 : tt_assert(base_delay > 0);
2568 4 : tt_assert(vote_interval > 0);
2569 4 : tt_assert(start_offset > 0);
2570 :
2571 : /* Skew the time to fit the fixed time in the vote */
2572 4 : mock_options->TestingV3AuthVotingStartOffset = start_offset;
2573 : /* Calculate the rest of the timings */
2574 4 : mock_options->TestingV3AuthInitialVotingInterval = vote_interval;
2575 4 : mock_options->TestingV3AuthInitialVoteDelay = base_delay;
2576 4 : mock_options->TestingV3AuthInitialDistDelay = base_delay;
2577 :
2578 4 : time_t now = 1441223455;
2579 4 : dirauth_sched_recalculate_timing(mock_options, now-1);
2580 4 : const time_t voting_starts = voting_schedule.voting_starts;
2581 4 : const time_t fetch_missing = voting_schedule.fetch_missing_votes;
2582 :
2583 4 : struct pending_vote_t *vote = NULL;
2584 :
2585 : /* Next voting interval */
2586 4 : vote = dirvote_add_vote(VOTE_BODY_V3,
2587 : fetch_missing + vote_interval, "foo",
2588 : &msg_out, &status_out);
2589 4 : tt_assert(!vote);
2590 4 : tt_int_op(status_out, OP_EQ, 400);
2591 4 : tt_str_op(msg_out, OP_EQ,
2592 : "Posted vote received too late, would be dangerous to count it");
2593 :
2594 : /* Just after fetch missing */
2595 4 : vote = dirvote_add_vote(VOTE_BODY_V3,
2596 : fetch_missing + 1, "foo",
2597 : &msg_out, &status_out);
2598 4 : tt_assert(!vote);
2599 4 : tt_int_op(status_out, OP_EQ, 400);
2600 4 : tt_str_op(msg_out, OP_EQ,
2601 : "Posted vote received too late, would be dangerous to count it");
2602 :
2603 : /* On fetch missing */
2604 4 : vote = dirvote_add_vote(VOTE_BODY_V3,
2605 : fetch_missing, "foo",
2606 : &msg_out, &status_out);
2607 4 : tt_assert(vote);
2608 :
2609 : /* Move the pending vote to previous vote */
2610 4 : dirvote_act(mock_options, now+1);
2611 : /* And reset the timing */
2612 4 : dirauth_sched_recalculate_timing(mock_options, now-1);
2613 :
2614 : /* Between voting starts and fetch missing */
2615 4 : vote = dirvote_add_vote(VOTE_BODY_V3,
2616 : voting_starts + 1, "foo",
2617 : &msg_out, &status_out);
2618 4 : tt_assert(vote);
2619 :
2620 : /* Move the pending vote to previous vote */
2621 4 : dirvote_act(mock_options, now+1);
2622 : /* And reset the timing */
2623 4 : dirauth_sched_recalculate_timing(mock_options, now-1);
2624 :
2625 : /* On voting starts */
2626 4 : vote = dirvote_add_vote(VOTE_BODY_V3,
2627 : voting_starts, "foo",
2628 : &msg_out, &status_out);
2629 4 : tt_assert(vote);
2630 :
2631 : /* Move the pending vote to previous vote */
2632 4 : dirvote_act(mock_options, now+1);
2633 : /* And reset the timing */
2634 4 : dirauth_sched_recalculate_timing(mock_options, now-1);
2635 :
2636 : /* Just before voting starts */
2637 4 : vote = dirvote_add_vote(VOTE_BODY_V3,
2638 : voting_starts - 1, "foo",
2639 : &msg_out, &status_out);
2640 4 : tt_assert(vote);
2641 :
2642 : /* Move the pending vote to previous vote */
2643 4 : dirvote_act(mock_options, now+1);
2644 :
2645 4 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
2646 4 : MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
2647 :
2648 4 : conn = new_dir_conn();
2649 4 : tt_int_op(0, OP_EQ, directory_handle_command_get(conn,
2650 : GET("/tor/status-vote/current/authority"), NULL, 0));
2651 :
2652 4 : fetch_from_buf_http(TO_CONN(conn)->outbuf, &header, MAX_HEADERS_SIZE,
2653 4 : &body, &body_used, strlen(VOTE_BODY_V3)+1, 0);
2654 :
2655 4 : tt_assert(header);
2656 4 : tt_ptr_op(strstr(header, "HTTP/1.0 200 OK\r\n"), OP_EQ, header);
2657 4 : tt_assert(strstr(header, "Content-Type: text/plain\r\n"));
2658 4 : tt_assert(strstr(header, "Content-Encoding: identity\r\n"));
2659 4 : tt_assert(strstr(header, "Content-Length: 4403\r\n"));
2660 :
2661 4 : tt_str_op(VOTE_BODY_V3, OP_EQ, body);
2662 :
2663 4 : done:
2664 4 : UNMOCK(check_signature_token);
2665 4 : UNMOCK(connection_write_to_buf_impl_);
2666 4 : UNMOCK(get_my_v3_authority_cert);
2667 4 : connection_free_minimal(TO_CONN(conn));
2668 4 : tor_free(header);
2669 4 : tor_free(body);
2670 4 : authority_cert_free(mock_cert); mock_cert = NULL;
2671 4 : or_options_free(mock_options); mock_options = NULL;
2672 :
2673 4 : clear_dir_servers();
2674 4 : routerlist_free_all();
2675 4 : dirvote_free_all();
2676 4 : }
2677 :
2678 : static void
2679 1 : test_dir_handle_get_parse_accept_encoding(void *arg)
2680 : {
2681 1 : (void)arg;
2682 1 : const unsigned B_NONE = 1u << NO_METHOD;
2683 1 : const unsigned B_ZLIB = 1u << ZLIB_METHOD;
2684 1 : const unsigned B_GZIP = 1u << GZIP_METHOD;
2685 1 : const unsigned B_LZMA = 1u << LZMA_METHOD;
2686 1 : const unsigned B_ZSTD = 1u << ZSTD_METHOD;
2687 :
2688 1 : unsigned encodings;
2689 :
2690 1 : encodings = parse_accept_encoding_header("");
2691 1 : tt_uint_op(B_NONE, OP_EQ, encodings);
2692 :
2693 1 : encodings = parse_accept_encoding_header(" ");
2694 1 : tt_uint_op(B_NONE, OP_EQ, encodings);
2695 :
2696 1 : encodings = parse_accept_encoding_header("dewey, cheatham, and howe ");
2697 1 : tt_uint_op(B_NONE, OP_EQ, encodings);
2698 :
2699 1 : encodings = parse_accept_encoding_header("dewey, cheatham, and gzip");
2700 1 : tt_uint_op(B_NONE, OP_EQ, encodings);
2701 :
2702 1 : encodings = parse_accept_encoding_header("dewey, cheatham, and, gzip");
2703 1 : tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
2704 :
2705 1 : encodings = parse_accept_encoding_header(" gzip");
2706 1 : tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
2707 :
2708 1 : encodings = parse_accept_encoding_header("gzip");
2709 1 : tt_uint_op(B_NONE|B_GZIP, OP_EQ, encodings);
2710 :
2711 1 : encodings = parse_accept_encoding_header("x-zstd, deflate, x-tor-lzma");
2712 1 : tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA, OP_EQ, encodings);
2713 :
2714 1 : encodings = parse_accept_encoding_header(
2715 : "x-zstd, deflate, x-tor-lzma, gzip");
2716 1 : tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA|B_GZIP, OP_EQ, encodings);
2717 :
2718 1 : encodings = parse_accept_encoding_header("x-zstd,deflate,x-tor-lzma,gzip");
2719 1 : tt_uint_op(B_NONE|B_ZLIB|B_ZSTD|B_LZMA|B_GZIP, OP_EQ, encodings);
2720 :
2721 1 : done:
2722 1 : ;
2723 1 : }
2724 :
2725 : #define DIR_HANDLE_CMD(name,flags) \
2726 : { #name, test_dir_handle_get_##name, (flags), NULL, NULL }
2727 :
2728 : #ifdef COCCI
2729 : /* Coccinelle doesn't like the stringification in this macro */
2730 : #define DIR_HANDLE_CMD_ARG(name,flags,arg) \
2731 : DIR_HANDLE_CMD(name,flags)
2732 : #else
2733 : #define DIR_HANDLE_CMD_ARG(name,flags,arg) \
2734 : { #name "/" arg, test_dir_handle_get_##name, (flags), \
2735 : &passthrough_setup, (void *)(arg) }
2736 : #endif /* defined(COCCI) */
2737 :
2738 : struct testcase_t dir_handle_get_tests[] = {
2739 : DIR_HANDLE_CMD(not_found, 0),
2740 : DIR_HANDLE_CMD(bad_request, 0),
2741 : DIR_HANDLE_CMD(v1_command_not_found, 0),
2742 : DIR_HANDLE_CMD(v1_command, 0),
2743 : DIR_HANDLE_CMD(robots_txt, 0),
2744 : DIR_HANDLE_CMD(micro_d_not_found, 0),
2745 : DIR_HANDLE_CMD(micro_d_server_busy, 0),
2746 : DIR_HANDLE_CMD(micro_d, 0),
2747 : DIR_HANDLE_CMD(networkstatus_bridges_not_found_without_auth, 0),
2748 : DIR_HANDLE_CMD(networkstatus_bridges_not_found_wrong_auth, 0),
2749 : DIR_HANDLE_CMD(networkstatus_bridges, 0),
2750 : DIR_HANDLE_CMD(server_descriptors_not_found, 0),
2751 : DIR_HANDLE_CMD(server_descriptors_busy, TT_FORK),
2752 : DIR_HANDLE_CMD(server_descriptors_all, TT_FORK),
2753 : DIR_HANDLE_CMD(server_descriptors_authority, TT_FORK),
2754 : DIR_HANDLE_CMD(server_descriptors_fp, TT_FORK),
2755 : DIR_HANDLE_CMD(server_descriptors_d, TT_FORK),
2756 : DIR_HANDLE_CMD(server_keys_bad_req, 0),
2757 : DIR_HANDLE_CMD(server_keys_busy, 0),
2758 : DIR_HANDLE_CMD(server_keys_all_not_found, 0),
2759 : DIR_HANDLE_CMD(server_keys_all, 0),
2760 : DIR_HANDLE_CMD(server_keys_authority_not_found, 0),
2761 : DIR_HANDLE_CMD(server_keys_authority, 0),
2762 : DIR_HANDLE_CMD(server_keys_fp_not_found, 0),
2763 : DIR_HANDLE_CMD(server_keys_fp, 0),
2764 : DIR_HANDLE_CMD(server_keys_sk_not_found, 0),
2765 : DIR_HANDLE_CMD(server_keys_sk, 0),
2766 : DIR_HANDLE_CMD(server_keys_fpsk_not_found, 0),
2767 : DIR_HANDLE_CMD(server_keys_fpsk, 0),
2768 : DIR_HANDLE_CMD(status_vote_current_not_found, 0),
2769 : DIR_HANDLE_CMD(status_vote_next_not_found, 0),
2770 : DIR_HANDLE_CMD(status_vote_current_authority_not_found, 0),
2771 : DIR_HANDLE_CMD(status_vote_current_authority, 0),
2772 : DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "min"),
2773 : DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "chutney"),
2774 : DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "half-public"),
2775 : DIR_HANDLE_CMD_ARG(status_vote_too_late, 0, "public"),
2776 : DIR_HANDLE_CMD(status_vote_next_authority_not_found, 0),
2777 : DIR_HANDLE_CMD(status_vote_next_authority, 0),
2778 : DIR_HANDLE_CMD(status_vote_next_bandwidth_not_found, 0),
2779 : DIR_HANDLE_CMD(status_vote_next_bandwidth, 0),
2780 : DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_enough_sigs, TT_FORK),
2781 : DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_found, TT_FORK),
2782 : DIR_HANDLE_CMD(status_vote_current_consensus_too_old, TT_FORK),
2783 : DIR_HANDLE_CMD(status_vote_current_consensus_ns_busy, TT_FORK),
2784 : DIR_HANDLE_CMD(status_vote_current_consensus_ns, TT_FORK),
2785 : DIR_HANDLE_CMD(status_vote_current_d_not_found, 0),
2786 : DIR_HANDLE_CMD(status_vote_next_d_not_found, 0),
2787 : DIR_HANDLE_CMD(status_vote_d, 0),
2788 : DIR_HANDLE_CMD(status_vote_next_consensus_not_found, 0),
2789 : DIR_HANDLE_CMD(status_vote_next_consensus_busy, 0),
2790 : DIR_HANDLE_CMD(status_vote_next_consensus, 0),
2791 : DIR_HANDLE_CMD(status_vote_next_consensus_signatures_not_found, 0),
2792 : DIR_HANDLE_CMD(status_vote_next_consensus_signatures_busy, 0),
2793 : DIR_HANDLE_CMD(status_vote_next_consensus_signatures, 0),
2794 : DIR_HANDLE_CMD(parse_accept_encoding, 0),
2795 : END_OF_TESTCASES
2796 : };
|