test_entryconn.c (27393B)
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 #include "orconfig.h" 5 6 #define CONNECTION_PRIVATE 7 #define CONNECTION_EDGE_PRIVATE 8 9 #include "core/or/or.h" 10 #include "test/test.h" 11 12 #include "feature/client/addressmap.h" 13 #include "app/config/config.h" 14 #include "lib/confmgt/confmgt.h" 15 #include "core/mainloop/connection.h" 16 #include "core/or/connection_edge.h" 17 #include "feature/nodelist/nodelist.h" 18 19 #include "feature/hs/hs_cache.h" 20 21 #include "core/or/entry_connection_st.h" 22 #include "core/or/socks_request_st.h" 23 24 #include "lib/encoding/confline.h" 25 26 static void * 27 entryconn_rewrite_setup(const struct testcase_t *tc) 28 { 29 (void)tc; 30 entry_connection_t *ec = entry_connection_new(CONN_TYPE_AP, AF_INET); 31 addressmap_init(); 32 return ec; 33 } 34 35 static int 36 entryconn_rewrite_teardown(const struct testcase_t *tc, void *arg) 37 { 38 (void)tc; 39 entry_connection_t *ec = arg; 40 if (ec) 41 connection_free_minimal(ENTRY_TO_CONN(ec)); 42 addressmap_free_all(); 43 return 1; 44 } 45 46 static struct testcase_setup_t test_rewrite_setup = { 47 entryconn_rewrite_setup, entryconn_rewrite_teardown 48 }; 49 50 /* Simple rewrite: no changes needed */ 51 static void 52 test_entryconn_rewrite_basic(void *arg) 53 { 54 entry_connection_t *ec = arg; 55 rewrite_result_t rr; 56 57 tt_assert(ec->socks_request); 58 strlcpy(ec->socks_request->address, "www.TORproject.org", 59 sizeof(ec->socks_request->address)); 60 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 61 connection_ap_handshake_rewrite(ec, &rr); 62 63 tt_int_op(rr.should_close, OP_EQ, 0); 64 tt_int_op(rr.end_reason, OP_EQ, 0); 65 tt_int_op(rr.automap, OP_EQ, 0); 66 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 67 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 68 tt_str_op(rr.orig_address, OP_EQ, "www.torproject.org"); 69 tt_str_op(ec->socks_request->address, OP_EQ, "www.torproject.org"); 70 tt_str_op(ec->original_dest_address, OP_EQ, "www.torproject.org"); 71 72 done: 73 ; 74 } 75 76 /* Rewrite but reject because of disallowed .exit */ 77 static void 78 test_entryconn_rewrite_bad_dotexit(void *arg) 79 { 80 entry_connection_t *ec = arg; 81 rewrite_result_t rr; 82 83 tt_assert(ec->socks_request); 84 strlcpy(ec->socks_request->address, "www.TORproject.org.foo.exit", 85 sizeof(ec->socks_request->address)); 86 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 87 connection_ap_handshake_rewrite(ec, &rr); 88 89 tt_int_op(rr.should_close, OP_EQ, 1); 90 tt_int_op(rr.end_reason, OP_EQ, END_STREAM_REASON_TORPROTOCOL); 91 92 done: 93 ; 94 } 95 96 /* Automap on resolve, connect to automapped address, resolve again and get 97 * same answer. (IPv4) */ 98 static void 99 test_entryconn_rewrite_automap_ipv4(void *arg) 100 { 101 entry_connection_t *ec = arg; 102 entry_connection_t *ec2=NULL, *ec3=NULL; 103 rewrite_result_t rr; 104 char *msg = NULL; 105 106 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET); 107 ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET); 108 109 get_options_mutable()->AutomapHostsOnResolve = 1; 110 smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, "."); 111 parse_virtual_addr_network("127.202.0.0/16", AF_INET, 0, &msg); 112 113 /* Automap this on resolve. */ 114 strlcpy(ec->socks_request->address, "WWW.MIT.EDU", 115 sizeof(ec->socks_request->address)); 116 ec->socks_request->command = SOCKS_COMMAND_RESOLVE; 117 connection_ap_handshake_rewrite(ec, &rr); 118 119 tt_int_op(rr.automap, OP_EQ, 1); 120 tt_int_op(rr.should_close, OP_EQ, 0); 121 tt_int_op(rr.end_reason, OP_EQ, 0); 122 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 123 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 124 tt_str_op(rr.orig_address, OP_EQ, "www.mit.edu"); 125 tt_str_op(ec->original_dest_address, OP_EQ, "www.mit.edu"); 126 127 tt_assert(!strcmpstart(ec->socks_request->address,"127.202.")); 128 129 /* Connect to it and make sure we get the original address back. */ 130 strlcpy(ec2->socks_request->address, ec->socks_request->address, 131 sizeof(ec2->socks_request->address)); 132 133 ec2->socks_request->command = SOCKS_COMMAND_CONNECT; 134 connection_ap_handshake_rewrite(ec2, &rr); 135 136 tt_int_op(rr.automap, OP_EQ, 0); 137 tt_int_op(rr.should_close, OP_EQ, 0); 138 tt_int_op(rr.end_reason, OP_EQ, 0); 139 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 140 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 141 tt_str_op(rr.orig_address, OP_EQ, ec->socks_request->address); 142 tt_str_op(ec2->original_dest_address, OP_EQ, ec->socks_request->address); 143 tt_str_op(ec2->socks_request->address, OP_EQ, "www.mit.edu"); 144 145 /* Resolve it again, make sure the answer is the same. */ 146 strlcpy(ec3->socks_request->address, "www.MIT.EDU", 147 sizeof(ec3->socks_request->address)); 148 ec3->socks_request->command = SOCKS_COMMAND_RESOLVE; 149 connection_ap_handshake_rewrite(ec3, &rr); 150 151 tt_int_op(rr.automap, OP_EQ, 1); 152 tt_int_op(rr.should_close, OP_EQ, 0); 153 tt_int_op(rr.end_reason, OP_EQ, 0); 154 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 155 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 156 tt_str_op(rr.orig_address, OP_EQ, "www.mit.edu"); 157 tt_str_op(ec3->original_dest_address, OP_EQ, "www.mit.edu"); 158 159 tt_str_op(ec3->socks_request->address, OP_EQ, 160 ec->socks_request->address); 161 162 done: 163 connection_free_minimal(ENTRY_TO_CONN(ec2)); 164 connection_free_minimal(ENTRY_TO_CONN(ec3)); 165 } 166 167 /* Automap on resolve, connect to automapped address, resolve again and get 168 * same answer. (IPv6) */ 169 static void 170 test_entryconn_rewrite_automap_ipv6(void *arg) 171 { 172 (void)arg; 173 entry_connection_t *ec =NULL; 174 entry_connection_t *ec2=NULL, *ec3=NULL; 175 rewrite_result_t rr; 176 char *msg = NULL; 177 178 ec = entry_connection_new(CONN_TYPE_AP, AF_INET6); 179 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET6); 180 ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET6); 181 182 get_options_mutable()->AutomapHostsOnResolve = 1; 183 smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, "."); 184 parse_virtual_addr_network("FE80::/32", AF_INET6, 0, &msg); 185 186 /* Automap this on resolve. */ 187 strlcpy(ec->socks_request->address, "WWW.MIT.EDU", 188 sizeof(ec->socks_request->address)); 189 ec->socks_request->command = SOCKS_COMMAND_RESOLVE; 190 connection_ap_handshake_rewrite(ec, &rr); 191 192 tt_int_op(rr.automap, OP_EQ, 1); 193 tt_int_op(rr.should_close, OP_EQ, 0); 194 tt_int_op(rr.end_reason, OP_EQ, 0); 195 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 196 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 197 tt_str_op(rr.orig_address, OP_EQ, "www.mit.edu"); 198 tt_str_op(ec->original_dest_address, OP_EQ, "www.mit.edu"); 199 200 /* Yes, this [ should be here. */ 201 tt_assert(!strcmpstart(ec->socks_request->address,"[fe80:")); 202 203 /* Connect to it and make sure we get the original address back. */ 204 strlcpy(ec2->socks_request->address, ec->socks_request->address, 205 sizeof(ec2->socks_request->address)); 206 207 ec2->socks_request->command = SOCKS_COMMAND_CONNECT; 208 connection_ap_handshake_rewrite(ec2, &rr); 209 210 tt_int_op(rr.automap, OP_EQ, 0); 211 tt_int_op(rr.should_close, OP_EQ, 0); 212 tt_int_op(rr.end_reason, OP_EQ, 0); 213 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 214 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 215 tt_str_op(rr.orig_address, OP_EQ, ec->socks_request->address); 216 tt_str_op(ec2->original_dest_address, OP_EQ, ec->socks_request->address); 217 tt_str_op(ec2->socks_request->address, OP_EQ, "www.mit.edu"); 218 219 /* Resolve it again, make sure the answer is the same. */ 220 strlcpy(ec3->socks_request->address, "www.MIT.EDU", 221 sizeof(ec3->socks_request->address)); 222 ec3->socks_request->command = SOCKS_COMMAND_RESOLVE; 223 connection_ap_handshake_rewrite(ec3, &rr); 224 225 tt_int_op(rr.automap, OP_EQ, 1); 226 tt_int_op(rr.should_close, OP_EQ, 0); 227 tt_int_op(rr.end_reason, OP_EQ, 0); 228 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 229 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 230 tt_str_op(rr.orig_address, OP_EQ, "www.mit.edu"); 231 tt_str_op(ec3->original_dest_address, OP_EQ, "www.mit.edu"); 232 233 tt_str_op(ec3->socks_request->address, OP_EQ, 234 ec->socks_request->address); 235 236 done: 237 connection_free_minimal(ENTRY_TO_CONN(ec)); 238 connection_free_minimal(ENTRY_TO_CONN(ec2)); 239 connection_free_minimal(ENTRY_TO_CONN(ec3)); 240 } 241 242 #if 0 243 /* FFFF not actually supported. */ 244 /* automap on resolve, reverse lookup. */ 245 static void 246 test_entryconn_rewrite_automap_reverse(void *arg) 247 { 248 entry_connection_t *ec = arg; 249 entry_connection_t *ec2=NULL; 250 rewrite_result_t rr; 251 char *msg = NULL; 252 253 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET); 254 255 get_options_mutable()->AutomapHostsOnResolve = 1; 256 get_options_mutable()->SafeLogging_ = SAFELOG_SCRUB_NONE; 257 smartlist_add(get_options_mutable()->AutomapHostsSuffixes, 258 tor_strdup(".bloom")); 259 parse_virtual_addr_network("127.80.0.0/16", AF_INET, 0, &msg); 260 261 /* Automap this on resolve. */ 262 strlcpy(ec->socks_request->address, "www.poldy.BLOOM", 263 sizeof(ec->socks_request->address)); 264 ec->socks_request->command = SOCKS_COMMAND_RESOLVE; 265 connection_ap_handshake_rewrite(ec, &rr); 266 267 tt_int_op(rr.automap, OP_EQ, 1); 268 tt_int_op(rr.should_close, OP_EQ, 0); 269 tt_int_op(rr.end_reason, OP_EQ, 0); 270 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 271 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 272 tt_str_op(rr.orig_address, OP_EQ, "www.poldy.bloom"); 273 tt_str_op(ec->original_dest_address, OP_EQ, "www.poldy.bloom"); 274 275 tt_assert(!strcmpstart(ec->socks_request->address,"127.80.")); 276 277 strlcpy(ec2->socks_request->address, ec->socks_request->address, 278 sizeof(ec2->socks_request->address)); 279 ec2->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; 280 connection_ap_handshake_rewrite(ec2, &rr); 281 282 tt_int_op(rr.automap, OP_EQ, 0); 283 tt_int_op(rr.should_close, OP_EQ, 1); 284 tt_int_op(rr.end_reason, OP_EQ, 285 END_STREAM_REASON_DONE|END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); 286 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 287 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 288 289 done: 290 connection_free_minimal(ENTRY_TO_CONN(ec2)); 291 } 292 #endif /* 0 */ 293 294 /* Rewrite because of cached DNS entry. */ 295 static void 296 test_entryconn_rewrite_cached_dns_ipv4(void *arg) 297 { 298 entry_connection_t *ec = arg; 299 rewrite_result_t rr; 300 time_t expires = time(NULL) + 3600; 301 entry_connection_t *ec2=NULL; 302 303 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET); 304 305 addressmap_register("www.friendly.example.com", 306 tor_strdup("240.240.241.241"), 307 expires, 308 ADDRMAPSRC_DNS, 309 0, 0, 0); 310 311 strlcpy(ec->socks_request->address, "www.friendly.example.com", 312 sizeof(ec->socks_request->address)); 313 strlcpy(ec2->socks_request->address, "www.friendly.example.com", 314 sizeof(ec2->socks_request->address)); 315 316 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 317 ec2->socks_request->command = SOCKS_COMMAND_CONNECT; 318 319 ec2->entry_cfg.use_cached_ipv4_answers = 1; /* only ec2 gets this flag */ 320 connection_ap_handshake_rewrite(ec, &rr); 321 322 tt_int_op(rr.automap, OP_EQ, 0); 323 tt_int_op(rr.should_close, OP_EQ, 0); 324 tt_int_op(rr.end_reason, OP_EQ, 0); 325 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 326 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 327 tt_str_op(rr.orig_address, OP_EQ, "www.friendly.example.com"); 328 tt_str_op(ec->socks_request->address, OP_EQ, "www.friendly.example.com"); 329 330 connection_ap_handshake_rewrite(ec2, &rr); 331 tt_int_op(rr.automap, OP_EQ, 0); 332 tt_int_op(rr.should_close, OP_EQ, 0); 333 tt_int_op(rr.end_reason, OP_EQ, 0); 334 tt_i64_op(rr.map_expires, OP_EQ, expires); 335 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 336 tt_str_op(rr.orig_address, OP_EQ, "www.friendly.example.com"); 337 tt_str_op(ec2->socks_request->address, OP_EQ, "240.240.241.241"); 338 339 done: 340 connection_free_minimal(ENTRY_TO_CONN(ec2)); 341 } 342 343 /* Rewrite because of cached DNS entry. */ 344 static void 345 test_entryconn_rewrite_cached_dns_ipv6(void *arg) 346 { 347 entry_connection_t *ec = NULL; 348 rewrite_result_t rr; 349 time_t expires = time(NULL) + 3600; 350 entry_connection_t *ec2=NULL; 351 352 (void)arg; 353 354 ec = entry_connection_new(CONN_TYPE_AP, AF_INET6); 355 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET6); 356 357 addressmap_register("www.friendly.example.com", 358 tor_strdup("[::f00f]"), 359 expires, 360 ADDRMAPSRC_DNS, 361 0, 0, 0); 362 363 strlcpy(ec->socks_request->address, "www.friendly.example.com", 364 sizeof(ec->socks_request->address)); 365 strlcpy(ec2->socks_request->address, "www.friendly.example.com", 366 sizeof(ec2->socks_request->address)); 367 368 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 369 ec2->socks_request->command = SOCKS_COMMAND_CONNECT; 370 371 ec2->entry_cfg.use_cached_ipv6_answers = 1; /* only ec2 gets this flag */ 372 connection_ap_handshake_rewrite(ec, &rr); 373 374 tt_int_op(rr.automap, OP_EQ, 0); 375 tt_int_op(rr.should_close, OP_EQ, 0); 376 tt_int_op(rr.end_reason, OP_EQ, 0); 377 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 378 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 379 tt_str_op(rr.orig_address, OP_EQ, "www.friendly.example.com"); 380 tt_str_op(ec->socks_request->address, OP_EQ, "www.friendly.example.com"); 381 382 connection_ap_handshake_rewrite(ec2, &rr); 383 tt_int_op(rr.automap, OP_EQ, 0); 384 tt_int_op(rr.should_close, OP_EQ, 0); 385 tt_int_op(rr.end_reason, OP_EQ, 0); 386 tt_i64_op(rr.map_expires, OP_EQ, expires); 387 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 388 tt_str_op(rr.orig_address, OP_EQ, "www.friendly.example.com"); 389 tt_str_op(ec2->socks_request->address, OP_EQ, "[::f00f]"); 390 391 done: 392 connection_free_minimal(ENTRY_TO_CONN(ec)); 393 connection_free_minimal(ENTRY_TO_CONN(ec2)); 394 } 395 396 /* Fail to connect to unmapped address in virtual range. */ 397 static void 398 test_entryconn_rewrite_unmapped_virtual(void *arg) 399 { 400 entry_connection_t *ec = arg; 401 rewrite_result_t rr; 402 entry_connection_t *ec2 = NULL; 403 char *msg = NULL; 404 405 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET6); 406 407 parse_virtual_addr_network("18.202.0.0/16", AF_INET, 0, &msg); 408 parse_virtual_addr_network("[ABCD::]/16", AF_INET6, 0, &msg); 409 410 strlcpy(ec->socks_request->address, "18.202.5.5", 411 sizeof(ec->socks_request->address)); 412 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 413 connection_ap_handshake_rewrite(ec, &rr); 414 415 tt_int_op(rr.should_close, OP_EQ, 1); 416 tt_int_op(rr.end_reason, OP_EQ, END_STREAM_REASON_INTERNAL); 417 tt_int_op(rr.automap, OP_EQ, 0); 418 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 419 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 420 421 strlcpy(ec2->socks_request->address, "[ABCD:9::5314:9543]", 422 sizeof(ec2->socks_request->address)); 423 ec2->socks_request->command = SOCKS_COMMAND_CONNECT; 424 connection_ap_handshake_rewrite(ec2, &rr); 425 426 tt_int_op(rr.should_close, OP_EQ, 1); 427 tt_int_op(rr.end_reason, OP_EQ, END_STREAM_REASON_INTERNAL); 428 tt_int_op(rr.automap, OP_EQ, 0); 429 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 430 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 431 432 done: 433 connection_free_minimal(ENTRY_TO_CONN(ec2)); 434 } 435 436 /* Rewrite because of mapaddress option */ 437 static void 438 test_entryconn_rewrite_mapaddress(void *arg) 439 { 440 entry_connection_t *ec = arg; 441 rewrite_result_t rr; 442 443 config_line_append(&get_options_mutable()->AddressMap, 444 "MapAddress", "meta metaobjects.example"); 445 config_register_addressmaps(get_options()); 446 447 strlcpy(ec->socks_request->address, "meta", 448 sizeof(ec->socks_request->address)); 449 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 450 connection_ap_handshake_rewrite(ec, &rr); 451 452 tt_int_op(rr.should_close, OP_EQ, 0); 453 tt_int_op(rr.end_reason, OP_EQ, 0); 454 tt_int_op(rr.automap, OP_EQ, 0); 455 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 456 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 457 tt_str_op(ec->socks_request->address, OP_EQ, "metaobjects.example"); 458 459 done: 460 ; 461 } 462 463 /* Reject reverse lookups of internal address. */ 464 static void 465 test_entryconn_rewrite_reject_internal_reverse(void *arg) 466 { 467 entry_connection_t *ec = arg; 468 rewrite_result_t rr; 469 470 strlcpy(ec->socks_request->address, "10.0.0.1", 471 sizeof(ec->socks_request->address)); 472 ec->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; 473 connection_ap_handshake_rewrite(ec, &rr); 474 475 tt_int_op(rr.should_close, OP_EQ, 1); 476 tt_int_op(rr.end_reason, OP_EQ, END_STREAM_REASON_SOCKSPROTOCOL | 477 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); 478 tt_int_op(rr.automap, OP_EQ, 0); 479 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 480 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 481 482 done: 483 ; 484 } 485 486 /* Rewrite into .exit because of virtual address mapping. */ 487 static void 488 test_entryconn_rewrite_automap_exit(void *arg) 489 { 490 entry_connection_t *ec = arg; 491 entry_connection_t *ec2=NULL; 492 rewrite_result_t rr; 493 char *msg = NULL; 494 495 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET); 496 497 smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, 498 ".EXIT"); 499 parse_virtual_addr_network("127.1.0.0/16", AF_INET, 0, &msg); 500 501 /* Try to automap this on resolve. */ 502 strlcpy(ec->socks_request->address, "website.example.exit", 503 sizeof(ec->socks_request->address)); 504 ec->socks_request->command = SOCKS_COMMAND_RESOLVE; 505 connection_ap_handshake_rewrite(ec, &rr); 506 507 /* Make sure it isn't allowed -- there is no longer an AllowDotExit 508 * option. */ 509 tt_int_op(rr.automap, OP_EQ, 0); 510 tt_int_op(rr.should_close, OP_EQ, 1); 511 tt_int_op(rr.end_reason, OP_EQ, END_STREAM_REASON_TORPROTOCOL); 512 513 done: 514 connection_free_minimal(ENTRY_TO_CONN(ec2)); 515 } 516 517 /* Rewrite into .exit because of mapaddress */ 518 static void 519 test_entryconn_rewrite_mapaddress_exit(void *arg) 520 { 521 entry_connection_t *ec = arg; 522 rewrite_result_t rr; 523 524 config_line_append(&get_options_mutable()->AddressMap, 525 "MapAddress", "*.example.com *.example.com.abc.exit"); 526 config_register_addressmaps(get_options()); 527 528 /* Automap this on resolve. */ 529 strlcpy(ec->socks_request->address, "abc.example.com", 530 sizeof(ec->socks_request->address)); 531 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 532 connection_ap_handshake_rewrite(ec, &rr); 533 534 tt_int_op(rr.automap, OP_EQ, 0); 535 tt_int_op(rr.should_close, OP_EQ, 0); 536 tt_int_op(rr.end_reason, OP_EQ, 0); 537 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 538 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_TORRC); 539 tt_str_op(rr.orig_address, OP_EQ, "abc.example.com"); 540 tt_str_op(ec->socks_request->address, OP_EQ, "abc.example.com.abc.exit"); 541 done: 542 ; 543 } 544 545 /* Map foo.onion to longthing.onion, and also automap. */ 546 static void 547 test_entryconn_rewrite_mapaddress_automap_onion(void *arg) 548 { 549 entry_connection_t *ec = arg; 550 entry_connection_t *ec2 = NULL; 551 entry_connection_t *ec3 = NULL; 552 entry_connection_t *ec4 = NULL; 553 rewrite_result_t rr; 554 char *msg = NULL; 555 556 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET); 557 ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET); 558 ec4 = entry_connection_new(CONN_TYPE_AP, AF_INET); 559 560 get_options_mutable()->AutomapHostsOnResolve = 1; 561 smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, 562 ".onion"); 563 parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg); 564 config_line_append(&get_options_mutable()->AddressMap, 565 "MapAddress", "foo.onion abcdefghijklmnop.onion"); 566 config_register_addressmaps(get_options()); 567 568 /* Connect to foo.onion. */ 569 strlcpy(ec->socks_request->address, "foo.onion", 570 sizeof(ec->socks_request->address)); 571 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 572 connection_ap_handshake_rewrite(ec, &rr); 573 574 tt_int_op(rr.automap, OP_EQ, 0); 575 tt_int_op(rr.should_close, OP_EQ, 0); 576 tt_int_op(rr.end_reason, OP_EQ, 0); 577 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 578 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 579 tt_str_op(rr.orig_address, OP_EQ, "foo.onion"); 580 tt_str_op(ec->socks_request->address, OP_EQ, "abcdefghijklmnop.onion"); 581 582 /* Okay, resolve foo.onion */ 583 strlcpy(ec2->socks_request->address, "foo.onion", 584 sizeof(ec2->socks_request->address)); 585 ec2->socks_request->command = SOCKS_COMMAND_RESOLVE; 586 connection_ap_handshake_rewrite(ec2, &rr); 587 588 tt_int_op(rr.automap, OP_EQ, 1); 589 tt_int_op(rr.should_close, OP_EQ, 0); 590 tt_int_op(rr.end_reason, OP_EQ, 0); 591 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 592 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 593 tt_str_op(rr.orig_address, OP_EQ, "foo.onion"); 594 tt_assert(!strcmpstart(ec2->socks_request->address, "192.168.")); 595 596 /* Now connect */ 597 strlcpy(ec3->socks_request->address, ec2->socks_request->address, 598 sizeof(ec3->socks_request->address)); 599 ec3->socks_request->command = SOCKS_COMMAND_CONNECT; 600 connection_ap_handshake_rewrite(ec3, &rr); 601 tt_int_op(rr.automap, OP_EQ, 0); 602 tt_int_op(rr.should_close, OP_EQ, 0); 603 tt_int_op(rr.end_reason, OP_EQ, 0); 604 tt_assert(!strcmpstart(ec3->socks_request->address, 605 "abcdefghijklmnop.onion")); 606 607 /* Now resolve abcefghijklmnop.onion. */ 608 strlcpy(ec4->socks_request->address, "abcdefghijklmnop.onion", 609 sizeof(ec4->socks_request->address)); 610 ec4->socks_request->command = SOCKS_COMMAND_RESOLVE; 611 connection_ap_handshake_rewrite(ec4, &rr); 612 613 tt_int_op(rr.automap, OP_EQ, 1); 614 tt_int_op(rr.should_close, OP_EQ, 0); 615 tt_int_op(rr.end_reason, OP_EQ, 0); 616 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 617 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 618 tt_str_op(rr.orig_address, OP_EQ, "abcdefghijklmnop.onion"); 619 tt_assert(!strcmpstart(ec4->socks_request->address, "192.168.")); 620 /* XXXX doesn't work 621 tt_str_op(ec4->socks_request->address, OP_EQ, ec2->socks_request->address); 622 */ 623 624 done: 625 connection_free_minimal(ENTRY_TO_CONN(ec2)); 626 connection_free_minimal(ENTRY_TO_CONN(ec3)); 627 connection_free_minimal(ENTRY_TO_CONN(ec4)); 628 } 629 630 static void 631 test_entryconn_rewrite_mapaddress_automap_onion_common(entry_connection_t *ec, 632 int map_to_onion, 633 int map_to_address) 634 { 635 entry_connection_t *ec2 = NULL; 636 entry_connection_t *ec3 = NULL; 637 rewrite_result_t rr; 638 639 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET); 640 ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET); 641 642 /* Connect to irc.example.com */ 643 strlcpy(ec->socks_request->address, "irc.example.com", 644 sizeof(ec->socks_request->address)); 645 ec->socks_request->command = SOCKS_COMMAND_CONNECT; 646 connection_ap_handshake_rewrite(ec, &rr); 647 648 tt_int_op(rr.automap, OP_EQ, 0); 649 tt_int_op(rr.should_close, OP_EQ, 0); 650 tt_int_op(rr.end_reason, OP_EQ, 0); 651 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 652 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 653 tt_str_op(rr.orig_address, OP_EQ, "irc.example.com"); 654 tt_str_op(ec->socks_request->address, OP_EQ, 655 map_to_onion ? "abcdefghijklmnop.onion" : "irc.example.com"); 656 657 /* Okay, resolve irc.example.com */ 658 strlcpy(ec2->socks_request->address, "irc.example.com", 659 sizeof(ec2->socks_request->address)); 660 ec2->socks_request->command = SOCKS_COMMAND_RESOLVE; 661 connection_ap_handshake_rewrite(ec2, &rr); 662 663 tt_int_op(rr.automap, OP_EQ, map_to_onion && map_to_address); 664 tt_int_op(rr.should_close, OP_EQ, 0); 665 tt_int_op(rr.end_reason, OP_EQ, 0); 666 tt_i64_op(rr.map_expires, OP_EQ, TIME_MAX); 667 tt_int_op(rr.exit_source, OP_EQ, ADDRMAPSRC_NONE); 668 tt_str_op(rr.orig_address, OP_EQ, "irc.example.com"); 669 if (map_to_onion && map_to_address) 670 tt_assert(!strcmpstart(ec2->socks_request->address, "192.168.")); 671 672 /* Now connect */ 673 strlcpy(ec3->socks_request->address, ec2->socks_request->address, 674 sizeof(ec3->socks_request->address)); 675 ec3->socks_request->command = SOCKS_COMMAND_CONNECT; 676 connection_ap_handshake_rewrite(ec3, &rr); 677 tt_int_op(rr.automap, OP_EQ, 0); 678 tt_int_op(rr.should_close, OP_EQ, 0); 679 tt_int_op(rr.end_reason, OP_EQ, 0); 680 if (map_to_onion) 681 tt_assert(!strcmpstart(ec3->socks_request->address, 682 "abcdefghijklmnop.onion")); 683 684 done: 685 connection_free_minimal(ENTRY_TO_CONN(ec2)); 686 connection_free_minimal(ENTRY_TO_CONN(ec3)); 687 } 688 689 /* This time is the same, but we start with a mapping from a non-onion 690 * address. */ 691 static void 692 test_entryconn_rewrite_mapaddress_automap_onion2(void *arg) 693 { 694 char *msg = NULL; 695 get_options_mutable()->AutomapHostsOnResolve = 1; 696 smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, 697 ".onion"); 698 parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg); 699 config_line_append(&get_options_mutable()->AddressMap, 700 "MapAddress", "irc.example.com abcdefghijklmnop.onion"); 701 config_register_addressmaps(get_options()); 702 703 test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 1, 1); 704 } 705 706 /* Same as above, with automapped turned off */ 707 static void 708 test_entryconn_rewrite_mapaddress_automap_onion3(void *arg) 709 { 710 config_line_append(&get_options_mutable()->AddressMap, 711 "MapAddress", "irc.example.com abcdefghijklmnop.onion"); 712 config_register_addressmaps(get_options()); 713 714 test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 1, 0); 715 } 716 717 /* As above, with no mapping. */ 718 static void 719 test_entryconn_rewrite_mapaddress_automap_onion4(void *arg) 720 { 721 char *msg = NULL; 722 get_options_mutable()->AutomapHostsOnResolve = 1; 723 smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, 724 ".onion"); 725 parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg); 726 727 test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1); 728 } 729 730 /** Test that rewrite functions can handle v3 onion addresses */ 731 static void 732 test_entryconn_rewrite_onion_v3(void *arg) 733 { 734 int retval; 735 entry_connection_t *conn = arg; 736 737 (void) arg; 738 739 hs_cache_init(); 740 741 /* Make a SOCKS request */ 742 conn->socks_request->command = SOCKS_COMMAND_CONNECT; 743 strlcpy(conn->socks_request->address, 744 "git.25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion", 745 sizeof(conn->socks_request->address)); 746 747 /* Make an onion connection using the SOCKS request */ 748 conn->entry_cfg.onion_traffic = 1; 749 ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_SOCKS_WAIT; 750 tt_assert(!ENTRY_TO_EDGE_CONN(conn)->hs_ident); 751 752 /* Handle SOCKS and rewrite! */ 753 retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); 754 tt_int_op(retval, OP_EQ, 0); 755 756 /* Check connection state after rewrite. It should be in waiting for 757 * descriptor state. */ 758 tt_int_op(ENTRY_TO_CONN(conn)->state, OP_EQ, AP_CONN_STATE_RENDDESC_WAIT); 759 /* check that the address got rewritten */ 760 tt_str_op(conn->socks_request->address, OP_EQ, 761 "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid"); 762 /* check that HS information got attached to the connection */ 763 tt_assert(ENTRY_TO_EDGE_CONN(conn)->hs_ident); 764 765 done: 766 hs_free_all(); 767 /* 'conn' is cleaned by handler */ 768 } 769 770 #define REWRITE(name) \ 771 { #name, test_entryconn_##name, TT_FORK, &test_rewrite_setup, NULL } 772 773 struct testcase_t entryconn_tests[] = { 774 REWRITE(rewrite_basic), 775 REWRITE(rewrite_bad_dotexit), 776 REWRITE(rewrite_automap_ipv4), 777 REWRITE(rewrite_automap_ipv6), 778 // REWRITE(rewrite_automap_reverse), 779 REWRITE(rewrite_cached_dns_ipv4), 780 REWRITE(rewrite_cached_dns_ipv6), 781 REWRITE(rewrite_unmapped_virtual), 782 REWRITE(rewrite_mapaddress), 783 REWRITE(rewrite_reject_internal_reverse), 784 REWRITE(rewrite_automap_exit), 785 REWRITE(rewrite_mapaddress_exit), 786 REWRITE(rewrite_mapaddress_automap_onion), 787 REWRITE(rewrite_mapaddress_automap_onion2), 788 REWRITE(rewrite_mapaddress_automap_onion3), 789 REWRITE(rewrite_mapaddress_automap_onion4), 790 REWRITE(rewrite_onion_v3), 791 792 END_OF_TESTCASES 793 };