/** Send a resolve request for <b>hostname</b> to the Tor listening on * <b>sockshost</b>:<b>socksport</b>. Store the resulting IPv4 * address (in host order) into *<b>result_addr</b>. */ static int do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, int reverse, int version, uint32_t *result_addr, char **result_hostname) { int s; struct sockaddr_in socksaddr; char *req = NULL; int len = 0; tor_assert(hostname); tor_assert(result_addr); tor_assert(version == 4 || version == 5); *result_addr = 0; *result_hostname = NULL; s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); if (s<0) { log_sock_error("creating_socket", -1); return -1; } memset(&socksaddr, 0, sizeof(socksaddr)); socksaddr.sin_family = AF_INET; socksaddr.sin_port = htons(socksport); socksaddr.sin_addr.s_addr = htonl(sockshost); if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) { log_sock_error("connecting to SOCKS host", s); return -1; } if (version == 5) { char method_buf[2]; if (write_all(s, "\x05\x01\x00", 3, 1) != 3) { log_err(LD_NET, "Error sending SOCKS5 method list."); return -1; } if (read_all(s, method_buf, 2, 1) != 2) { log_err(LD_NET, "Error reading SOCKS5 methods."); return -1; } if (method_buf[0] != '\x05') { log_err(LD_NET, "Unrecognized socks version: %u", (unsigned)method_buf[0]); return -1; } if (method_buf[1] != '\x00') { log_err(LD_NET, "Unrecognized socks authentication method: %u", (unsigned)method_buf[1]); return -1; } } if ((len = build_socks_resolve_request(&req, "", hostname, reverse, version))<0) { log_err(LD_BUG,"Error generating SOCKS request"); tor_assert(!req); return -1; } if (write_all(s, req, len, 1) != len) { log_sock_error("sending SOCKS request", s); tor_free(req); return -1; } tor_free(req); if (version == 4) { char reply_buf[RESPONSE_LEN_4]; if (read_all(s, reply_buf, RESPONSE_LEN_4, 1) != RESPONSE_LEN_4) { log_err(LD_NET, "Error reading SOCKS4 response."); return -1; } if (parse_socks4a_resolve_response(reply_buf, RESPONSE_LEN_4, result_addr)<0){ return -1; } } else { char reply_buf[4]; if (read_all(s, reply_buf, 4, 1) != 4) { log_err(LD_NET, "Error reading SOCKS5 response."); return -1; } if (reply_buf[0] != 5) { log_err(LD_NET, "Bad SOCKS5 reply version."); return -1; } if (reply_buf[1] != 0) { log_warn(LD_NET,"Got status response '%u': SOCKS5 request failed.", (unsigned)reply_buf[1]); return -1; } if (reply_buf[3] == 1) { /* IPv4 address */ if (read_all(s, reply_buf, 4, 1) != 4) { log_err(LD_NET, "Error reading address in socks5 response."); return -1; } *result_addr = ntohl(get_uint32(reply_buf)); } else if (reply_buf[3] == 3) { size_t result_len; if (read_all(s, reply_buf, 1, 1) != 1) { log_err(LD_NET, "Error reading address_length in socks5 response."); return -1; } result_len = *(uint8_t*)(reply_buf); *result_hostname = tor_malloc(result_len+1); if (read_all(s, *result_hostname, result_len, 1) != (int) result_len) { log_err(LD_NET, "Error reading hostname in socks5 response."); return -1; } (*result_hostname)[result_len] = '\0'; } } return 0; }
static int do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, uint32_t *result_addr) { int s; struct sockaddr_in socksaddr; char *req, *cp; int r, len; char response_buf[RESPONSE_LEN]; show_msg(MSGDEBUG, "do_resolve: resolving %s\n", hostname); s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s<0) { show_msg(MSGWARN, "do_resolve: problem creating socket\n"); return -1; } memset(&socksaddr, 0, sizeof(socksaddr)); socksaddr.sin_family = AF_INET; socksaddr.sin_port = htons(socksport); socksaddr.sin_addr.s_addr = htonl(sockshost); if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) { show_msg(MSGWARN, "do_resolve: error connecting to SOCKS server\n"); return -1; } if ((len = build_socks4a_resolve_request(&req, "", hostname))<0) { show_msg(MSGWARN, "do_resolve: error generating SOCKS request\n"); return -1; } cp = req; while (len) { r = (int)send(s, cp, len, 0); if (r<0) { show_msg(MSGWARN, "do_resolve: error sending SOCKS request\n"); free(req); return -1; } len -= r; cp += r; } free(req); len = 0; while (len < RESPONSE_LEN) { r = (int)recv(s, response_buf+len, RESPONSE_LEN-len, 0); if (r==0) { show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS response\n"); return -1; } if (r<0) { show_msg(MSGWARN, "do_resolve: error reading SOCKS response\n"); return -1; } len += r; } close(s); if (parse_socks4a_resolve_response(response_buf, RESPONSE_LEN, result_addr) < 0){ show_msg(MSGWARN, "do_resolve: error parsing SOCKS response\n"); return -1; } show_msg(MSGDEBUG, "do_resolve: success\n"); return 0; }
/** Send a resolve request for <b>hostname</b> to the Tor listening on * <b>sockshost</b>:<b>socksport</b>. Store the resulting IPv4 * address (in host order) into *<b>result_addr</b>. */ static int do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, int reverse, int version, tor_addr_t *result_addr, char **result_hostname) { int s = -1; struct sockaddr_in socksaddr; char *req = NULL; ssize_t len = 0; tor_assert(hostname); tor_assert(result_addr); tor_assert(version == 4 || version == 5); tor_addr_make_unspec(result_addr); *result_hostname = NULL; s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); if (s<0) { log_sock_error("creating_socket", -1); return -1; } memset(&socksaddr, 0, sizeof(socksaddr)); socksaddr.sin_family = AF_INET; socksaddr.sin_port = htons(socksport); socksaddr.sin_addr.s_addr = htonl(sockshost); if (connect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) { log_sock_error("connecting to SOCKS host", s); goto err; } if (version == 5) { char method_buf[2]; if (write_all(s, "\x05\x01\x00", 3, 1) != 3) { log_err(LD_NET, "Error sending SOCKS5 method list."); goto err; } if (read_all(s, method_buf, 2, 1) != 2) { log_err(LD_NET, "Error reading SOCKS5 methods."); goto err; } if (method_buf[0] != '\x05') { log_err(LD_NET, "Unrecognized socks version: %u", (unsigned)method_buf[0]); goto err; } if (method_buf[1] != '\x00') { log_err(LD_NET, "Unrecognized socks authentication method: %u", (unsigned)method_buf[1]); goto err; } } if ((len = build_socks_resolve_request(&req, "", hostname, reverse, version))<0) { log_err(LD_BUG,"Error generating SOCKS request"); tor_assert(!req); goto err; } if (write_all(s, req, len, 1) != len) { log_sock_error("sending SOCKS request", s); tor_free(req); goto err; } tor_free(req); if (version == 4) { char reply_buf[RESPONSE_LEN_4]; if (read_all(s, reply_buf, RESPONSE_LEN_4, 1) != RESPONSE_LEN_4) { log_err(LD_NET, "Error reading SOCKS4 response."); goto err; } if (parse_socks4a_resolve_response(hostname, reply_buf, RESPONSE_LEN_4, result_addr)<0) { goto err; } } else { char reply_buf[16]; if (read_all(s, reply_buf, 4, 1) != 4) { log_err(LD_NET, "Error reading SOCKS5 response."); goto err; } if (reply_buf[0] != 5) { log_err(LD_NET, "Bad SOCKS5 reply version."); goto err; } /* Give a user some useful feedback about SOCKS5 errors */ if (reply_buf[1] != 0) { log_warn(LD_NET,"Got SOCKS5 status response '%u': %s", (unsigned)reply_buf[1], socks5_reason_to_string(reply_buf[1])); if (reply_buf[1] == 4 && !strcasecmpend(hostname, ".onion")) { onion_warning(hostname); } goto err; } if (reply_buf[3] == 1) { /* IPv4 address */ if (read_all(s, reply_buf, 4, 1) != 4) { log_err(LD_NET, "Error reading address in socks5 response."); goto err; } tor_addr_from_ipv4n(result_addr, get_uint32(reply_buf)); } else if (reply_buf[3] == 4) { /* IPv6 address */ if (read_all(s, reply_buf, 16, 1) != 16) { log_err(LD_NET, "Error reading address in socks5 response."); goto err; } tor_addr_from_ipv6_bytes(result_addr, reply_buf); } else if (reply_buf[3] == 3) { /* Domain name */ size_t result_len; if (read_all(s, reply_buf, 1, 1) != 1) { log_err(LD_NET, "Error reading address_length in socks5 response."); goto err; } result_len = *(uint8_t*)(reply_buf); *result_hostname = tor_malloc(result_len+1); if (read_all(s, *result_hostname, result_len, 1) != (int) result_len) { log_err(LD_NET, "Error reading hostname in socks5 response."); goto err; } (*result_hostname)[result_len] = '\0'; } } tor_close_socket(s); return 0; err: tor_close_socket(s); return -1; }
static int do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, uint32_t *result_addr, const void *addr, int version, int reverse, char **result_hostname) { int s; struct sockaddr_in socksaddr; char *req, *cp=NULL; int r, len, hslen; char response_buf[RESPONSE_LEN]; const char *handshake="\x05\x01\x00"; show_msg(MSGDEBUG, "do_resolve: resolving %s\n", hostname); /* Create SOCKS connection */ s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s<0) { show_msg(MSGWARN, "do_resolve: problem creating socket\n"); return -1; } /* Connect to SOCKS server */ memset(&socksaddr, 0, sizeof(socksaddr)); socksaddr.sin_family = AF_INET; socksaddr.sin_port = htons(socksport); socksaddr.sin_addr.s_addr = htonl(sockshost); if (realconnect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) { show_msg(MSGWARN, "do_resolve: error connecting to SOCKS server\n"); realclose(s); return -1; } /* If a SOCKS5 connection, perform handshake */ if (version == 5) { char method_buf[2]; hslen=3; while (hslen) { r = send(s, handshake, hslen, 0); if (r<0) { show_msg(MSGWARN, "do_resolve: error sending SOCKS5 method list.\n"); realclose(s); return -1; } hslen -= r; handshake += r; } len = 0; while (len < METHODRESPONSE_LEN) { r = recv(s, method_buf+len, METHODRESPONSE_LEN-len, 0); if (r==0) { show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS response\n"); realclose(s); return -1; } if (r<0) { show_msg(MSGWARN, "do_resolve: error reading SOCKS response\n"); realclose(s); return -1; } len += r; } if (method_buf[0] != '\x05') { show_msg(MSGWARN, "Unrecognized socks version: %u", (unsigned)method_buf[0]); realclose(s); return -1; } if (method_buf[1] != '\x00') { show_msg(MSGWARN, "Unrecognized socks authentication method: %u", (unsigned)method_buf[1]); realclose(s); return -1; } } /* Create SOCKS request */ if (reverse) { if ((len = build_socks5_resolve_ptr_request(&req, addr))<0) { show_msg(MSGWARN, "do_resolve: error generating reverse SOCKS request\n"); realclose(s); return -1; } }else{ if ((len = build_socks4a_resolve_request(&req, "", hostname))<0) { show_msg(MSGWARN, "do_resolve: error generating SOCKS request\n"); realclose(s); return -1; } } /* Send SOCKS request */ cp = req; while (len) { r = send(s, cp, len, 0); if (r<0) { show_msg(MSGWARN, "do_resolve: error sending SOCKS request\n"); free(req); realclose(s); return -1; } len -= r; cp += r; } free(req); /* Handle SOCKS Response */ if (reverse) { if (parse_socks5_resolve_ptr_response(s, response_buf, RESPONSE_LEN, result_addr, &result_hostname) < 0){ show_msg(MSGWARN, "do_resolve: error parsing SOCKS response\n"); realclose(s); return -1; } }else{ /* Process SOCKS response */ len = 0; while (len < RESPONSE_LEN) { r = recv(s, response_buf+len, RESPONSE_LEN-len, 0); if (r==0) { show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS response\n"); realclose(s); return -1; } if (r<0) { show_msg(MSGWARN, "do_resolve: error reading SOCKS response\n"); realclose(s); return -1; } len += r; } realclose(s); /* Parse SOCKS response */ if (parse_socks4a_resolve_response(response_buf, RESPONSE_LEN, result_addr) < 0){ show_msg(MSGWARN, "do_resolve: error parsing SOCKS response\n"); return -1; } } show_msg(MSGDEBUG, "do_resolve: success\n"); return 0; }