/* * Torsocks call for close(2). */ LIBC_CLOSE_RET_TYPE tsocks_close(LIBC_CLOSE_SIG) { struct connection *conn; DBG("[close] Close caught for fd %d", fd); connection_registry_lock(); conn = connection_find(fd); if (conn) { /* * Remove from the registry so it's not visible anymore and thus using * it without lock. */ connection_remove(conn); } connection_registry_unlock(); /* * Put back the connection reference. If the refcount get to 0, the * connection pointer is destroyed. */ if (conn) { DBG("[close] Close connection putting back ref"); connection_put_ref(conn); } /* * Let the log system detect when the log file fd is about to be * closed and clean up. */ log_fd_close_notify(fd); /* Return the original libc close. */ return tsocks_libc_close(fd); }
/* * Close all fds in the given array of size count. */ static void close_fds(int *fds, size_t count) { int i; for (i = 0; i < count; i++) { tsocks_libc_close(fds[i]); } }
/* * Resolve a hostname through Tor and set the ip address in the given pointer. * * Return 0 on success else a negative value and the result addr is untouched. */ int tsocks_tor_resolve_ptr(const char *addr, char **ip, int af) { int ret; struct connection conn; uint8_t socks5_method; assert(addr); assert(ip); DBG("Resolving %" PRIu32 " on the Tor network", addr); conn.fd = tsocks_libc_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (conn.fd < 0) { PERROR("socket"); ret = -errno; goto error; } conn.dest_addr.domain = CONNECTION_DOMAIN_INET; /* Is this configuration is set to use SOCKS5 authentication. */ if (tsocks_config.socks5_use_auth) { socks5_method = SOCKS5_USER_PASS_METHOD; } else { socks5_method = SOCKS5_NO_AUTH_METHOD; } ret = setup_tor_connection(&conn, socks5_method); if (ret < 0) { goto end_close; } /* For the user/pass method, send the request before resolve ptr. */ if (socks5_method == SOCKS5_USER_PASS_METHOD) { ret = auth_socks5(&conn); if (ret < 0) { goto end_close; } } ret = socks5_send_resolve_ptr_request(&conn, addr, af); if (ret < 0) { goto end_close; } /* Force IPv4 resolution for now. */ ret = socks5_recv_resolve_ptr_reply(&conn, ip); if (ret < 0) { goto end_close; } end_close: if (tsocks_libc_close(conn.fd) < 0) { PERROR("close"); } error: return ret; }
/* * Resolve a hostname through Tor and set the ip address in the given pointer. * * Return 0 on success else a negative value and the result addr is untouched. */ int tsocks_tor_resolve_ptr(const char *addr, char **ip, int af) { int ret; struct connection conn; assert(addr); assert(ip); DBG("Resolving %" PRIu32 " on the Tor network", addr); conn.fd = tsocks_libc_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (conn.fd < 0) { PERROR("socket"); ret = -errno; goto error; } conn.dest_addr.domain = CONNECTION_DOMAIN_INET; ret = setup_tor_connection(&conn, SOCKS5_NO_AUTH_METHOD); if (ret < 0) { goto end_close; } ret = socks5_send_resolve_ptr_request(&conn, addr, af); if (ret < 0) { goto end_close; } /* Force IPv4 resolution for now. */ ret = socks5_recv_resolve_ptr_reply(&conn, ip); if (ret < 0) { goto end_close; } end_close: if (tsocks_libc_close(conn.fd) < 0) { PERROR("close"); } error: return ret; }
/* * Resolve a hostname through Tor and set the ip address in the given pointer. * * Return 0 on success else a negative value and the result addr is untouched. */ int tsocks_tor_resolve(int af, const char *hostname, void *ip_addr) { int ret; size_t addr_len; struct connection conn; assert(hostname); assert(ip_addr); if (af == AF_INET) { addr_len = sizeof(uint32_t); conn.dest_addr.domain = CONNECTION_DOMAIN_INET; } else if (af == AF_INET6) { addr_len = 16; conn.dest_addr.domain = CONNECTION_DOMAIN_INET6; /* Tor daemon does not support IPv6 DNS resolution yet. */ ret = -ENOSYS; goto error; } else { ret = -EINVAL; goto error; } ret = utils_localhost_resolve(hostname, af, ip_addr, addr_len); if (ret) { /* Found to be a localhost name. */ ret = 0; goto end; } DBG("Resolving %s on the Tor network", hostname); /* * Tor hidden service address have no IP address so we send back an onion * reserved IP address that acts as a cookie that we will use to find the * onion hostname at the connect() stage. */ if (utils_strcasecmpend(hostname, ".onion") == 0) { struct onion_entry *entry; entry = get_onion_entry(hostname, &tsocks_onion_pool); if (entry) { memcpy(ip_addr, &entry->ip, sizeof(entry->ip)); ret = 0; goto end; } } conn.fd = tsocks_libc_socket(af, SOCK_STREAM, IPPROTO_TCP); if (conn.fd < 0) { PERROR("socket"); ret = -errno; goto error; } ret = setup_tor_connection(&conn, SOCKS5_NO_AUTH_METHOD); if (ret < 0) { goto end_close; } ret = socks5_send_resolve_request(hostname, &conn); if (ret < 0) { goto end_close; } /* Force IPv4 resolution for now. */ ret = socks5_recv_resolve_reply(&conn, ip_addr, addr_len); if (ret < 0) { goto end_close; } end_close: if (tsocks_libc_close(conn.fd) < 0) { PERROR("close"); } end: error: return ret; }