test_hs_config.c (13986B)
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 helper_config_service(const char *conf, int validate_only) 24 { 25 int ret = 0; 26 or_options_t *options = NULL; 27 tt_assert(conf); 28 options = helper_parse_options(conf); 29 tt_assert(options); 30 ret = hs_config_service_all(options, validate_only); 31 done: 32 or_options_free(options); 33 return ret; 34 } 35 36 static void 37 test_invalid_service(void *arg) 38 { 39 int ret; 40 41 (void) arg; 42 43 /* Try with a missing port configuration. */ 44 { 45 const char *conf = 46 "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" 47 "HiddenServiceVersion 1\n"; /* Wrong not supported version. */ 48 setup_full_capture_of_logs(LOG_WARN); 49 ret = helper_config_service(conf, 1); 50 tt_int_op(ret, OP_EQ, -1); 51 expect_log_msg_containing("HiddenServiceVersion must be 3, not 1"); 52 teardown_capture_of_logs(); 53 } 54 55 /* Bad value of HiddenServiceAllowUnknownPorts. */ 56 { 57 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 setup_full_capture_of_logs(LOG_WARN); 62 ret = helper_config_service(conf, 1); 63 tt_int_op(ret, OP_EQ, -1); 64 expect_log_msg_containing("Could not parse " 65 "HiddenServiceAllowUnknownPorts: Unrecognized " 66 "value 2. Allowed values are 0 and 1."); 67 teardown_capture_of_logs(); 68 } 69 70 /* Bad value of HiddenServiceDirGroupReadable */ 71 { 72 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 setup_full_capture_of_logs(LOG_WARN); 77 ret = helper_config_service(conf, 1); 78 tt_int_op(ret, OP_EQ, -1); 79 expect_log_msg_containing("Could not parse " 80 "HiddenServiceDirGroupReadable: " 81 "Unrecognized value 2."); 82 teardown_capture_of_logs(); 83 } 84 85 /* Bad value of HiddenServiceMaxStreamsCloseCircuit */ 86 { 87 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 setup_full_capture_of_logs(LOG_WARN); 92 ret = helper_config_service(conf, 1); 93 tt_int_op(ret, OP_EQ, -1); 94 expect_log_msg_containing("Could not parse " 95 "HiddenServiceMaxStreamsCloseCircuit: " 96 "Unrecognized value 2"); 97 teardown_capture_of_logs(); 98 } 99 100 /* Too much max streams. */ 101 { 102 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 setup_full_capture_of_logs(LOG_WARN); 108 ret = helper_config_service(conf, 1); 109 tt_int_op(ret, OP_EQ, -1); 110 expect_log_msg_containing("HiddenServiceMaxStreams must be between " 111 "0 and 65535, not 65536"); 112 teardown_capture_of_logs(); 113 } 114 115 /* Duplicate directory directive. */ 116 { 117 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 setup_full_capture_of_logs(LOG_WARN); 125 ret = helper_config_service(conf, 1); 126 tt_int_op(ret, OP_EQ, -1); 127 expect_log_msg_containing("Another hidden service is already " 128 "configured for directory"); 129 teardown_capture_of_logs(); 130 } 131 132 /* Bad port. */ 133 { 134 const char *conf = 135 "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" 136 "HiddenServiceVersion 3\n" 137 "HiddenServicePort 65536\n"; 138 setup_full_capture_of_logs(LOG_WARN); 139 ret = helper_config_service(conf, 1); 140 tt_int_op(ret, OP_EQ, -1); 141 expect_log_msg_containing("Missing or invalid port"); 142 teardown_capture_of_logs(); 143 } 144 145 /* Bad target addr:port separation. */ 146 { 147 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 setup_full_capture_of_logs(LOG_WARN); 152 ret = helper_config_service(conf, 1); 153 tt_int_op(ret, OP_EQ, -1); 154 expect_log_msg_containing("HiddenServicePort parse error: " 155 "invalid port mapping"); 156 teardown_capture_of_logs(); 157 } 158 159 /* Out of order directives. */ 160 { 161 const char *conf = 162 "HiddenServiceVersion 3\n" 163 "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" 164 "HiddenServicePort 80\n"; 165 setup_full_capture_of_logs(LOG_WARN); 166 ret = helper_config_service(conf, 1); 167 tt_int_op(ret, OP_EQ, -1); 168 expect_log_msg_containing("HiddenServiceVersion with no preceding " 169 "HiddenServiceDir directive"); 170 teardown_capture_of_logs(); 171 } 172 173 done: 174 ; 175 } 176 177 static void 178 test_valid_service(void *arg) 179 { 180 int ret; 181 182 (void) arg; 183 184 { 185 const char *conf = 186 "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs2\n" 187 "HiddenServiceVersion 3\n" 188 "HiddenServicePort 81\n"; 189 ret = helper_config_service(conf, 1); 190 tt_int_op(ret, OP_EQ, 0); 191 } 192 193 done: 194 ; 195 } 196 197 static void 198 test_invalid_service_v3(void *arg) 199 { 200 int validate_only = 1, ret; 201 202 (void) arg; 203 204 /* Try with a missing port configuration. */ 205 { 206 const char *conf = 207 "HiddenServiceDir /tmp/tor-test-hs-RANDOM/hs1\n" 208 "HiddenServiceVersion 3\n"; 209 setup_full_capture_of_logs(LOG_WARN); 210 ret = helper_config_service(conf, validate_only); 211 tt_int_op(ret, OP_EQ, -1); 212 expect_log_msg_containing("with no ports configured."); 213 teardown_capture_of_logs(); 214 } 215 216 /* Too many introduction points. */ 217 { 218 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 setup_full_capture_of_logs(LOG_WARN); 224 ret = helper_config_service(conf, validate_only); 225 tt_int_op(ret, OP_EQ, -1); 226 expect_log_msg_containing("HiddenServiceNumIntroductionPoints must " 227 "be between 3 and 20, not 21."); 228 teardown_capture_of_logs(); 229 } 230 231 /* Too little introduction points. */ 232 { 233 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 setup_full_capture_of_logs(LOG_WARN); 239 ret = helper_config_service(conf, validate_only); 240 tt_int_op(ret, OP_EQ, -1); 241 expect_log_msg_containing("HiddenServiceNumIntroductionPoints must " 242 "be between 3 and 20, not 1."); 243 teardown_capture_of_logs(); 244 } 245 246 done: 247 ; 248 } 249 250 static void 251 test_valid_service_v3(void *arg) 252 { 253 int ret; 254 255 (void) arg; 256 mock_hostname_resolver(); 257 258 /* Valid complex configuration. */ 259 { 260 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 ret = helper_config_service(conf, 1); 274 tt_int_op(ret, OP_EQ, 0); 275 } 276 277 /* Valid complex configuration. */ 278 { 279 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 ret = helper_config_service(conf, 1); 293 tt_int_op(ret, OP_EQ, 0); 294 } 295 296 done: 297 unmock_hostname_resolver(); 298 } 299 300 static void 301 test_staging_service_v3(void *arg) 302 { 303 int ret; 304 305 (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 hs_init(); 312 313 /* Time for a valid v3 service that should get staged. */ 314 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 ret = helper_config_service(conf, 0); 328 tt_int_op(ret, OP_EQ, 0); 329 /* Ok, we have a service in our map! Registration went well. */ 330 tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); 331 332 done: 333 hs_free_all(); 334 } 335 336 static void 337 test_dos_parameters(void *arg) 338 { 339 int ret; 340 341 (void) arg; 342 343 hs_init(); 344 345 /* Valid configuration. */ 346 { 347 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 setup_full_capture_of_logs(LOG_INFO); 356 ret = helper_config_service(conf, 0); 357 tt_int_op(ret, OP_EQ, 0); 358 expect_log_msg_containing("Service INTRO2 DoS defenses rate set to: 42"); 359 expect_log_msg_containing("Service INTRO2 DoS defenses burst set to: 87"); 360 teardown_capture_of_logs(); 361 } 362 363 /* Invalid rate. Value of 2^37. Max allowed is 2^31. */ 364 { 365 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 setup_full_capture_of_logs(LOG_WARN); 374 ret = helper_config_service(conf, 0); 375 tt_int_op(ret, OP_EQ, -1); 376 expect_log_msg_containing("Could not parse " 377 "HiddenServiceEnableIntroDoSRatePerSec: " 378 "Integer 137438953472 is malformed or out of " 379 "bounds."); 380 teardown_capture_of_logs(); 381 } 382 383 /* Invalid burst. Value of 2^38. Max allowed is 2^31. */ 384 { 385 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 setup_full_capture_of_logs(LOG_WARN); 394 ret = helper_config_service(conf, 0); 395 tt_int_op(ret, OP_EQ, -1); 396 expect_log_msg_containing("Could not parse " 397 "HiddenServiceEnableIntroDoSBurstPerSec: " 398 "Integer 274877906944 is malformed or out " 399 "of bounds."); 400 teardown_capture_of_logs(); 401 } 402 403 /* Burst is smaller than rate. */ 404 { 405 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 setup_full_capture_of_logs(LOG_WARN); 414 ret = helper_config_service(conf, 0); 415 tt_int_op(ret, OP_EQ, -1); 416 expect_log_msg_containing("Hidden service DoS defenses burst (27) can " 417 "not be smaller than the rate value (42)."); 418 teardown_capture_of_logs(); 419 } 420 421 /* Negative value. */ 422 { 423 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 setup_full_capture_of_logs(LOG_WARN); 432 ret = helper_config_service(conf, 0); 433 tt_int_op(ret, OP_EQ, -1); 434 expect_log_msg_containing("Could not parse " 435 "HiddenServiceEnableIntroDoSRatePerSec: " 436 "Integer -1 is malformed or out of bounds."); 437 teardown_capture_of_logs(); 438 } 439 440 done: 441 hs_free_all(); 442 } 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 };