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