tor-resolve.c
上传用户:awang829
上传日期:2019-07-14
资源大小:2356k
文件大小:12k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
  2.  * Copyright (c) 2007-2009, The Tor Project, Inc.
  3.  */
  4. /* See LICENSE for licensing information */
  5. #include "orconfig.h"
  6. #include "compat.h"
  7. #include "util.h"
  8. #include "address.h"
  9. #include "log.h"
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stdarg.h>
  13. #include <string.h>
  14. #include <assert.h>
  15. #ifdef HAVE_NETINET_IN_H
  16. #include <netinet/in.h>
  17. #endif
  18. #ifdef HAVE_ARPA_INET_H
  19. #include <arpa/inet.h>
  20. #endif
  21. #ifdef HAVE_SYS_SOCKET_H
  22. #include <sys/socket.h>
  23. #endif
  24. #ifdef HAVE_SYS_TYPES_H
  25. #include <sys/types.h> /* Must be included before sys/stat.h for Ultrix */
  26. #endif
  27. #ifdef HAVE_ERRNO_H
  28. #include <errno.h>
  29. #endif
  30. #ifdef MS_WINDOWS
  31. #if defined(_MSC_VER) && (_MSC_VER <= 1300)
  32. #include <winsock.h>
  33. #else
  34. #include <winsock2.h>
  35. #include <ws2tcpip.h>
  36. #endif
  37. #endif
  38. #define RESPONSE_LEN_4 8
  39. #define log_sock_error(act, _s)                                         
  40.   STMT_BEGIN log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act,         
  41.               tor_socket_strerror(tor_socket_errno(_s))); STMT_END
  42. static void usage(void) ATTR_NORETURN;
  43. /** Set *<b>out</b> to a newly allocated SOCKS4a resolve request with
  44.  * <b>username</b> and <b>hostname</b> as provided.  Return the number
  45.  * of bytes in the request. */
  46. static ssize_t
  47. build_socks_resolve_request(char **out,
  48.                             const char *username,
  49.                             const char *hostname,
  50.                             int reverse,
  51.                             int version)
  52. {
  53.   size_t len = 0;
  54.   tor_assert(out);
  55.   tor_assert(username);
  56.   tor_assert(hostname);
  57.   if (version == 4) {
  58.     len = 8 + strlen(username) + 1 + strlen(hostname) + 1;
  59.     *out = tor_malloc(len);
  60.     (*out)[0] = 4;      /* SOCKS version 4 */
  61.     (*out)[1] = 'xF0'; /* Command: resolve. */
  62.     set_uint16((*out)+2, htons(0)); /* port: 0. */
  63.     set_uint32((*out)+4, htonl(0x00000001u)); /* addr: 0.0.0.1 */
  64.     memcpy((*out)+8, username, strlen(username)+1);
  65.     memcpy((*out)+8+strlen(username)+1, hostname, strlen(hostname)+1);
  66.   } else if (version == 5) {
  67.     int is_ip_address;
  68.     struct in_addr in;
  69.     size_t addrlen;
  70.     is_ip_address = tor_inet_aton(hostname, &in);
  71.     if (!is_ip_address && reverse) {
  72.       log_err(LD_GENERAL, "Tried to do a reverse lookup on a non-IP!");
  73.       return -1;
  74.     }
  75.     addrlen = reverse ? 4 : 1 + strlen(hostname);
  76.     len = 6 + addrlen;
  77.     *out = tor_malloc(len);
  78.     (*out)[0] = 5; /* SOCKS version 5 */
  79.     (*out)[1] = reverse ? 'xF1' : 'xF0'; /* RESOLVE_PTR or RESOLVE */
  80.     (*out)[2] = 0; /* reserved. */
  81.     (*out)[3] = reverse ? 1 : 3;
  82.     if (reverse) {
  83.       set_uint32((*out)+4, in.s_addr);
  84.     } else {
  85.       (*out)[4] = (char)(uint8_t)(addrlen - 1);
  86.       memcpy((*out)+5, hostname, addrlen - 1);
  87.     }
  88.     set_uint16((*out)+4+addrlen, 0); /* port */
  89.   } else {
  90.     tor_assert(0);
  91.   }
  92.   return len;
  93. }
  94. /** Given a <b>len</b>-byte SOCKS4a response in <b>response</b>, set
  95.  * *<b>addr_out</b> to the address it contains (in host order).
  96.  * Return 0 on success, -1 on error.
  97.  */
  98. static int
  99. parse_socks4a_resolve_response(const char *hostname,
  100.                                const char *response, size_t len,
  101.                                uint32_t *addr_out)
  102. {
  103.   uint8_t status;
  104.   tor_assert(response);
  105.   tor_assert(addr_out);
  106.   if (len < RESPONSE_LEN_4) {
  107.     log_warn(LD_PROTOCOL,"Truncated socks response.");
  108.     return -1;
  109.   }
  110.   if (((uint8_t)response[0])!=0) { /* version: 0 */
  111.     log_warn(LD_PROTOCOL,"Nonzero version in socks response: bad format.");
  112.     return -1;
  113.   }
  114.   status = (uint8_t)response[1];
  115.   if (get_uint16(response+2)!=0) { /* port: 0 */
  116.     log_warn(LD_PROTOCOL,"Nonzero port in socks response: bad format.");
  117.     return -1;
  118.   }
  119.   if (status != 90) {
  120.     log_warn(LD_NET,"Got status response '%d': socks request failed.", status);
  121.     if (!strcasecmpend(hostname, ".onion")) {
  122.       log_warn(LD_NET,
  123.         "%s is a hidden service; those don't have IP addresses. "
  124.         "To connect to a hidden service, you need to send the hostname "
  125.         "to Tor; we suggest an application that uses SOCKS 4a.",hostname);
  126.       return -1;
  127.     }
  128.     return -1;
  129.   }
  130.   *addr_out = ntohl(get_uint32(response+4));
  131.   return 0;
  132. }
  133. /* It would be nice to let someone know what SOCKS5 issue a user may have */
  134. static const char *
  135. socks5_reason_to_string(char reason)
  136. {
  137.   switch(reason) {
  138.     case SOCKS5_SUCCEEDED:
  139.       return "succeeded";
  140.     case SOCKS5_GENERAL_ERROR:
  141.       return "general error";
  142.     case SOCKS5_NOT_ALLOWED:
  143.       return "not allowed";
  144.     case SOCKS5_NET_UNREACHABLE:
  145.       return "network is unreachable";
  146.     case SOCKS5_HOST_UNREACHABLE:
  147.       return "host is unreachable";
  148.     case SOCKS5_CONNECTION_REFUSED:
  149.       return "connection refused";
  150.     case SOCKS5_TTL_EXPIRED:
  151.       return "ttl expired";
  152.     case SOCKS5_COMMAND_NOT_SUPPORTED:
  153.       return "command not supported";
  154.     case SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED:
  155.       return "address type not supported";
  156.     default:
  157.       return "unknown SOCKS5 code";
  158.   }
  159. }
  160. /** Send a resolve request for <b>hostname</b> to the Tor listening on
  161.  * <b>sockshost</b>:<b>socksport</b>.  Store the resulting IPv4
  162.  * address (in host order) into *<b>result_addr</b>.
  163.  */
  164. static int
  165. do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
  166.            int reverse, int version,
  167.            uint32_t *result_addr, char **result_hostname)
  168. {
  169.   int s;
  170.   struct sockaddr_in socksaddr;
  171.   char *req = NULL;
  172.   ssize_t len = 0;
  173.   tor_assert(hostname);
  174.   tor_assert(result_addr);
  175.   tor_assert(version == 4 || version == 5);
  176.   *result_addr = 0;
  177.   *result_hostname = NULL;
  178.   s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  179.   if (s<0) {
  180.     log_sock_error("creating_socket", -1);
  181.     return -1;
  182.   }
  183.   memset(&socksaddr, 0, sizeof(socksaddr));
  184.   socksaddr.sin_family = AF_INET;
  185.   socksaddr.sin_port = htons(socksport);
  186.   socksaddr.sin_addr.s_addr = htonl(sockshost);
  187.   if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) {
  188.     log_sock_error("connecting to SOCKS host", s);
  189.     return -1;
  190.   }
  191.   if (version == 5) {
  192.     char method_buf[2];
  193.     if (write_all(s, "x05x01x00", 3, 1) != 3) {
  194.       log_err(LD_NET, "Error sending SOCKS5 method list.");
  195.       return -1;
  196.     }
  197.     if (read_all(s, method_buf, 2, 1) != 2) {
  198.       log_err(LD_NET, "Error reading SOCKS5 methods.");
  199.       return -1;
  200.     }
  201.     if (method_buf[0] != 'x05') {
  202.       log_err(LD_NET, "Unrecognized socks version: %u",
  203.               (unsigned)method_buf[0]);
  204.       return -1;
  205.     }
  206.     if (method_buf[1] != 'x00') {
  207.       log_err(LD_NET, "Unrecognized socks authentication method: %u",
  208.               (unsigned)method_buf[1]);
  209.       return -1;
  210.     }
  211.   }
  212.   if ((len = build_socks_resolve_request(&req, "", hostname, reverse,
  213.                                          version))<0) {
  214.     log_err(LD_BUG,"Error generating SOCKS request");
  215.     tor_assert(!req);
  216.     return -1;
  217.   }
  218.   if (write_all(s, req, len, 1) != len) {
  219.     log_sock_error("sending SOCKS request", s);
  220.     tor_free(req);
  221.     return -1;
  222.   }
  223.   tor_free(req);
  224.   if (version == 4) {
  225.     char reply_buf[RESPONSE_LEN_4];
  226.     if (read_all(s, reply_buf, RESPONSE_LEN_4, 1) != RESPONSE_LEN_4) {
  227.       log_err(LD_NET, "Error reading SOCKS4 response.");
  228.       return -1;
  229.     }
  230.     if (parse_socks4a_resolve_response(hostname,
  231.                                        reply_buf, RESPONSE_LEN_4,
  232.                                        result_addr)<0){
  233.       return -1;
  234.     }
  235.   } else {
  236.     char reply_buf[4];
  237.     if (read_all(s, reply_buf, 4, 1) != 4) {
  238.       log_err(LD_NET, "Error reading SOCKS5 response.");
  239.       return -1;
  240.     }
  241.     if (reply_buf[0] != 5) {
  242.       log_err(LD_NET, "Bad SOCKS5 reply version.");
  243.       return -1;
  244.     }
  245.     /* Give a user some useful feedback about SOCKS5 errors */
  246.     if (reply_buf[1] != 0) {
  247.       log_warn(LD_NET,"Got SOCKS5 status response '%u': %s",
  248.                (unsigned)reply_buf[1],
  249.                socks5_reason_to_string(reply_buf[1]));
  250.       if (reply_buf[1] == 4 && !strcasecmpend(hostname, ".onion")) {
  251.         log_warn(LD_NET,
  252.             "%s is a hidden service; those don't have IP addresses. "
  253.             "To connect to a hidden service, you need to send the hostname "
  254.             "to Tor; we suggest an application that uses SOCKS 4a.",
  255.             hostname);
  256.       }
  257.       return -1;
  258.     }
  259.     if (reply_buf[3] == 1) {
  260.       /* IPv4 address */
  261.       if (read_all(s, reply_buf, 4, 1) != 4) {
  262.         log_err(LD_NET, "Error reading address in socks5 response.");
  263.         return -1;
  264.       }
  265.       *result_addr = ntohl(get_uint32(reply_buf));
  266.     } else if (reply_buf[3] == 3) {
  267.       size_t result_len;
  268.       if (read_all(s, reply_buf, 1, 1) != 1) {
  269.         log_err(LD_NET, "Error reading address_length in socks5 response.");
  270.         return -1;
  271.       }
  272.       result_len = *(uint8_t*)(reply_buf);
  273.       *result_hostname = tor_malloc(result_len+1);
  274.       if (read_all(s, *result_hostname, result_len, 1) != (int) result_len) {
  275.         log_err(LD_NET, "Error reading hostname in socks5 response.");
  276.         return -1;
  277.       }
  278.       (*result_hostname)[result_len] = '';
  279.     }
  280.   }
  281.   return 0;
  282. }
  283. /** Print a usage message and exit. */
  284. static void
  285. usage(void)
  286. {
  287.   puts("Syntax: tor-resolve [-4] [-v] [-x] [-F] [-p port] "
  288.        "hostname [sockshost:socksport]");
  289.   exit(1);
  290. }
  291. /** Entry point to tor-resolve */
  292. int
  293. main(int argc, char **argv)
  294. {
  295.   uint32_t sockshost;
  296.   uint16_t socksport = 0, port_option = 0;
  297.   int isSocks4 = 0, isVerbose = 0, isReverse = 0, force = 0;
  298.   char **arg;
  299.   int n_args;
  300.   struct in_addr a;
  301.   uint32_t result = 0;
  302.   char *result_hostname = NULL;
  303.   char buf[INET_NTOA_BUF_LEN];
  304.   log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
  305.   init_logging();
  306.   arg = &argv[1];
  307.   n_args = argc-1;
  308.   if (!n_args)
  309.     usage();
  310.   if (!strcmp(arg[0],"--version")) {
  311.     printf("Tor version %s.n",VERSION);
  312.     return 0;
  313.   }
  314.   while (n_args && *arg[0] == '-') {
  315.     if (!strcmp("-v", arg[0]))
  316.       isVerbose = 1;
  317.     else if (!strcmp("-4", arg[0]))
  318.       isSocks4 = 1;
  319.     else if (!strcmp("-5", arg[0]))
  320.       isSocks4 = 0;
  321.     else if (!strcmp("-x", arg[0]))
  322.       isReverse = 1;
  323.     else if (!strcmp("-F", arg[0]))
  324.       force = 1;
  325.     else if (!strcmp("-p", arg[0])) {
  326.       int p;
  327.       if (n_args < 2) {
  328.         fprintf(stderr, "No arguments given to -pn");
  329.         usage();
  330.       }
  331.       p = atoi(arg[1]);
  332.       if (p<1 || p > 65535) {
  333.         fprintf(stderr, "-p requires a number between 1 and 65535n");
  334.         usage();
  335.       }
  336.       port_option = (uint16_t) p;
  337.       ++arg; /* skip the port */
  338.       --n_args;
  339.     } else {
  340.       fprintf(stderr, "Unrecognized flag '%s'n", arg[0]);
  341.       usage();
  342.     }
  343.     ++arg;
  344.     --n_args;
  345.   }
  346.   if (isSocks4 && isReverse) {
  347.     fprintf(stderr, "Reverse lookups not supported with SOCKS4an");
  348.     usage();
  349.   }
  350.   if (isVerbose)
  351.     set_log_severity_config(LOG_DEBUG, LOG_ERR, s);
  352.   else
  353.     set_log_severity_config(LOG_WARN, LOG_ERR, s);
  354.   add_stream_log(s, "<stderr>", fileno(stderr));
  355.   if (n_args == 1) {
  356.     log_debug(LD_CONFIG, "defaulting to localhost");
  357.     sockshost = 0x7f000001u; /* localhost */
  358.     if (port_option) {
  359.       log_debug(LD_CONFIG, "Using port %d", (int)port_option);
  360.       socksport = port_option;
  361.     } else {
  362.       log_debug(LD_CONFIG, "defaulting to port 9050");
  363.       socksport = 9050; /* 9050 */
  364.     }
  365.   } else if (n_args == 2) {
  366.     if (parse_addr_port(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) {
  367.       fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]);
  368.       return 1;
  369.     }
  370.     if (socksport && port_option && socksport != port_option) {
  371.       log_warn(LD_CONFIG, "Conflicting ports; using %d, not %d",
  372.                (int)socksport, (int)port_option);
  373.     } else if (port_option) {
  374.       socksport = port_option;
  375.     } else if (!socksport) {
  376.       log_debug(LD_CONFIG, "defaulting to port 9050");
  377.       socksport = 9050;
  378.     }
  379.   } else {
  380.     usage();
  381.   }
  382.   if (network_init()<0) {
  383.     log_err(LD_BUG,"Error initializing network; exiting.");
  384.     return 1;
  385.   }
  386.   if (do_resolve(arg[0], sockshost, socksport, isReverse,
  387.                  isSocks4 ? 4 : 5, &result,
  388.                  &result_hostname))
  389.     return 1;
  390.   if (result_hostname) {
  391.     printf("%sn", result_hostname);
  392.   } else {
  393.     a.s_addr = htonl(result);
  394.     tor_inet_ntoa(&a, buf, sizeof(buf));
  395.     printf("%sn", buf);
  396.   }
  397.   return 0;
  398. }