tor-resolve.c (18732B)
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson 2 * Copyright (c) 2007-2021, The Tor Project, Inc. 3 */ 4 /* See LICENSE for licensing information */ 5 6 #include "orconfig.h" 7 8 #include "lib/arch/bytes.h" 9 #include "lib/log/log.h" 10 #include "lib/malloc/malloc.h" 11 #include "lib/net/address.h" 12 #include "lib/net/resolve.h" 13 #include "lib/net/socket.h" 14 #include "lib/sandbox/sandbox.h" 15 #include "lib/string/util_string.h" 16 17 #include "lib/net/socks5_status.h" 18 #include "trunnel/socks5.h" 19 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <stdarg.h> 23 #include <string.h> 24 25 #ifdef HAVE_NETINET_IN_H 26 #include <netinet/in.h> 27 #endif 28 #ifdef HAVE_ARPA_INET_H 29 #include <arpa/inet.h> 30 #endif 31 #ifdef HAVE_SYS_SOCKET_H 32 #include <sys/socket.h> 33 #endif 34 #ifdef HAVE_SYS_TYPES_H 35 #include <sys/types.h> /* Must be included before sys/stat.h for Ultrix */ 36 #endif 37 #ifdef HAVE_ERRNO_H 38 #include <errno.h> 39 #endif 40 41 #ifdef _WIN32 42 #include <winsock2.h> 43 #include <ws2tcpip.h> 44 #endif 45 46 #define RESPONSE_LEN_4 8 47 #define log_sock_error(act, _s) \ 48 STMT_BEGIN \ 49 log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act, \ 50 tor_socket_strerror(tor_socket_errno(_s))); \ 51 STMT_END 52 53 static void usage(void) ATTR_NORETURN; 54 55 /** 56 * Set <b>out</b> to a pointer to newly allocated buffer containing 57 * SOCKS4a RESOLVE request with <b>username</b> and <b>hostname</b>. 58 * Return number of bytes in the buffer if succeeded or -1 if failed. 59 */ 60 static ssize_t 61 build_socks4a_resolve_request(uint8_t **out, 62 const char *username, 63 const char *hostname) 64 { 65 tor_assert(out); 66 tor_assert(username); 67 tor_assert(hostname); 68 69 const char *errmsg = NULL; 70 uint8_t *output = NULL; 71 socks4_client_request_t *rq = socks4_client_request_new(); 72 73 socks4_client_request_set_version(rq, 4); 74 socks4_client_request_set_command(rq, CMD_RESOLVE); 75 socks4_client_request_set_port(rq, 0); 76 socks4_client_request_set_addr(rq, 0x00000001u); 77 socks4_client_request_set_username(rq, username); 78 socks4_client_request_set_socks4a_addr_hostname(rq, hostname); 79 80 errmsg = socks4_client_request_check(rq); 81 if (errmsg) { 82 goto cleanup; 83 } 84 85 ssize_t encoded_len = socks4_client_request_encoded_len(rq); 86 if (encoded_len <= 0) { 87 errmsg = "socks4_client_request_encoded_len failed"; 88 goto cleanup; 89 } 90 91 output = tor_malloc(encoded_len); 92 memset(output, 0, encoded_len); 93 94 encoded_len = socks4_client_request_encode(output, encoded_len, rq); 95 if (encoded_len <= 0) { 96 errmsg = "socks4_client_request_encode failed"; 97 goto cleanup; 98 } 99 100 *out = output; 101 102 cleanup: 103 socks4_client_request_free(rq); 104 if (errmsg) { 105 log_err(LD_NET, "build_socks4a_resolve_request failed: %s", errmsg); 106 *out = NULL; 107 tor_free(output); 108 } 109 return errmsg ? -1 : encoded_len; 110 } 111 112 #define SOCKS5_ATYPE_HOSTNAME 0x03 113 #define SOCKS5_ATYPE_IPV4 0x01 114 #define SOCKS5_ATYPE_IPV6 0x04 115 116 /** 117 * Set <b>out</b> to pointer to newly allocated buffer containing 118 * SOCKS5 RESOLVE/RESOLVE_PTR request with given <b>hostname<b>. 119 * Generate a reverse request if <b>reverse</b> is true. 120 * Return the number of bytes in the buffer if succeeded or -1 if failed. 121 */ 122 static ssize_t 123 build_socks5_resolve_request(uint8_t **out, 124 const char *hostname, 125 int reverse) 126 { 127 const char *errmsg = NULL; 128 uint8_t *outbuf = NULL; 129 int is_ip_address; 130 tor_addr_t addr; 131 size_t addrlen; 132 int ipv6; 133 is_ip_address = tor_addr_parse(&addr, hostname) != -1; 134 if (!is_ip_address && reverse) { 135 log_err(LD_GENERAL, "Tried to do a reverse lookup on a non-IP!"); 136 return -1; 137 } 138 ipv6 = reverse && tor_addr_family(&addr) == AF_INET6; 139 addrlen = reverse ? (ipv6 ? 16 : 4) : 1 + strlen(hostname); 140 if (addrlen > UINT8_MAX) { 141 log_err(LD_GENERAL, "Hostname is too long!"); 142 return -1; 143 } 144 145 socks5_client_request_t *rq = socks5_client_request_new(); 146 147 socks5_client_request_set_version(rq, 5); 148 /* RESOLVE_PTR or RESOLVE */ 149 socks5_client_request_set_command(rq, reverse ? CMD_RESOLVE_PTR : 150 CMD_RESOLVE); 151 socks5_client_request_set_reserved(rq, 0); 152 153 uint8_t atype = SOCKS5_ATYPE_HOSTNAME; 154 if (reverse) 155 atype = ipv6 ? SOCKS5_ATYPE_IPV6 : SOCKS5_ATYPE_IPV4; 156 157 socks5_client_request_set_atype(rq, atype); 158 159 switch (atype) { 160 case SOCKS5_ATYPE_IPV4: { 161 socks5_client_request_set_dest_addr_ipv4(rq, 162 tor_addr_to_ipv4h(&addr)); 163 } break; 164 case SOCKS5_ATYPE_IPV6: { 165 uint8_t *ipv6_array = 166 socks5_client_request_getarray_dest_addr_ipv6(rq); 167 168 tor_assert(ipv6_array); 169 170 memcpy(ipv6_array, tor_addr_to_in6_addr8(&addr), 16); 171 } break; 172 173 case SOCKS5_ATYPE_HOSTNAME: { 174 domainname_t *dn = domainname_new(); 175 domainname_set_len(dn, addrlen - 1); 176 domainname_setlen_name(dn, addrlen - 1); 177 char *dn_buf = domainname_getarray_name(dn); 178 memcpy(dn_buf, hostname, addrlen - 1); 179 180 errmsg = domainname_check(dn); 181 182 if (errmsg) { 183 domainname_free(dn); 184 goto cleanup; 185 } else { 186 socks5_client_request_set_dest_addr_domainname(rq, dn); 187 } 188 } break; 189 default: 190 tor_assert_unreached(); 191 break; 192 } 193 194 socks5_client_request_set_dest_port(rq, 0); 195 196 errmsg = socks5_client_request_check(rq); 197 if (errmsg) { 198 goto cleanup; 199 } 200 201 ssize_t encoded_len = socks5_client_request_encoded_len(rq); 202 if (encoded_len < 0) { 203 errmsg = "Cannot predict encoded length"; 204 goto cleanup; 205 } 206 207 outbuf = tor_malloc(encoded_len); 208 memset(outbuf, 0, encoded_len); 209 210 encoded_len = socks5_client_request_encode(outbuf, encoded_len, rq); 211 if (encoded_len < 0) { 212 errmsg = "encoding failed"; 213 goto cleanup; 214 } 215 216 *out = outbuf; 217 218 cleanup: 219 socks5_client_request_free(rq); 220 if (errmsg) { 221 tor_free(outbuf); 222 log_err(LD_NET, "build_socks5_resolve_request failed with error: %s", 223 errmsg); 224 } 225 226 return errmsg ? -1 : encoded_len; 227 } 228 229 /** Set *<b>out</b> to a newly allocated SOCKS4a resolve request with 230 * <b>username</b> and <b>hostname</b> as provided. Return the number 231 * of bytes in the request. */ 232 static ssize_t 233 build_socks_resolve_request(uint8_t **out, 234 const char *username, 235 const char *hostname, 236 int reverse, 237 int version) 238 { 239 tor_assert(out); 240 tor_assert(username); 241 tor_assert(hostname); 242 243 tor_assert(version == 4 || version == 5); 244 245 if (version == 4) { 246 return build_socks4a_resolve_request(out, username, hostname); 247 } else if (version == 5) { 248 return build_socks5_resolve_request(out, hostname, reverse); 249 } 250 251 tor_assert_unreached(); 252 return -1; 253 } 254 255 static void 256 onion_hs_warning(const char *hostname) 257 { 258 log_warn(LD_NET, 259 "%s is a hidden service; those don't have IP addresses. " 260 "You can use the AutomapHostsOnResolve option to have Tor return a " 261 "fake address for hidden services. Or you can have your " 262 "application send the address to Tor directly; we recommend an " 263 "application that uses SOCKS 5 with hostnames.", 264 hostname); 265 } 266 267 static void 268 onion_exit_warning(const char *hostname) 269 { 270 log_warn(LD_NET, 271 "%s is a link pointing to an exit node; however, .exit domains" 272 "have been long defunct and are not valid anymore.", 273 hostname); 274 } 275 276 /** Given a <b>len</b>-byte SOCKS4a response in <b>response</b>, set 277 * *<b>addr_out</b> to the address it contains (in host order). 278 * Return 0 on success, -1 on error. 279 */ 280 static int 281 parse_socks4a_resolve_response(const char *hostname, 282 const char *response, size_t len, 283 tor_addr_t *addr_out) 284 { 285 int result = 0; 286 uint8_t status; 287 tor_assert(response); 288 tor_assert(addr_out); 289 290 socks4_server_reply_t *reply; 291 292 ssize_t parsed = socks4_server_reply_parse(&reply, 293 (const uint8_t *)response, 294 len); 295 296 if (parsed == -1) { 297 log_warn(LD_PROTOCOL, "Failed parsing SOCKS4a response"); 298 result = -1; goto cleanup; 299 } 300 301 if (parsed == -2) { 302 log_warn(LD_PROTOCOL,"Truncated socks response."); 303 result = -1; goto cleanup; 304 } 305 306 if (socks4_server_reply_get_version(reply) != 0) { /* version: 0 */ 307 log_warn(LD_PROTOCOL,"Nonzero version in socks response: bad format."); 308 result = -1; goto cleanup; 309 } 310 if (socks4_server_reply_get_port(reply) != 0) { /* port: 0 */ 311 log_warn(LD_PROTOCOL,"Nonzero port in socks response: bad format."); 312 result = -1; goto cleanup; 313 } 314 status = socks4_server_reply_get_status(reply); 315 if (status != 90) { 316 log_warn(LD_NET,"Got status response '%d': socks request failed.", status); 317 if (!strcasecmpend(hostname, ".onion")) { 318 onion_hs_warning(hostname); 319 result = -1; goto cleanup; 320 } 321 322 if (!strcasecmpend(hostname, ".exit")) { 323 onion_exit_warning(hostname); 324 result = -1; goto cleanup; 325 } 326 327 result = -1; goto cleanup; 328 } 329 330 tor_addr_from_ipv4h(addr_out, socks4_server_reply_get_addr(reply)); 331 332 cleanup: 333 socks4_server_reply_free(reply); 334 return result; 335 } 336 337 /* It would be nice to let someone know what SOCKS5 issue a user may have */ 338 static const char * 339 socks5_reason_to_string(char reason) 340 { 341 switch (reason) { 342 case SOCKS5_SUCCEEDED: 343 return "succeeded"; 344 case SOCKS5_GENERAL_ERROR: 345 return "general error"; 346 case SOCKS5_NOT_ALLOWED: 347 return "not allowed"; 348 case SOCKS5_NET_UNREACHABLE: 349 return "network is unreachable"; 350 case SOCKS5_HOST_UNREACHABLE: 351 return "host is unreachable"; 352 case SOCKS5_CONNECTION_REFUSED: 353 return "connection refused"; 354 case SOCKS5_TTL_EXPIRED: 355 return "ttl expired"; 356 case SOCKS5_COMMAND_NOT_SUPPORTED: 357 return "command not supported"; 358 case SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED: 359 return "address type not supported"; 360 default: 361 return "unknown SOCKS5 code"; 362 } 363 } 364 365 /** Send a resolve request for <b>hostname</b> to the Tor listening on 366 * <b>sockshost</b>:<b>socksport</b>. Store the resulting IPv4 367 * address (in host order) into *<b>result_addr</b>. 368 */ 369 static int 370 do_resolve(const char *hostname, 371 const tor_addr_t *sockshost, uint16_t socksport, 372 int reverse, int version, 373 tor_addr_t *result_addr, char **result_hostname) 374 { 375 int s = -1; 376 struct sockaddr_storage ss; 377 socklen_t socklen; 378 uint8_t *req = NULL; 379 ssize_t len = 0; 380 381 tor_assert(hostname); 382 tor_assert(result_addr); 383 tor_assert(version == 4 || version == 5); 384 385 tor_addr_make_unspec(result_addr); 386 *result_hostname = NULL; 387 388 s = tor_open_socket(sockshost->family,SOCK_STREAM,IPPROTO_TCP); 389 if (s<0) { 390 log_sock_error("creating_socket", -1); 391 return -1; 392 } 393 394 socklen = tor_addr_to_sockaddr(sockshost, socksport, 395 (struct sockaddr *)&ss, sizeof(ss)); 396 397 if (connect(s, (struct sockaddr*)&ss, socklen)) { 398 log_sock_error("connecting to SOCKS host", s); 399 goto err; 400 } 401 402 if (version == 5) { 403 socks5_client_version_t *v = socks5_client_version_new(); 404 405 socks5_client_version_set_version(v, 5); 406 socks5_client_version_set_n_methods(v, 1); 407 socks5_client_version_setlen_methods(v, 1); 408 socks5_client_version_set_methods(v, 0, 0x00); 409 410 tor_assert(!socks5_client_version_check(v)); 411 ssize_t encoded_len = socks5_client_version_encoded_len(v); 412 tor_assert(encoded_len > 0); 413 414 uint8_t *buf = tor_malloc(encoded_len); 415 encoded_len = socks5_client_version_encode(buf, encoded_len, v); 416 tor_assert(encoded_len > 0); 417 418 socks5_client_version_free(v); 419 420 if (write_all_to_socket(s, (const char *)buf, 421 encoded_len) != encoded_len) { 422 log_err(LD_NET, "Error sending SOCKS5 method list."); 423 tor_free(buf); 424 425 goto err; 426 } 427 428 tor_free(buf); 429 430 uint8_t method_buf[2]; 431 432 if (read_all_from_socket(s, (char *)method_buf, 2) != 2) { 433 log_err(LD_NET, "Error reading SOCKS5 methods."); 434 goto err; 435 } 436 437 socks5_server_method_t *m; 438 ssize_t parsed = socks5_server_method_parse(&m, method_buf, 439 sizeof(method_buf)); 440 441 if (parsed < 2) { 442 log_err(LD_NET, "Failed to parse SOCKS5 method selection " 443 "message"); 444 socks5_server_method_free(m); 445 goto err; 446 } 447 448 uint8_t method = socks5_server_method_get_method(m); 449 450 socks5_server_method_free(m); 451 452 if (method != 0x00) { 453 log_err(LD_NET, "Unrecognized socks authentication method: %u", 454 (unsigned)method); 455 goto err; 456 } 457 } 458 459 if ((len = build_socks_resolve_request(&req, "", hostname, reverse, 460 version))<0) { 461 log_err(LD_BUG,"Error generating SOCKS request"); 462 tor_assert(!req); 463 goto err; 464 } 465 if (write_all_to_socket(s, (const char *)req, len) != len) { 466 log_sock_error("sending SOCKS request", s); 467 tor_free(req); 468 goto err; 469 } 470 tor_free(req); 471 472 if (version == 4) { 473 char reply_buf[RESPONSE_LEN_4]; 474 if (read_all_from_socket(s, reply_buf, RESPONSE_LEN_4) != RESPONSE_LEN_4) { 475 log_err(LD_NET, "Error reading SOCKS4 response."); 476 goto err; 477 } 478 if (parse_socks4a_resolve_response(hostname, 479 reply_buf, RESPONSE_LEN_4, 480 result_addr)<0) { 481 goto err; 482 } 483 } else { 484 uint8_t reply_buf[512]; 485 486 len = read_all_from_socket(s, (char *)reply_buf, 487 sizeof(reply_buf)); 488 489 socks5_server_reply_t *reply; 490 491 ssize_t parsed = socks5_server_reply_parse(&reply, 492 reply_buf, 493 len); 494 if (parsed == -1) { 495 log_err(LD_NET, "Failed parsing SOCKS5 response"); 496 goto err; 497 } 498 499 if (parsed == -2) { 500 log_err(LD_NET, "Truncated SOCKS5 response"); 501 goto err; 502 } 503 504 /* Give a user some useful feedback about SOCKS5 errors */ 505 uint8_t reply_field = socks5_server_reply_get_reply(reply); 506 if (reply_field != 0) { 507 log_warn(LD_NET,"Got SOCKS5 status response '%u': %s", 508 (unsigned)reply_field, 509 socks5_reason_to_string(reply_field)); 510 if (reply_field == 4 && !strcasecmpend(hostname, ".onion")) { 511 onion_hs_warning(hostname); 512 } 513 514 if (reply_field == 4 && !strcasecmpend(hostname, ".exit")) { 515 onion_exit_warning(hostname); 516 } 517 518 socks5_server_reply_free(reply); 519 goto err; 520 } 521 522 uint8_t atype = socks5_server_reply_get_atype(reply); 523 524 if (atype == SOCKS5_ATYPE_IPV4) { 525 /* IPv4 address */ 526 tor_addr_from_ipv4h(result_addr, 527 socks5_server_reply_get_bind_addr_ipv4(reply)); 528 } else if (atype == SOCKS5_ATYPE_IPV6) { 529 /* IPv6 address */ 530 tor_addr_from_ipv6_bytes(result_addr, 531 socks5_server_reply_getarray_bind_addr_ipv6(reply)); 532 } else if (atype == SOCKS5_ATYPE_HOSTNAME) { 533 /* Domain name */ 534 domainname_t *dn = 535 socks5_server_reply_get_bind_addr_domainname(reply); 536 537 *result_hostname = tor_strdup(domainname_getstr_name(dn)); 538 } 539 540 socks5_server_reply_free(reply); 541 } 542 543 tor_close_socket(s); 544 return 0; 545 err: 546 tor_close_socket(s); 547 return -1; 548 } 549 550 /** Print a usage message and exit. */ 551 static void 552 usage(void) 553 { 554 puts("Syntax: tor-resolve [-4] [-5] [-v] [-x] [-p port] " 555 "hostname [sockshost[:socksport]]"); 556 exit(1); 557 } 558 559 /** Entry point to tor-resolve */ 560 int 561 main(int argc, char **argv) 562 { 563 tor_addr_t sockshost; 564 uint16_t socksport = 0, port_option = 0; 565 int isSocks4 = 0, isVerbose = 0, isReverse = 0; 566 char **arg; 567 int n_args; 568 tor_addr_t result; 569 char *result_hostname = NULL; 570 571 init_logging(1); 572 sandbox_disable_getaddrinfo_cache(); 573 574 arg = &argv[1]; 575 n_args = argc-1; 576 577 if (!n_args) 578 usage(); 579 580 if (!strcmp(arg[0],"--version")) { 581 printf("Tor version %s.\n",VERSION); 582 return 0; 583 } 584 while (n_args && *arg[0] == '-') { 585 if (!strcmp("-v", arg[0])) 586 isVerbose = 1; 587 else if (!strcmp("-4", arg[0])) 588 isSocks4 = 1; 589 else if (!strcmp("-5", arg[0])) 590 isSocks4 = 0; 591 else if (!strcmp("-x", arg[0])) 592 isReverse = 1; 593 else if (!strcmp("-p", arg[0])) { 594 int p; 595 if (n_args < 2) { 596 fprintf(stderr, "No arguments given to -p\n"); 597 usage(); 598 } 599 p = atoi(arg[1]); 600 if (p<1 || p > 65535) { 601 fprintf(stderr, "-p requires a number between 1 and 65535\n"); 602 usage(); 603 } 604 port_option = (uint16_t) p; 605 ++arg; /* skip the port */ 606 --n_args; 607 } else { 608 fprintf(stderr, "Unrecognized flag '%s'\n", arg[0]); 609 usage(); 610 } 611 ++arg; 612 --n_args; 613 } 614 615 if (isSocks4 && isReverse) { 616 fprintf(stderr, "Reverse lookups not supported with SOCKS4a\n"); 617 usage(); 618 } 619 620 log_severity_list_t *severities = 621 tor_malloc_zero(sizeof(log_severity_list_t)); 622 if (isVerbose) 623 set_log_severity_config(LOG_DEBUG, LOG_ERR, severities); 624 else 625 set_log_severity_config(LOG_WARN, LOG_ERR, severities); 626 add_stream_log(severities, "<stderr>", fileno(stderr)); 627 tor_free(severities); 628 629 if (n_args == 1) { 630 log_debug(LD_CONFIG, "defaulting to localhost"); 631 tor_addr_from_ipv4h(&sockshost, 0x7f000001u); /* localhost */ 632 if (port_option) { 633 log_debug(LD_CONFIG, "Using port %d", (int)port_option); 634 socksport = port_option; 635 } else { 636 log_debug(LD_CONFIG, "defaulting to port 9050"); 637 socksport = 9050; /* 9050 */ 638 } 639 } else if (n_args == 2) { 640 if (tor_addr_port_lookup(arg[1], &sockshost, &socksport)<0) { 641 fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]); 642 return 1; 643 } 644 if (socksport && port_option && socksport != port_option) { 645 log_warn(LD_CONFIG, "Conflicting ports; using %d, not %d", 646 (int)socksport, (int)port_option); 647 } else if (port_option) { 648 socksport = port_option; 649 } else if (!socksport) { 650 log_debug(LD_CONFIG, "defaulting to port 9050"); 651 socksport = 9050; 652 } 653 } else { 654 usage(); 655 } 656 657 if (network_init()<0) { 658 log_err(LD_BUG,"Error initializing network; exiting."); 659 return 1; 660 } 661 662 if (do_resolve(arg[0], &sockshost, socksport, isReverse, 663 isSocks4 ? 4 : 5, &result, 664 &result_hostname)) 665 return 1; 666 667 if (result_hostname) { 668 printf("%s\n", result_hostname); 669 } else { 670 printf("%s\n", fmt_addr(&result)); 671 } 672 return 0; 673 }