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 : #include "orconfig.h"
7 : #define PT_PRIVATE
8 : #define STATEFILE_PRIVATE
9 : #define CONTROL_EVENTS_PRIVATE
10 : #define PROCESS_PRIVATE
11 : #include "core/or/or.h"
12 : #include "app/config/config.h"
13 : #include "lib/confmgt/confmgt.h"
14 : #include "feature/control/control.h"
15 : #include "feature/control/control_events.h"
16 : #include "feature/client/transports.h"
17 : #include "core/or/circuitbuild.h"
18 : #include "app/config/statefile.h"
19 : #include "test/test.h"
20 : #include "lib/encoding/confline.h"
21 : #include "lib/net/resolve.h"
22 : #include "lib/process/process.h"
23 :
24 : #include "app/config/or_state_st.h"
25 :
26 : #include "test/log_test_helpers.h"
27 :
28 : static void
29 12 : reset_mp(managed_proxy_t *mp)
30 : {
31 12 : mp->conf_state = PT_PROTO_LAUNCHED;
32 16 : SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
33 12 : smartlist_clear(mp->transports);
34 12 : }
35 :
36 : static void
37 1 : test_pt_parsing(void *arg)
38 : {
39 1 : char line[200];
40 1 : transport_t *transport = NULL;
41 1 : tor_addr_t test_addr;
42 :
43 1 : managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
44 1 : (void)arg;
45 1 : mp->conf_state = PT_PROTO_INFANT;
46 1 : mp->transports = smartlist_new();
47 :
48 : /* incomplete cmethod */
49 1 : strlcpy(line,"CMETHOD trebuchet",sizeof(line));
50 1 : tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);
51 :
52 1 : reset_mp(mp);
53 :
54 : /* wrong proxy type */
55 1 : strlcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999",sizeof(line));
56 1 : tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);
57 :
58 1 : reset_mp(mp);
59 :
60 : /* wrong addrport */
61 1 : strlcpy(line,"CMETHOD trebuchet socks4 abcd",sizeof(line));
62 1 : tt_int_op(parse_cmethod_line(line, mp), OP_LT, 0);
63 :
64 1 : reset_mp(mp);
65 :
66 : /* correct line */
67 1 : strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
68 1 : tt_int_op(parse_cmethod_line(line, mp), OP_EQ, 0);
69 1 : tt_int_op(smartlist_len(mp->transports), OP_EQ, 1);
70 1 : transport = smartlist_get(mp->transports, 0);
71 : /* test registered address of transport */
72 1 : tor_addr_parse(&test_addr, "127.0.0.1");
73 1 : tt_assert(tor_addr_eq(&test_addr, &transport->addr));
74 : /* test registered port of transport */
75 1 : tt_uint_op(transport->port, OP_EQ, 1999);
76 : /* test registered SOCKS version of transport */
77 1 : tt_int_op(transport->socks_version, OP_EQ, PROXY_SOCKS5);
78 : /* test registered name of transport */
79 1 : tt_str_op(transport->name,OP_EQ, "trebuchet");
80 :
81 1 : reset_mp(mp);
82 :
83 : /* incomplete smethod */
84 1 : strlcpy(line,"SMETHOD trebuchet",sizeof(line));
85 1 : tt_int_op(parse_smethod_line(line, mp), OP_LT, 0);
86 :
87 1 : reset_mp(mp);
88 :
89 : /* wrong addr type */
90 1 : strlcpy(line,"SMETHOD trebuchet abcd",sizeof(line));
91 1 : tt_int_op(parse_smethod_line(line, mp), OP_LT, 0);
92 :
93 1 : reset_mp(mp);
94 :
95 : /* cowwect */
96 1 : strlcpy(line,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line));
97 1 : tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0);
98 1 : tt_int_op(smartlist_len(mp->transports), OP_EQ, 1);
99 1 : transport = smartlist_get(mp->transports, 0);
100 : /* test registered address of transport */
101 1 : tor_addr_parse(&test_addr, "127.0.0.2");
102 1 : tt_assert(tor_addr_eq(&test_addr, &transport->addr));
103 : /* test registered port of transport */
104 1 : tt_uint_op(transport->port, OP_EQ, 2999);
105 : /* test registered name of transport */
106 1 : tt_str_op(transport->name,OP_EQ, "trebuchy");
107 :
108 1 : reset_mp(mp);
109 :
110 : /* Include some arguments. Good ones. */
111 1 : strlcpy(line,"SMETHOD trebuchet 127.0.0.1:9999 "
112 : "ARGS:counterweight=3,sling=snappy",
113 : sizeof(line));
114 1 : tt_int_op(parse_smethod_line(line, mp), OP_EQ, 0);
115 1 : tt_int_op(1, OP_EQ, smartlist_len(mp->transports));
116 : {
117 1 : const transport_t *transport_ = smartlist_get(mp->transports, 0);
118 1 : tt_assert(transport_);
119 1 : tt_str_op(transport_->name, OP_EQ, "trebuchet");
120 1 : tt_int_op(transport_->port, OP_EQ, 9999);
121 1 : tt_str_op(fmt_addr(&transport_->addr), OP_EQ, "127.0.0.1");
122 1 : tt_str_op(transport_->extra_info_args, OP_EQ,
123 : "counterweight=3,sling=snappy");
124 : }
125 1 : reset_mp(mp);
126 :
127 : /* unsupported version */
128 1 : strlcpy(line,"VERSION 666",sizeof(line));
129 1 : tt_int_op(parse_version(line, mp), OP_LT, 0);
130 :
131 : /* incomplete VERSION */
132 1 : strlcpy(line,"VERSION ",sizeof(line));
133 1 : tt_int_op(parse_version(line, mp), OP_LT, 0);
134 :
135 : /* correct VERSION */
136 1 : strlcpy(line,"VERSION 1",sizeof(line));
137 1 : tt_int_op(parse_version(line, mp), OP_EQ, 0);
138 :
139 1 : done:
140 1 : reset_mp(mp);
141 1 : smartlist_free(mp->transports);
142 1 : tor_free(mp);
143 1 : }
144 :
145 : static void
146 1 : test_pt_get_transport_options(void *arg)
147 : {
148 1 : char **execve_args;
149 1 : smartlist_t *transport_list = smartlist_new();
150 1 : managed_proxy_t *mp;
151 1 : or_options_t *options = get_options_mutable();
152 1 : char *opt_str = NULL;
153 1 : config_line_t *cl = NULL;
154 1 : (void)arg;
155 :
156 1 : execve_args = tor_malloc(sizeof(char*)*2);
157 1 : execve_args[0] = tor_strdup("cheeseshop");
158 1 : execve_args[1] = NULL;
159 :
160 1 : mp = managed_proxy_create(transport_list, execve_args, 1);
161 1 : tt_ptr_op(mp, OP_NE, NULL);
162 1 : opt_str = get_transport_options_for_server_proxy(mp);
163 1 : tt_ptr_op(opt_str, OP_EQ, NULL);
164 :
165 1 : smartlist_add_strdup(mp->transports_to_launch, "gruyere");
166 1 : smartlist_add_strdup(mp->transports_to_launch, "roquefort");
167 1 : smartlist_add_strdup(mp->transports_to_launch, "stnectaire");
168 :
169 1 : tt_assert(options);
170 :
171 1 : cl = tor_malloc_zero(sizeof(config_line_t));
172 1 : cl->value = tor_strdup("gruyere melty=10 hardness=se;ven");
173 1 : options->ServerTransportOptions = cl;
174 :
175 1 : cl = tor_malloc_zero(sizeof(config_line_t));
176 1 : cl->value = tor_strdup("stnectaire melty=4 hardness=three");
177 1 : cl->next = options->ServerTransportOptions;
178 1 : options->ServerTransportOptions = cl;
179 :
180 1 : cl = tor_malloc_zero(sizeof(config_line_t));
181 1 : cl->value = tor_strdup("pepperjack melty=12 hardness=five");
182 1 : cl->next = options->ServerTransportOptions;
183 1 : options->ServerTransportOptions = cl;
184 :
185 1 : opt_str = get_transport_options_for_server_proxy(mp);
186 1 : tt_str_op(opt_str, OP_EQ,
187 : "gruyere:melty=10;gruyere:hardness=se\\;ven;"
188 : "stnectaire:melty=4;stnectaire:hardness=three");
189 :
190 1 : done:
191 1 : tor_free(opt_str);
192 1 : config_free_lines(cl);
193 1 : managed_proxy_destroy(mp, 0);
194 1 : smartlist_free(transport_list);
195 1 : }
196 :
197 : static void
198 1 : test_pt_protocol(void *arg)
199 : {
200 1 : char line[200];
201 :
202 1 : managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
203 1 : (void)arg;
204 1 : mp->conf_state = PT_PROTO_LAUNCHED;
205 1 : mp->transports = smartlist_new();
206 1 : mp->argv = tor_calloc(2, sizeof(char *));
207 1 : mp->argv[0] = tor_strdup("<testcase>");
208 :
209 : /* various wrong protocol runs: */
210 :
211 1 : strlcpy(line,"VERSION 1",sizeof(line));
212 1 : handle_proxy_line(line, mp);
213 1 : tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
214 :
215 1 : strlcpy(line,"VERSION 1",sizeof(line));
216 1 : handle_proxy_line(line, mp);
217 1 : tt_assert(mp->conf_state == PT_PROTO_BROKEN);
218 :
219 1 : reset_mp(mp);
220 :
221 1 : strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
222 1 : handle_proxy_line(line, mp);
223 1 : tt_assert(mp->conf_state == PT_PROTO_BROKEN);
224 :
225 1 : reset_mp(mp);
226 :
227 : /* correct protocol run: */
228 1 : strlcpy(line,"VERSION 1",sizeof(line));
229 1 : handle_proxy_line(line, mp);
230 1 : tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
231 :
232 1 : strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
233 1 : handle_proxy_line(line, mp);
234 1 : tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
235 :
236 1 : strlcpy(line,"CMETHODS DONE",sizeof(line));
237 1 : handle_proxy_line(line, mp);
238 1 : tt_assert(mp->conf_state == PT_PROTO_CONFIGURED);
239 :
240 1 : done:
241 1 : reset_mp(mp);
242 1 : smartlist_free(mp->transports);
243 1 : tor_free(mp->argv[0]);
244 1 : tor_free(mp->argv);
245 1 : tor_free(mp);
246 1 : }
247 :
248 : static void
249 1 : test_pt_get_extrainfo_string(void *arg)
250 : {
251 1 : managed_proxy_t *mp1 = NULL, *mp2 = NULL;
252 1 : char **argv1, **argv2;
253 1 : smartlist_t *t1 = smartlist_new(), *t2 = smartlist_new();
254 1 : int r;
255 1 : char *s = NULL;
256 1 : (void) arg;
257 :
258 1 : argv1 = tor_malloc_zero(sizeof(char*)*3);
259 1 : argv1[0] = tor_strdup("ewige");
260 1 : argv1[1] = tor_strdup("Blumenkraft");
261 1 : argv1[2] = NULL;
262 1 : argv2 = tor_malloc_zero(sizeof(char*)*4);
263 1 : argv2[0] = tor_strdup("und");
264 1 : argv2[1] = tor_strdup("ewige");
265 1 : argv2[2] = tor_strdup("Schlangenkraft");
266 1 : argv2[3] = NULL;
267 :
268 1 : mp1 = managed_proxy_create(t1, argv1, 1);
269 1 : mp2 = managed_proxy_create(t2, argv2, 1);
270 :
271 1 : r = parse_smethod_line("SMETHOD hagbard 127.0.0.1:5555", mp1);
272 1 : tt_int_op(r, OP_EQ, 0);
273 1 : r = parse_smethod_line("SMETHOD celine 127.0.0.1:1723 ARGS:card=no-enemy",
274 : mp2);
275 1 : tt_int_op(r, OP_EQ, 0);
276 :
277 : /* Force these proxies to look "completed" or they won't generate output. */
278 1 : mp1->conf_state = mp2->conf_state = PT_PROTO_COMPLETED;
279 :
280 1 : s = pt_get_extra_info_descriptor_string();
281 1 : tt_assert(s);
282 1 : tt_str_op(s, OP_EQ,
283 : "transport hagbard 127.0.0.1:5555\n"
284 : "transport celine 127.0.0.1:1723 card=no-enemy\n");
285 :
286 1 : done:
287 : /* XXXX clean up better */
288 1 : smartlist_free(t1);
289 1 : smartlist_free(t2);
290 1 : tor_free(s);
291 1 : }
292 :
293 : static int
294 8 : process_read_stdout_replacement(process_t *process, buf_t *buffer)
295 : {
296 8 : (void)process;
297 8 : static int times_called = 0;
298 :
299 : /* Generate some dummy CMETHOD lines the first 5 times. The 6th
300 : time, send 'CMETHODS DONE' to finish configuring the proxy. */
301 8 : times_called++;
302 :
303 8 : if (times_called <= 5) {
304 5 : buf_add_printf(buffer, "SMETHOD mock%d 127.0.0.1:555%d\n",
305 : times_called, times_called);
306 3 : } else if (times_called <= 6) {
307 1 : buf_add_string(buffer, "SMETHODS DONE\n");
308 2 : } else if (times_called <= 7) {
309 1 : buf_add_string(buffer, "LOG SEVERITY=error MESSAGE=\"Oh noes, something "
310 : "bad happened. What do we do!?\"\n");
311 1 : buf_add_string(buffer, "LOG SEVERITY=warning MESSAGE=\"warning msg\"\n");
312 1 : buf_add_string(buffer, "LOG SEVERITY=notice MESSAGE=\"notice msg\"\n");
313 1 : buf_add_string(buffer, "LOG SEVERITY=info MESSAGE=\"info msg\"\n");
314 1 : buf_add_string(buffer, "LOG SEVERITY=debug MESSAGE=\"debug msg\"\n");
315 1 : } else if (times_called <= 8) {
316 1 : buf_add_string(buffer, "STATUS TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\n");
317 1 : buf_add_string(buffer, "STATUS TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\n");
318 1 : buf_add_string(buffer, "STATUS TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\n");
319 : }
320 :
321 8 : return (int)buf_datalen(buffer);
322 : }
323 :
324 : static or_state_t *dummy_state = NULL;
325 :
326 : static or_state_t *
327 11 : get_or_state_replacement(void)
328 : {
329 11 : return dummy_state;
330 : }
331 :
332 : static int controlevent_n = 0;
333 : static uint16_t controlevent_event = 0;
334 : static smartlist_t *controlevent_msgs = NULL;
335 :
336 : static void
337 13 : queue_control_event_string_replacement(uint16_t event, char *msg)
338 : {
339 13 : ++controlevent_n;
340 13 : controlevent_event = event;
341 13 : if (!controlevent_msgs)
342 1 : controlevent_msgs = smartlist_new();
343 13 : smartlist_add(controlevent_msgs, msg);
344 13 : }
345 :
346 : /* Test the configure_proxy() function. */
347 : static void
348 1 : test_pt_configure_proxy(void *arg)
349 : {
350 1 : int i, retval;
351 1 : managed_proxy_t *mp = NULL;
352 1 : (void) arg;
353 :
354 1 : dummy_state = or_state_new();
355 :
356 1 : MOCK(process_read_stdout, process_read_stdout_replacement);
357 1 : MOCK(get_or_state,
358 : get_or_state_replacement);
359 1 : MOCK(queue_control_event_string,
360 : queue_control_event_string_replacement);
361 :
362 1 : control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED);
363 :
364 1 : mp = tor_malloc_zero(sizeof(managed_proxy_t));
365 1 : mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
366 1 : mp->transports = smartlist_new();
367 1 : mp->transports_to_launch = smartlist_new();
368 1 : mp->argv = tor_malloc_zero(sizeof(char*)*2);
369 1 : mp->argv[0] = tor_strdup("<testcase>");
370 1 : mp->is_server = 1;
371 :
372 : /* Configure the process. */
373 1 : mp->process = process_new("");
374 1 : process_set_stdout_read_callback(mp->process, managed_proxy_stdout_callback);
375 1 : process_set_data(mp->process, mp);
376 :
377 : /* Test the return value of configure_proxy() by calling it some
378 : times while it is uninitialized and then finally finalizing its
379 : configuration. */
380 1 : for (i = 0 ; i < 5 ; i++) {
381 : /* force a read from our mocked stdout reader. */
382 5 : process_notify_event_stdout(mp->process);
383 : /* try to configure our proxy. */
384 5 : retval = configure_proxy(mp);
385 : /* retval should be zero because proxy hasn't finished configuring yet */
386 5 : tt_int_op(retval, OP_EQ, 0);
387 : /* check the number of registered transports */
388 5 : tt_int_op(smartlist_len(mp->transports), OP_EQ, i+1);
389 : /* check that the mp is still waiting for transports */
390 11 : tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
391 : }
392 :
393 : /* Get the SMETHOD DONE written to the process. */
394 1 : process_notify_event_stdout(mp->process);
395 :
396 : /* this last configure_proxy() should finalize the proxy configuration. */
397 1 : retval = configure_proxy(mp);
398 : /* retval should be 1 since the proxy finished configuring */
399 1 : tt_int_op(retval, OP_EQ, 1);
400 : /* check the mp state */
401 1 : tt_assert(mp->conf_state == PT_PROTO_COMPLETED);
402 :
403 1 : tt_int_op(controlevent_n, OP_EQ, 5);
404 1 : tt_int_op(controlevent_event, OP_EQ, EVENT_TRANSPORT_LAUNCHED);
405 1 : tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 5);
406 1 : smartlist_sort_strings(controlevent_msgs);
407 1 : tt_str_op(smartlist_get(controlevent_msgs, 0), OP_EQ,
408 : "650 TRANSPORT_LAUNCHED server mock1 127.0.0.1 5551\r\n");
409 1 : tt_str_op(smartlist_get(controlevent_msgs, 1), OP_EQ,
410 : "650 TRANSPORT_LAUNCHED server mock2 127.0.0.1 5552\r\n");
411 1 : tt_str_op(smartlist_get(controlevent_msgs, 2), OP_EQ,
412 : "650 TRANSPORT_LAUNCHED server mock3 127.0.0.1 5553\r\n");
413 1 : tt_str_op(smartlist_get(controlevent_msgs, 3), OP_EQ,
414 : "650 TRANSPORT_LAUNCHED server mock4 127.0.0.1 5554\r\n");
415 1 : tt_str_op(smartlist_get(controlevent_msgs, 4), OP_EQ,
416 : "650 TRANSPORT_LAUNCHED server mock5 127.0.0.1 5555\r\n");
417 :
418 : /* Get the log message out. */
419 1 : setup_full_capture_of_logs(LOG_ERR);
420 1 : process_notify_event_stdout(mp->process);
421 1 : expect_single_log_msg_containing("Oh noes, something bad happened");
422 1 : teardown_capture_of_logs();
423 :
424 1 : tt_int_op(controlevent_n, OP_EQ, 10);
425 1 : tt_int_op(controlevent_event, OP_EQ, EVENT_PT_LOG);
426 1 : tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 10);
427 1 : tt_str_op(smartlist_get(controlevent_msgs, 5), OP_EQ,
428 : "650 PT_LOG PT=<testcase> SEVERITY=error "
429 : "MESSAGE=\"Oh noes, "
430 : "something bad happened. What do we do!?\"\r\n");
431 1 : tt_str_op(smartlist_get(controlevent_msgs, 6), OP_EQ,
432 : "650 PT_LOG PT=<testcase> SEVERITY=warning "
433 : "MESSAGE=\"warning msg\"\r\n");
434 1 : tt_str_op(smartlist_get(controlevent_msgs, 7), OP_EQ,
435 : "650 PT_LOG PT=<testcase> SEVERITY=notice "
436 : "MESSAGE=\"notice msg\"\r\n");
437 1 : tt_str_op(smartlist_get(controlevent_msgs, 8), OP_EQ,
438 : "650 PT_LOG PT=<testcase> SEVERITY=info "
439 : "MESSAGE=\"info msg\"\r\n");
440 1 : tt_str_op(smartlist_get(controlevent_msgs, 9), OP_EQ,
441 : "650 PT_LOG PT=<testcase> SEVERITY=debug "
442 : "MESSAGE=\"debug msg\"\r\n");
443 :
444 : /* Get the STATUS messages out. */
445 1 : process_notify_event_stdout(mp->process);
446 :
447 1 : tt_int_op(controlevent_n, OP_EQ, 13);
448 1 : tt_int_op(controlevent_event, OP_EQ, EVENT_PT_STATUS);
449 1 : tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 13);
450 :
451 1 : tt_str_op(smartlist_get(controlevent_msgs, 10), OP_EQ,
452 : "650 PT_STATUS "
453 : "PT=<testcase> TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\r\n");
454 1 : tt_str_op(smartlist_get(controlevent_msgs, 11), OP_EQ,
455 : "650 PT_STATUS "
456 : "PT=<testcase> TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\r\n");
457 1 : tt_str_op(smartlist_get(controlevent_msgs, 12), OP_EQ,
458 : "650 PT_STATUS "
459 : "PT=<testcase> TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\r\n");
460 :
461 : { /* check that the transport info were saved properly in the tor state */
462 1 : config_line_t *transport_in_state = NULL;
463 1 : smartlist_t *transport_info_sl = smartlist_new();
464 1 : char *name_of_transport = NULL;
465 1 : char *bindaddr = NULL;
466 :
467 : /* Get the bindaddr for "mock1" and check it against the bindaddr
468 : that the mocked tor_get_lines_from_handle() generated. */
469 1 : transport_in_state = get_transport_in_state_by_name("mock1");
470 1 : tt_assert(transport_in_state);
471 1 : smartlist_split_string(transport_info_sl, transport_in_state->value,
472 : NULL, 0, 0);
473 1 : name_of_transport = smartlist_get(transport_info_sl, 0);
474 1 : bindaddr = smartlist_get(transport_info_sl, 1);
475 1 : tt_str_op(name_of_transport, OP_EQ, "mock1");
476 1 : tt_str_op(bindaddr, OP_EQ, "127.0.0.1:5551");
477 :
478 3 : SMARTLIST_FOREACH(transport_info_sl, char *, cp, tor_free(cp));
479 1 : smartlist_free(transport_info_sl);
480 : }
481 :
482 1 : done:
483 1 : teardown_capture_of_logs();
484 1 : or_state_free(dummy_state);
485 1 : UNMOCK(process_read_stdout);
486 1 : UNMOCK(get_or_state);
487 1 : UNMOCK(queue_control_event_string);
488 1 : if (controlevent_msgs) {
489 14 : SMARTLIST_FOREACH(controlevent_msgs, char *, cp, tor_free(cp));
490 1 : smartlist_free(controlevent_msgs);
491 1 : controlevent_msgs = NULL;
492 : }
493 1 : if (mp->transports) {
494 6 : SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
495 1 : smartlist_free(mp->transports);
496 : }
497 1 : smartlist_free(mp->transports_to_launch);
498 1 : process_free(mp->process);
499 1 : tor_free(mp->argv[0]);
500 1 : tor_free(mp->argv);
501 1 : tor_free(mp);
502 1 : }
503 :
504 : /* Test the get_pt_proxy_uri() function. */
505 : static void
506 1 : test_get_pt_proxy_uri(void *arg)
507 : {
508 1 : or_options_t *options = get_options_mutable();
509 1 : char *uri = NULL;
510 1 : int ret;
511 1 : (void) arg;
512 :
513 : /* Test with no proxy. */
514 1 : uri = get_pt_proxy_uri();
515 1 : tt_ptr_op(uri, OP_EQ, NULL);
516 :
517 : /* Test with a SOCKS4 proxy. */
518 1 : options->Socks4Proxy = tor_strdup("192.0.2.1:1080");
519 2 : ret = tor_addr_port_lookup(options->Socks4Proxy,
520 1 : &options->Socks4ProxyAddr,
521 : &options->Socks4ProxyPort);
522 1 : tt_int_op(ret, OP_EQ, 0);
523 1 : uri = get_pt_proxy_uri();
524 1 : tt_str_op(uri, OP_EQ, "socks4a://192.0.2.1:1080");
525 1 : tor_free(uri);
526 1 : tor_free(options->Socks4Proxy);
527 :
528 : /* Test with a SOCKS5 proxy, no username/password. */
529 1 : options->Socks5Proxy = tor_strdup("192.0.2.1:1080");
530 2 : ret = tor_addr_port_lookup(options->Socks5Proxy,
531 1 : &options->Socks5ProxyAddr,
532 : &options->Socks5ProxyPort);
533 1 : tt_int_op(ret, OP_EQ, 0);
534 1 : uri = get_pt_proxy_uri();
535 1 : tt_str_op(uri, OP_EQ, "socks5://192.0.2.1:1080");
536 1 : tor_free(uri);
537 :
538 : /* Test with a SOCKS5 proxy, with username/password. */
539 1 : options->Socks5ProxyUsername = tor_strdup("hwest");
540 1 : options->Socks5ProxyPassword = tor_strdup("r34n1m470r");
541 1 : uri = get_pt_proxy_uri();
542 1 : tt_str_op(uri, OP_EQ, "socks5://hwest:r34n1m470r@192.0.2.1:1080");
543 1 : tor_free(uri);
544 1 : tor_free(options->Socks5Proxy);
545 1 : tor_free(options->Socks5ProxyUsername);
546 1 : tor_free(options->Socks5ProxyPassword);
547 :
548 : /* Test with a HTTPS proxy, no authenticator. */
549 1 : options->HTTPSProxy = tor_strdup("192.0.2.1:80");
550 2 : ret = tor_addr_port_lookup(options->HTTPSProxy,
551 1 : &options->HTTPSProxyAddr,
552 : &options->HTTPSProxyPort);
553 1 : tt_int_op(ret, OP_EQ, 0);
554 1 : uri = get_pt_proxy_uri();
555 1 : tt_str_op(uri, OP_EQ, "http://192.0.2.1:80");
556 1 : tor_free(uri);
557 :
558 : /* Test with a HTTPS proxy, with authenticator. */
559 1 : options->HTTPSProxyAuthenticator = tor_strdup("hwest:r34n1m470r");
560 1 : uri = get_pt_proxy_uri();
561 1 : tt_str_op(uri, OP_EQ, "http://hwest:r34n1m470r@192.0.2.1:80");
562 1 : tor_free(uri);
563 1 : tor_free(options->HTTPSProxy);
564 1 : tor_free(options->HTTPSProxyAuthenticator);
565 :
566 : /* Token nod to the fact that IPv6 exists. */
567 1 : options->Socks4Proxy = tor_strdup("[2001:db8::1]:1080");
568 1 : ret = tor_addr_port_lookup(options->Socks4Proxy,
569 : &options->Socks4ProxyAddr,
570 : &options->Socks4ProxyPort);
571 1 : tt_int_op(ret, OP_EQ, 0);
572 1 : uri = get_pt_proxy_uri();
573 1 : tt_str_op(uri, OP_EQ, "socks4a://[2001:db8::1]:1080");
574 1 : tor_free(uri);
575 1 : tor_free(options->Socks4Proxy);
576 :
577 0 : done:
578 1 : if (uri)
579 0 : tor_free(uri);
580 1 : }
581 :
582 : #ifndef COCCI
583 : #define PT_LEGACY(name) \
584 : { (#name), test_pt_ ## name , 0, NULL, NULL }
585 : #endif
586 :
587 : struct testcase_t pt_tests[] = {
588 : PT_LEGACY(parsing),
589 : PT_LEGACY(protocol),
590 : { "get_transport_options", test_pt_get_transport_options, TT_FORK,
591 : NULL, NULL },
592 : { "get_extrainfo_string", test_pt_get_extrainfo_string, TT_FORK,
593 : NULL, NULL },
594 : { "configure_proxy",test_pt_configure_proxy, TT_FORK,
595 : NULL, NULL },
596 : { "get_pt_proxy_uri", test_get_pt_proxy_uri, TT_FORK,
597 : NULL, NULL },
598 : END_OF_TESTCASES
599 : };
|