Line data Source code
1 : /* Copyright (c) 2016-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : /**
5 : * \file test_hs_config.c
6 : * \brief Test hidden service configuration functionality.
7 : */
8 :
9 : #define CONFIG_PRIVATE
10 : #define HS_SERVICE_PRIVATE
11 :
12 : #include "test/test.h"
13 : #include "test/test_helpers.h"
14 : #include "test/log_test_helpers.h"
15 : #include "test/resolve_test_helpers.h"
16 :
17 : #include "app/config/config.h"
18 : #include "feature/hs/hs_common.h"
19 : #include "feature/hs/hs_config.h"
20 : #include "feature/hs/hs_service.h"
21 :
22 : static int
23 21 : helper_config_service(const char *conf, int validate_only)
24 : {
25 21 : int ret = 0;
26 21 : or_options_t *options = NULL;
27 21 : tt_assert(conf);
28 21 : options = helper_parse_options(conf);
29 21 : tt_assert(options);
30 21 : ret = hs_config_service_all(options, validate_only);
31 21 : done:
32 21 : or_options_free(options);
33 21 : return ret;
34 : }
35 :
36 : static void
37 1 : test_invalid_service(void *arg)
38 : {
39 1 : int ret;
40 :
41 1 : (void) arg;
42 :
43 : /* Try with a missing port configuration. */
44 : {
45 1 : const char *conf =
46 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
47 : "HiddenServiceVersion 1\n"; /* Wrong not supported version. */
48 1 : setup_full_capture_of_logs(LOG_WARN);
49 1 : ret = helper_config_service(conf, 1);
50 1 : tt_int_op(ret, OP_EQ, -1);
51 1 : expect_log_msg_containing("HiddenServiceVersion must be between 3 and 3");
52 1 : teardown_capture_of_logs();
53 : }
54 :
55 : /* Bad value of HiddenServiceAllowUnknownPorts. */
56 : {
57 1 : const char *conf =
58 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
59 : "HiddenServiceVersion 3\n"
60 : "HiddenServiceAllowUnknownPorts 2\n"; /* Should be 0 or 1. */
61 1 : setup_full_capture_of_logs(LOG_WARN);
62 1 : ret = helper_config_service(conf, 1);
63 1 : tt_int_op(ret, OP_EQ, -1);
64 1 : expect_log_msg_containing("Could not parse "
65 : "HiddenServiceAllowUnknownPorts: Unrecognized "
66 1 : "value 2. Allowed values are 0 and 1.");
67 1 : teardown_capture_of_logs();
68 : }
69 :
70 : /* Bad value of HiddenServiceDirGroupReadable */
71 : {
72 1 : const char *conf =
73 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
74 : "HiddenServiceVersion 3\n"
75 : "HiddenServiceDirGroupReadable 2\n"; /* Should be 0 or 1. */
76 1 : setup_full_capture_of_logs(LOG_WARN);
77 1 : ret = helper_config_service(conf, 1);
78 1 : tt_int_op(ret, OP_EQ, -1);
79 1 : expect_log_msg_containing("Could not parse "
80 : "HiddenServiceDirGroupReadable: "
81 1 : "Unrecognized value 2.");
82 1 : teardown_capture_of_logs();
83 : }
84 :
85 : /* Bad value of HiddenServiceMaxStreamsCloseCircuit */
86 : {
87 1 : const char *conf =
88 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
89 : "HiddenServiceVersion 3\n"
90 : "HiddenServiceMaxStreamsCloseCircuit 2\n"; /* Should be 0 or 1. */
91 1 : setup_full_capture_of_logs(LOG_WARN);
92 1 : ret = helper_config_service(conf, 1);
93 1 : tt_int_op(ret, OP_EQ, -1);
94 1 : expect_log_msg_containing("Could not parse "
95 : "HiddenServiceMaxStreamsCloseCircuit: "
96 1 : "Unrecognized value 2");
97 1 : teardown_capture_of_logs();
98 : }
99 :
100 : /* Too much max streams. */
101 : {
102 1 : const char *conf =
103 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
104 : "HiddenServiceVersion 3\n"
105 : "HiddenServicePort 80\n"
106 : "HiddenServiceMaxStreams 65536\n"; /* One too many. */
107 1 : setup_full_capture_of_logs(LOG_WARN);
108 1 : ret = helper_config_service(conf, 1);
109 1 : tt_int_op(ret, OP_EQ, -1);
110 1 : expect_log_msg_containing("HiddenServiceMaxStreams must be between "
111 1 : "0 and 65535, not 65536");
112 1 : teardown_capture_of_logs();
113 : }
114 :
115 : /* Duplicate directory directive. */
116 : {
117 1 : const char *conf =
118 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
119 : "HiddenServiceVersion 3\n"
120 : "HiddenServicePort 80\n"
121 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
122 : "HiddenServiceVersion 3\n"
123 : "HiddenServicePort 81\n";
124 1 : setup_full_capture_of_logs(LOG_WARN);
125 1 : ret = helper_config_service(conf, 1);
126 1 : tt_int_op(ret, OP_EQ, -1);
127 1 : expect_log_msg_containing("Another hidden service is already "
128 1 : "configured for directory");
129 1 : teardown_capture_of_logs();
130 : }
131 :
132 : /* Bad port. */
133 : {
134 1 : const char *conf =
135 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
136 : "HiddenServiceVersion 3\n"
137 : "HiddenServicePort 65536\n";
138 1 : setup_full_capture_of_logs(LOG_WARN);
139 1 : ret = helper_config_service(conf, 1);
140 1 : tt_int_op(ret, OP_EQ, -1);
141 1 : expect_log_msg_containing("Missing or invalid port");
142 1 : teardown_capture_of_logs();
143 : }
144 :
145 : /* Bad target addr:port separation. */
146 : {
147 1 : const char *conf =
148 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
149 : "HiddenServiceVersion 3\n"
150 : "HiddenServicePort 80 127.0.0.1 8000\n";
151 1 : setup_full_capture_of_logs(LOG_WARN);
152 1 : ret = helper_config_service(conf, 1);
153 1 : tt_int_op(ret, OP_EQ, -1);
154 1 : expect_log_msg_containing("HiddenServicePort parse error: "
155 1 : "invalid port mapping");
156 1 : teardown_capture_of_logs();
157 : }
158 :
159 : /* Out of order directives. */
160 : {
161 1 : const char *conf =
162 : "HiddenServiceVersion 3\n"
163 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
164 : "HiddenServicePort 80\n";
165 1 : setup_full_capture_of_logs(LOG_WARN);
166 1 : ret = helper_config_service(conf, 1);
167 1 : tt_int_op(ret, OP_EQ, -1);
168 1 : expect_log_msg_containing("HiddenServiceVersion with no preceding "
169 1 : "HiddenServiceDir directive");
170 1 : teardown_capture_of_logs();
171 : }
172 :
173 1 : done:
174 1 : ;
175 1 : }
176 :
177 : static void
178 1 : test_valid_service(void *arg)
179 : {
180 1 : int ret;
181 :
182 1 : (void) arg;
183 :
184 : {
185 1 : const char *conf =
186 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
187 : "HiddenServiceVersion 3\n"
188 : "HiddenServicePort 81\n";
189 1 : ret = helper_config_service(conf, 1);
190 1 : tt_int_op(ret, OP_EQ, 0);
191 : }
192 :
193 1 : done:
194 1 : ;
195 1 : }
196 :
197 : static void
198 1 : test_invalid_service_v3(void *arg)
199 : {
200 1 : int validate_only = 1, ret;
201 :
202 1 : (void) arg;
203 :
204 : /* Try with a missing port configuration. */
205 : {
206 1 : const char *conf =
207 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
208 : "HiddenServiceVersion 3\n";
209 1 : setup_full_capture_of_logs(LOG_WARN);
210 1 : ret = helper_config_service(conf, validate_only);
211 1 : tt_int_op(ret, OP_EQ, -1);
212 1 : expect_log_msg_containing("with no ports configured.");
213 1 : teardown_capture_of_logs();
214 : }
215 :
216 : /* Too many introduction points. */
217 : {
218 1 : const char *conf =
219 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
220 : "HiddenServiceVersion 3\n"
221 : "HiddenServicePort 80\n"
222 : "HiddenServiceNumIntroductionPoints 21\n"; /* One too many. */
223 1 : setup_full_capture_of_logs(LOG_WARN);
224 1 : ret = helper_config_service(conf, validate_only);
225 1 : tt_int_op(ret, OP_EQ, -1);
226 1 : expect_log_msg_containing("HiddenServiceNumIntroductionPoints must "
227 1 : "be between 3 and 20, not 21.");
228 1 : teardown_capture_of_logs();
229 : }
230 :
231 : /* Too little introduction points. */
232 : {
233 1 : const char *conf =
234 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
235 : "HiddenServiceVersion 3\n"
236 : "HiddenServicePort 80\n"
237 : "HiddenServiceNumIntroductionPoints 1\n";
238 1 : setup_full_capture_of_logs(LOG_WARN);
239 1 : ret = helper_config_service(conf, validate_only);
240 1 : tt_int_op(ret, OP_EQ, -1);
241 1 : expect_log_msg_containing("HiddenServiceNumIntroductionPoints must "
242 1 : "be between 3 and 20, not 1.");
243 1 : teardown_capture_of_logs();
244 : }
245 :
246 1 : done:
247 1 : ;
248 1 : }
249 :
250 : static void
251 1 : test_valid_service_v3(void *arg)
252 : {
253 1 : int ret;
254 :
255 1 : (void) arg;
256 1 : mock_hostname_resolver();
257 :
258 : /* Valid complex configuration. */
259 : {
260 1 : const char *conf =
261 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n"
262 : "HiddenServiceVersion 3\n"
263 : "HiddenServicePort 80\n"
264 : "HiddenServicePort 22 localhost:22\n"
265 : #ifdef HAVE_SYS_UN_H
266 : "HiddenServicePort 42 unix:/path/to/socket\n"
267 : #endif
268 : "HiddenServiceAllowUnknownPorts 1\n"
269 : "HiddenServiceMaxStreams 42\n"
270 : "HiddenServiceMaxStreamsCloseCircuit 0\n"
271 : "HiddenServiceDirGroupReadable 1\n"
272 : "HiddenServiceNumIntroductionPoints 7\n";
273 1 : ret = helper_config_service(conf, 1);
274 1 : tt_int_op(ret, OP_EQ, 0);
275 : }
276 :
277 : /* Valid complex configuration. */
278 : {
279 1 : const char *conf =
280 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
281 : "HiddenServiceVersion 3\n"
282 : "HiddenServicePort 65535\n"
283 : "HiddenServicePort 22 1.1.1.1:22\n"
284 : #ifdef HAVE_SYS_UN_H
285 : "HiddenServicePort 9000 unix:/path/to/socket\n"
286 : #endif
287 : "HiddenServiceAllowUnknownPorts 0\n"
288 : "HiddenServiceMaxStreams 42\n"
289 : "HiddenServiceMaxStreamsCloseCircuit 0\n"
290 : "HiddenServiceDirGroupReadable 1\n"
291 : "HiddenServiceNumIntroductionPoints 20\n";
292 1 : ret = helper_config_service(conf, 1);
293 1 : tt_int_op(ret, OP_EQ, 0);
294 : }
295 :
296 1 : done:
297 1 : unmock_hostname_resolver();
298 1 : }
299 :
300 : static void
301 1 : test_staging_service_v3(void *arg)
302 : {
303 1 : int ret;
304 :
305 1 : (void) arg;
306 :
307 : /* We don't validate a service object, this is the service test that are in
308 : * charge of doing so. We just check for the stable state after
309 : * registration. */
310 :
311 1 : hs_init();
312 :
313 : /* Time for a valid v3 service that should get staged. */
314 1 : const char *conf =
315 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n"
316 : "HiddenServiceVersion 3\n"
317 : "HiddenServicePort 65535\n"
318 : "HiddenServicePort 22 1.1.1.1:22\n"
319 : #ifdef HAVE_SYS_UN_H
320 : "HiddenServicePort 9000 unix:/path/to/socket\n"
321 : #endif
322 : "HiddenServiceAllowUnknownPorts 0\n"
323 : "HiddenServiceMaxStreams 42\n"
324 : "HiddenServiceMaxStreamsCloseCircuit 0\n"
325 : "HiddenServiceDirGroupReadable 1\n"
326 : "HiddenServiceNumIntroductionPoints 20\n";
327 1 : ret = helper_config_service(conf, 0);
328 1 : tt_int_op(ret, OP_EQ, 0);
329 : /* Ok, we have a service in our map! Registration went well. */
330 1 : tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
331 :
332 1 : done:
333 1 : hs_free_all();
334 1 : }
335 :
336 : static void
337 1 : test_dos_parameters(void *arg)
338 : {
339 1 : int ret;
340 :
341 1 : (void) arg;
342 :
343 1 : hs_init();
344 :
345 : /* Valid configuration. */
346 : {
347 1 : const char *conf =
348 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
349 : "HiddenServiceVersion 3\n"
350 : "HiddenServicePort 22 1.1.1.1:22\n"
351 : "HiddenServiceEnableIntroDoSDefense 1\n"
352 : "HiddenServiceEnableIntroDoSRatePerSec 42\n"
353 : "HiddenServiceEnableIntroDoSBurstPerSec 87\n";
354 :
355 1 : setup_full_capture_of_logs(LOG_INFO);
356 1 : ret = helper_config_service(conf, 0);
357 1 : tt_int_op(ret, OP_EQ, 0);
358 1 : expect_log_msg_containing("Service INTRO2 DoS defenses rate set to: 42");
359 1 : expect_log_msg_containing("Service INTRO2 DoS defenses burst set to: 87");
360 1 : teardown_capture_of_logs();
361 : }
362 :
363 : /* Invalid rate. Value of 2^37. Max allowed is 2^31. */
364 : {
365 1 : const char *conf =
366 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
367 : "HiddenServiceVersion 3\n"
368 : "HiddenServicePort 22 1.1.1.1:22\n"
369 : "HiddenServiceEnableIntroDoSDefense 1\n"
370 : "HiddenServiceEnableIntroDoSRatePerSec 137438953472\n"
371 : "HiddenServiceEnableIntroDoSBurstPerSec 87\n";
372 :
373 1 : setup_full_capture_of_logs(LOG_WARN);
374 1 : ret = helper_config_service(conf, 0);
375 1 : tt_int_op(ret, OP_EQ, -1);
376 1 : expect_log_msg_containing("Could not parse "
377 : "HiddenServiceEnableIntroDoSRatePerSec: "
378 : "Integer 137438953472 is malformed or out of "
379 1 : "bounds.");
380 1 : teardown_capture_of_logs();
381 : }
382 :
383 : /* Invalid burst. Value of 2^38. Max allowed is 2^31. */
384 : {
385 1 : const char *conf =
386 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
387 : "HiddenServiceVersion 3\n"
388 : "HiddenServicePort 22 1.1.1.1:22\n"
389 : "HiddenServiceEnableIntroDoSDefense 1\n"
390 : "HiddenServiceEnableIntroDoSRatePerSec 42\n"
391 : "HiddenServiceEnableIntroDoSBurstPerSec 274877906944\n";
392 :
393 1 : setup_full_capture_of_logs(LOG_WARN);
394 1 : ret = helper_config_service(conf, 0);
395 1 : tt_int_op(ret, OP_EQ, -1);
396 1 : expect_log_msg_containing("Could not parse "
397 : "HiddenServiceEnableIntroDoSBurstPerSec: "
398 : "Integer 274877906944 is malformed or out "
399 1 : "of bounds.");
400 1 : teardown_capture_of_logs();
401 : }
402 :
403 : /* Burst is smaller than rate. */
404 : {
405 1 : const char *conf =
406 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
407 : "HiddenServiceVersion 3\n"
408 : "HiddenServicePort 22 1.1.1.1:22\n"
409 : "HiddenServiceEnableIntroDoSDefense 1\n"
410 : "HiddenServiceEnableIntroDoSRatePerSec 42\n"
411 : "HiddenServiceEnableIntroDoSBurstPerSec 27\n";
412 :
413 1 : setup_full_capture_of_logs(LOG_WARN);
414 1 : ret = helper_config_service(conf, 0);
415 1 : tt_int_op(ret, OP_EQ, -1);
416 1 : expect_log_msg_containing("Hidden service DoS defenses burst (27) can "
417 1 : "not be smaller than the rate value (42).");
418 1 : teardown_capture_of_logs();
419 : }
420 :
421 : /* Negative value. */
422 : {
423 1 : const char *conf =
424 : "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs3\n"
425 : "HiddenServiceVersion 3\n"
426 : "HiddenServicePort 22 1.1.1.1:22\n"
427 : "HiddenServiceEnableIntroDoSDefense 1\n"
428 : "HiddenServiceEnableIntroDoSRatePerSec -1\n"
429 : "HiddenServiceEnableIntroDoSBurstPerSec 42\n";
430 :
431 1 : setup_full_capture_of_logs(LOG_WARN);
432 1 : ret = helper_config_service(conf, 0);
433 1 : tt_int_op(ret, OP_EQ, -1);
434 1 : expect_log_msg_containing("Could not parse "
435 : "HiddenServiceEnableIntroDoSRatePerSec: "
436 1 : "Integer -1 is malformed or out of bounds.");
437 1 : teardown_capture_of_logs();
438 : }
439 :
440 1 : done:
441 1 : hs_free_all();
442 1 : }
443 :
444 : struct testcase_t hs_config_tests[] = {
445 : /* Invalid service not specific to any version. */
446 : { "invalid_service", test_invalid_service, TT_FORK,
447 : NULL, NULL },
448 : { "valid_service", test_valid_service, TT_FORK,
449 : NULL, NULL },
450 :
451 : /* Test case only for version 3. */
452 : { "invalid_service_v3", test_invalid_service_v3, TT_FORK,
453 : NULL, NULL },
454 : { "valid_service_v3", test_valid_service_v3, TT_FORK,
455 : NULL, NULL },
456 :
457 : /* Test service staging. */
458 : { "staging_service_v3", test_staging_service_v3, TT_FORK,
459 : NULL, NULL },
460 :
461 : /* Test HS DoS parameters. */
462 : { "dos_parameters", test_dos_parameters, TT_FORK,
463 : NULL, NULL },
464 :
465 : END_OF_TESTCASES
466 : };
|