Update copyrights to 2021, using "make update-copyright"
[tor.git] / src / test / test_entryconn.c
blob9ab43a90ad4352f99d20bbcfc3e3f253db72ae97
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #include "orconfig.h"
6 #define CONNECTION_PRIVATE
7 #define CONNECTION_EDGE_PRIVATE
9 #include "core/or/or.h"
10 #include "test/test.h"
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"
19 #include "feature/hs/hs_cache.h"
21 #include "core/or/entry_connection_st.h"
22 #include "core/or/socks_request_st.h"
24 #include "lib/encoding/confline.h"
26 static void *
27 entryconn_rewrite_setup(const struct testcase_t *tc)
29 (void)tc;
30 entry_connection_t *ec = entry_connection_new(CONN_TYPE_AP, AF_INET);
31 addressmap_init();
32 return ec;
35 static int
36 entryconn_rewrite_teardown(const struct testcase_t *tc, void *arg)
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;
46 static struct testcase_setup_t test_rewrite_setup = {
47 entryconn_rewrite_setup, entryconn_rewrite_teardown
50 /* Simple rewrite: no changes needed */
51 static void
52 test_entryconn_rewrite_basic(void *arg)
54 entry_connection_t *ec = arg;
55 rewrite_result_t rr;
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);
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");
72 done:
76 /* Rewrite but reject because of disallowed .exit */
77 static void
78 test_entryconn_rewrite_bad_dotexit(void *arg)
80 entry_connection_t *ec = arg;
81 rewrite_result_t rr;
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);
89 tt_int_op(rr.should_close, OP_EQ, 1);
90 tt_int_op(rr.end_reason, OP_EQ, END_STREAM_REASON_TORPROTOCOL);
92 done:
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)
101 entry_connection_t *ec = arg;
102 entry_connection_t *ec2=NULL, *ec3=NULL;
103 rewrite_result_t rr;
104 char *msg = NULL;
106 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET);
107 ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET);
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);
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);
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");
127 tt_assert(!strcmpstart(ec->socks_request->address,"127.202."));
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));
133 ec2->socks_request->command = SOCKS_COMMAND_CONNECT;
134 connection_ap_handshake_rewrite(ec2, &rr);
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");
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);
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");
159 tt_str_op(ec3->socks_request->address, OP_EQ,
160 ec->socks_request->address);
162 done:
163 connection_free_minimal(ENTRY_TO_CONN(ec2));
164 connection_free_minimal(ENTRY_TO_CONN(ec3));
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)
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;
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);
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);
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);
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");
200 /* Yes, this [ should be here. */
201 tt_assert(!strcmpstart(ec->socks_request->address,"[fe80:"));
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));
207 ec2->socks_request->command = SOCKS_COMMAND_CONNECT;
208 connection_ap_handshake_rewrite(ec2, &rr);
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");
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);
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");
233 tt_str_op(ec3->socks_request->address, OP_EQ,
234 ec->socks_request->address);
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));
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)
248 entry_connection_t *ec = arg;
249 entry_connection_t *ec2=NULL;
250 rewrite_result_t rr;
251 char *msg = NULL;
253 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET);
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);
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);
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");
275 tt_assert(!strcmpstart(ec->socks_request->address,"127.80."));
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);
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);
289 done:
290 connection_free_minimal(ENTRY_TO_CONN(ec2));
292 #endif /* 0 */
294 /* Rewrite because of cached DNS entry. */
295 static void
296 test_entryconn_rewrite_cached_dns_ipv4(void *arg)
298 entry_connection_t *ec = arg;
299 rewrite_result_t rr;
300 time_t expires = time(NULL) + 3600;
301 entry_connection_t *ec2=NULL;
303 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET);
305 addressmap_register("www.friendly.example.com",
306 tor_strdup("240.240.241.241"),
307 expires,
308 ADDRMAPSRC_DNS,
309 0, 0, 0);
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));
316 ec->socks_request->command = SOCKS_COMMAND_CONNECT;
317 ec2->socks_request->command = SOCKS_COMMAND_CONNECT;
319 ec2->entry_cfg.use_cached_ipv4_answers = 1; /* only ec2 gets this flag */
320 connection_ap_handshake_rewrite(ec, &rr);
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");
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");
339 done:
340 connection_free_minimal(ENTRY_TO_CONN(ec2));
343 /* Rewrite because of cached DNS entry. */
344 static void
345 test_entryconn_rewrite_cached_dns_ipv6(void *arg)
347 entry_connection_t *ec = NULL;
348 rewrite_result_t rr;
349 time_t expires = time(NULL) + 3600;
350 entry_connection_t *ec2=NULL;
352 (void)arg;
354 ec = entry_connection_new(CONN_TYPE_AP, AF_INET6);
355 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET6);
357 addressmap_register("www.friendly.example.com",
358 tor_strdup("[::f00f]"),
359 expires,
360 ADDRMAPSRC_DNS,
361 0, 0, 0);
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));
368 ec->socks_request->command = SOCKS_COMMAND_CONNECT;
369 ec2->socks_request->command = SOCKS_COMMAND_CONNECT;
371 ec2->entry_cfg.use_cached_ipv6_answers = 1; /* only ec2 gets this flag */
372 connection_ap_handshake_rewrite(ec, &rr);
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");
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]");
391 done:
392 connection_free_minimal(ENTRY_TO_CONN(ec));
393 connection_free_minimal(ENTRY_TO_CONN(ec2));
396 /* Fail to connect to unmapped address in virtual range. */
397 static void
398 test_entryconn_rewrite_unmapped_virtual(void *arg)
400 entry_connection_t *ec = arg;
401 rewrite_result_t rr;
402 entry_connection_t *ec2 = NULL;
403 char *msg = NULL;
405 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET6);
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);
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);
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);
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);
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);
432 done:
433 connection_free_minimal(ENTRY_TO_CONN(ec2));
436 /* Rewrite because of mapaddress option */
437 static void
438 test_entryconn_rewrite_mapaddress(void *arg)
440 entry_connection_t *ec = arg;
441 rewrite_result_t rr;
443 config_line_append(&get_options_mutable()->AddressMap,
444 "MapAddress", "meta metaobjects.example");
445 config_register_addressmaps(get_options());
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);
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");
459 done:
463 /* Reject reverse lookups of internal address. */
464 static void
465 test_entryconn_rewrite_reject_internal_reverse(void *arg)
467 entry_connection_t *ec = arg;
468 rewrite_result_t rr;
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);
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);
482 done:
486 /* Rewrite into .exit because of virtual address mapping. */
487 static void
488 test_entryconn_rewrite_automap_exit(void *arg)
490 entry_connection_t *ec = arg;
491 entry_connection_t *ec2=NULL;
492 rewrite_result_t rr;
493 char *msg = NULL;
495 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET);
497 smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes,
498 ".EXIT");
499 parse_virtual_addr_network("127.1.0.0/16", AF_INET, 0, &msg);
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);
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);
513 done:
514 connection_free_minimal(ENTRY_TO_CONN(ec2));
517 /* Rewrite into .exit because of mapaddress */
518 static void
519 test_entryconn_rewrite_mapaddress_exit(void *arg)
521 entry_connection_t *ec = arg;
522 rewrite_result_t rr;
524 config_line_append(&get_options_mutable()->AddressMap,
525 "MapAddress", "*.example.com *.example.com.abc.exit");
526 config_register_addressmaps(get_options());
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);
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:
545 /* Map foo.onion to longthing.onion, and also automap. */
546 static void
547 test_entryconn_rewrite_mapaddress_automap_onion(void *arg)
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;
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);
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());
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);
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");
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);
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."));
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"));
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);
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);
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));
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)
635 entry_connection_t *ec2 = NULL;
636 entry_connection_t *ec3 = NULL;
637 rewrite_result_t rr;
639 ec2 = entry_connection_new(CONN_TYPE_AP, AF_INET);
640 ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET);
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);
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");
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);
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."));
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"));
684 done:
685 connection_free_minimal(ENTRY_TO_CONN(ec2));
686 connection_free_minimal(ENTRY_TO_CONN(ec3));
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)
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());
703 test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 1, 1);
706 /* Same as above, with automapped turned off */
707 static void
708 test_entryconn_rewrite_mapaddress_automap_onion3(void *arg)
710 config_line_append(&get_options_mutable()->AddressMap,
711 "MapAddress", "irc.example.com abcdefghijklmnop.onion");
712 config_register_addressmaps(get_options());
714 test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 1, 0);
717 /* As above, with no mapping. */
718 static void
719 test_entryconn_rewrite_mapaddress_automap_onion4(void *arg)
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);
727 test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1);
730 /** Test that rewrite functions can handle v3 onion addresses */
731 static void
732 test_entryconn_rewrite_onion_v3(void *arg)
734 int retval;
735 entry_connection_t *conn = arg;
737 (void) arg;
739 hs_cache_init();
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));
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);
752 /* Handle SOCKS and rewrite! */
753 retval = connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL);
754 tt_int_op(retval, OP_EQ, 0);
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);
765 done:
766 hs_free_all();
767 /* 'conn' is cleaned by handler */
770 #define REWRITE(name) \
771 { #name, test_entryconn_##name, TT_FORK, &test_rewrite_setup, NULL }
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),
792 END_OF_TESTCASES