diff --git a/src/core.c b/src/core.c index 8cedc3c..a5f2fc3 100644 --- a/src/core.c +++ b/src/core.c @@ -935,7 +935,6 @@ int socksify_udp_packet(void* udp_data, size_t udp_data_len, udp_relay_chain cha // Append UDP data in the remaining space of the buffer size_t min = (udp_data_len>(buffer_len-tmp_buffer_len))?(buffer_len-tmp_buffer_len):udp_data_len; - PDEBUG("test, min = %lu\n", min); memcpy(buffer + tmp_buffer_len, udp_data, min); *buffer_len = tmp_buffer_len + min; @@ -987,7 +986,7 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) { proxychains_write_log(TP " timeout\n"); error: if(*fd != -1) - close(*fd); + true_close(*fd); return SOCKET_ERROR; } @@ -1348,7 +1347,7 @@ int add_node_to_chain(proxy_data * pd, udp_relay_chain * chain){ err: // Ensure new node tcp socket is closed if(new_node->tcp_sockfd != -1){ - close(new_node->tcp_sockfd); + true_close(new_node->tcp_sockfd); } // Remove the new node from the chain @@ -1365,27 +1364,28 @@ int add_node_to_chain(proxy_data * pd, udp_relay_chain * chain){ return -1; } -int free_relay_chain(udp_relay_chain chain){ - if(NULL != chain.connected_peer_addr){ - free(chain.connected_peer_addr); - chain.connected_peer_addr = NULL; +int free_relay_chain_contents(udp_relay_chain* chain){ + if(NULL != chain->connected_peer_addr){ + free(chain->connected_peer_addr); + chain->connected_peer_addr = NULL; } - if(chain.head == NULL){ + if(chain->head == NULL){ return SUCCESS; } - udp_relay_node * current = chain.head; + udp_relay_node * current = chain->head; udp_relay_node * next = NULL; - + while(current != NULL){ next = current->next; - close(current->tcp_sockfd); + true_close(current->tcp_sockfd); free(current); current = next; } + chain->head = NULL; return SUCCESS; } @@ -1447,7 +1447,7 @@ udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, cha error: PDEBUG("error\n"); release_all(pd, proxy_count); - free_relay_chain(*new_chain); + free_relay_chain_contents(new_chain); free(new_chain); errno = ETIMEDOUT; return NULL; @@ -1491,7 +1491,6 @@ void set_connected_peer_addr(udp_relay_chain* chain, struct sockaddr* addr, sock chain->connected_peer_addr = (struct sockaddr*)new_addr; chain->connected_peer_addr_len = sizeof(struct sockaddr_in); } - } @@ -1505,7 +1504,7 @@ void add_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* new_cha new_chain->prev = NULL; } else { // Add the new chain at the end - chains_list->tail->next = new_chain; + (chains_list->tail)->next = new_chain; new_chain->prev = chains_list->tail; chains_list->tail = new_chain; } @@ -1519,17 +1518,18 @@ void del_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* chain){ chains_list->tail = NULL; }else{ chains_list->head = chain->next; + chains_list->head->prev = NULL; free(chain); } - } else if (chain = chains_list->tail){ + } else if (chain == chains_list->tail){ chains_list->tail = chain->prev; + chains_list->tail->next = NULL; free(chain); } else { chain->next->prev = chain->prev; chain->prev->next = chain->next; free(chain); } - } udp_relay_chain* get_relay_chain(udp_relay_chain_list chains_list, int sockfd){ diff --git a/src/core.h b/src/core.h index 9014958..e810de8 100644 --- a/src/core.h +++ b/src/core.h @@ -196,6 +196,7 @@ extern recvmsg_t true_recvmsg; extern getpeername_t true_getpeername; extern read_t true_read; extern write_t true_write; +extern close_t true_close; struct gethostbyname_data { struct hostent hostent_space; @@ -218,7 +219,7 @@ static int udp_associate(int sock, ip_type * dst_addr, unsigned short dst_port, udp_relay_chain* get_relay_chain(udp_relay_chain_list chains_list, int sockfd); void del_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* chain); void add_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* new_chain); -int free_relay_chain(udp_relay_chain chain); +int free_relay_chain_contents(udp_relay_chain* chain); udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, chain_type ct, unsigned int max_chains); int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsigned short target_port, char frag, char * data, unsigned int data_len, int flags); int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, unsigned short* src_port, char* data, unsigned int data_len ); diff --git a/src/debug.c b/src/debug.c index 9b6efc5..be1937f 100644 --- a/src/debug.c +++ b/src/debug.c @@ -34,7 +34,7 @@ void dump_relay_chains_list(udp_relay_chain_list list){ udp_relay_chain* current; current = list.head; - PDEBUG("relay chains list dump: \n"); + PDEBUG("relay chains list (head: %x, tail: %x) dump: \n", list.head, list.tail); while(current != NULL){ dump_relay_chain(current); current = current->next; @@ -47,7 +47,7 @@ void dump_relay_chain(udp_relay_chain* chain){ current_node = chain->head; char ip_buf[INET6_ADDRSTRLEN]; char ip_buf2[INET6_ADDRSTRLEN]; - while(current_node ){ + while(current_node){ printf("\tNode%x", current_node); printf("[%s:%i]", inet_ntop(current_node->bnd_addr.is_v6?AF_INET6:AF_INET, current_node->bnd_addr.is_v6?(void*)current_node->bnd_addr.addr.v6:(void*)current_node->bnd_addr.addr.v4.octet, ip_buf2, sizeof(ip_buf2)) , ntohs(current_node->bnd_port)); printf("(ctrl_fd%i-%s:%i)", current_node->tcp_sockfd, inet_ntop(current_node->pd.ip.is_v6?AF_INET6:AF_INET, current_node->pd.ip.is_v6?(void*)current_node->pd.ip.addr.v6:(void*)current_node->pd.ip.addr.v4.octet, ip_buf, sizeof(ip_buf)) , ntohs(current_node->pd.port) ); diff --git a/src/libproxychains.c b/src/libproxychains.c index c931f90..b7365ca 100644 --- a/src/libproxychains.c +++ b/src/libproxychains.c @@ -44,6 +44,7 @@ #include "core.h" #include "common.h" #include "rdns.h" +#include "mutex.h" #undef satosin #define satosin(x) ((struct sockaddr_in *) &(x)) @@ -96,6 +97,7 @@ size_t num_dnats = 0; unsigned int remote_dns_subnet = 224; udp_relay_chain_list relay_chains = {NULL, NULL}; +pthread_mutex_t relay_chains_mutex; pthread_once_t init_once = PTHREAD_ONCE_INIT; @@ -152,6 +154,7 @@ static void do_init(void) { char *env; srand(get_rand_seed()); + MUTEX_INIT(&relay_chains_mutex); core_initialize(); env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR); @@ -609,27 +612,38 @@ HOOKFUNC(int, close, int fd) { /***** UDP STUFF *******/ //PDEBUG("checking if a relay chain is opened for fd %d\n", fd); - udp_relay_chain* chain = NULL; + udp_relay_chain* relay_chain = NULL; - chain = get_relay_chain(relay_chains, fd); - if(NULL != chain){ - PDEBUG("fd %d corresponds to chain %x, closing it\n", fd, chain); - free_relay_chain(*chain); - del_relay_chain(&relay_chains, chain); + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); + relay_chain = get_relay_chain(relay_chains, fd); + if(NULL != relay_chain){ + PDEBUG("fd %d corresponds to chain %x, closing it\n", fd, relay_chain); + free_relay_chain_contents(relay_chain); + del_relay_chain(&relay_chains, relay_chain); + PDEBUG("chain %x corresponding to fd %d closed\n", relay_chain, fd); + DUMP_RELAY_CHAINS_LIST(relay_chains); } + /***** END UDP STUFF *******/ - if(proxychains_resolver != DNSLF_RDNS_THREAD) return true_close(fd); + if(proxychains_resolver != DNSLF_RDNS_THREAD){ + MUTEX_UNLOCK(&relay_chains_mutex); + return true_close(fd); + } /* prevent rude programs (like ssh) from closing our pipes */ if(fd != req_pipefd[0] && fd != req_pipefd[1] && fd != resp_pipefd[0] && fd != resp_pipefd[1]) { + MUTEX_UNLOCK(&relay_chains_mutex); return true_close(fd); } err: errno = EBADF; + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } @@ -650,6 +664,7 @@ static void intsort(int *a, int n) { /* Warning: Linux manual says the third arg is `unsigned int`, but unistd.h says `int`. */ HOOKFUNC(int, close_range, unsigned first, unsigned last, int flags) { + PFUNC(); if(true_close_range == NULL) { fprintf(stderr, "Calling close_range, but this platform does not provide this system call. "); return -1; @@ -734,15 +749,20 @@ HOOKFUNC(int, getpeername, int sockfd, struct sockaddr *restrict addr, socklen_t // Check if a relay chain exists for the socket + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd); if(relay_chain == NULL){ PDEBUG("no relay chain exists for socket %d, returning true_getpeername()\n", sockfd); + MUTEX_UNLOCK(&relay_chains_mutex); return true_getpeername(sockfd, addr, addrlen); } // Check if a connected peer address is stored in the relay chain structure if(relay_chain->connected_peer_addr == NULL){ PDEBUG("no connected peer address is stored for socket %d, returning true_getpeername()\n", sockfd); + MUTEX_UNLOCK(&relay_chains_mutex); return true_getpeername(sockfd, addr, addrlen); } @@ -756,6 +776,7 @@ HOOKFUNC(int, getpeername, int sockfd, struct sockaddr *restrict addr, socklen_t *addrlen = min; + MUTEX_UNLOCK(&relay_chains_mutex); return SUCCESS; /* END UDP STUFF */ @@ -786,6 +807,9 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) PDEBUG("connect() on an UDP socket\n"); // Check if a relay chain is already opened for the socket fd, otherwise open it + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sock); if(relay_chain == NULL){ // No chain is opened for this socket, open one @@ -793,12 +817,14 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) if(NULL == (relay_chain = open_relay_chain(proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain))){ PDEBUG("could not open a chain of relay\n"); errno = ECONNREFUSED; + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } relay_chain->sockfd = sock; add_relay_chain(&relay_chains, relay_chain); + DUMP_RELAY_CHAINS_LIST(relay_chains); } - DUMP_RELAY_CHAINS_LIST(relay_chains); + // Store the peer address in the relay chain structure, in order to be able to retrieve it in subsequent calls to send(), sendmsg(), ... @@ -819,7 +845,8 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) .sin6_port = relay_chain->head->bnd_port, }; if(v6) memcpy(&addr6.sin6_addr.s6_addr, relay_chain->head->bnd_addr.addr.v6, 16); - + + MUTEX_UNLOCK(&relay_chains_mutex); return true_connect(sock, (struct sockaddr *) (v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr) ); } @@ -1130,6 +1157,9 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags, } // Check if a chain of UDP relay is already opened for this socket + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd); if(relay_chain == NULL){ // No chain is opened for this socket, open one @@ -1137,12 +1167,14 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags, if(NULL == (relay_chain = open_relay_chain(proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain))){ PDEBUG("could not open a chain of relay\n"); errno = ECONNREFUSED; + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } relay_chain->sockfd = sockfd; add_relay_chain(&relay_chains, relay_chain); + DUMP_RELAY_CHAINS_LIST(relay_chains); } - DUMP_RELAY_CHAINS_LIST(relay_chains); + memcpy(dest_ip.addr.v6, v6 ? (void*)p_addr_in6 : (void*)p_addr_in, v6?16:4); @@ -1153,6 +1185,7 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags, rc = socksify_udp_packet(buf, len, *relay_chain, dest_ip, htons(port), send_buffer, &send_buffer_len); if(rc != SUCCESS){ PDEBUG("error socksify_udp_packet()\n"); + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } @@ -1189,8 +1222,10 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags, if(flags & MSG_MORE){ PDEBUG("error, MSG_MORE not yet supported\n"); errno = EOPNOTSUPP; + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } + MUTEX_UNLOCK(&relay_chains_mutex); ssize_t sent = 0; sent = true_sendto(sockfd, send_buffer, send_buffer_len, flags, (struct sockaddr*)(v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr)); @@ -1328,6 +1363,9 @@ HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){ } // Check if a chain of UDP relay is already opened for this socket + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd); if(relay_chain == NULL){ // No chain is opened for this socket, open one @@ -1335,12 +1373,14 @@ HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){ if(NULL == (relay_chain = open_relay_chain(proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain))){ PDEBUG("could not open a chain of relay\n"); errno = ECONNREFUSED; + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } relay_chain->sockfd = sockfd; add_relay_chain(&relay_chains, relay_chain); + DUMP_RELAY_CHAINS_LIST(relay_chains); } - DUMP_RELAY_CHAINS_LIST(relay_chains); + memcpy(dest_ip.addr.v6, v6 ? (void*)p_addr_in6 : (void*)p_addr_in, v6?16:4); @@ -1359,6 +1399,7 @@ HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){ rc = socksify_udp_packet(udp_data, udp_data_len, *relay_chain, dest_ip, htons(port),send_buffer, &send_buffer_len); if(rc != SUCCESS){ PDEBUG("error socksify_udp_packet()\n"); + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } @@ -1394,6 +1435,7 @@ HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){ tmp_msg.msg_name = (struct sockaddr*)(v6?(void*)&addr6:(void*)&addr); tmp_msg.msg_namelen = v6?sizeof(addr6):sizeof(addr) ; + MUTEX_UNLOCK(&relay_chains_mutex); //send it @@ -1463,6 +1505,9 @@ HOOKFUNC(int, sendmmsg, int sockfd, struct mmsghdr* msgvec, unsigned int vlen, i } // Check if a chain of UDP relay is already opened for this socket + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd); if(relay_chain == NULL){ // No chain is opened for this socket, open one @@ -1470,18 +1515,21 @@ HOOKFUNC(int, sendmmsg, int sockfd, struct mmsghdr* msgvec, unsigned int vlen, i if(NULL == (relay_chain = open_relay_chain(proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain))){ PDEBUG("could not open a chain of relay\n"); errno = ECONNREFUSED; + MUTEX_UNLOCK(&relay_chains_mutex); goto freeAndExit; } relay_chain->sockfd = sockfd; add_relay_chain(&relay_chains, relay_chain); - } - DUMP_RELAY_CHAINS_LIST(relay_chains); + DUMP_RELAY_CHAINS_LIST(relay_chains); + } + // Prepare our mmsg struct mmsghdr* tmp_msgvec = NULL; if(NULL == (tmp_msgvec = (struct mmsghdr*)calloc(vlen, sizeof(struct mmsghdr)))){ PDEBUG("error allocating memory for tmp_mmsghdr\n"); + MUTEX_UNLOCK(&relay_chains_mutex); goto freeAndExit; } @@ -1510,6 +1558,7 @@ HOOKFUNC(int, sendmmsg, int sockfd, struct mmsghdr* msgvec, unsigned int vlen, i } else { if(msgvec[i].msg_hdr.msg_namelen > addrlen){ PDEBUG("msgvec[%d].msg_hdr.msg_namelen too long\n", i); + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } addrlen = msgvec[i].msg_hdr.msg_namelen; @@ -1672,10 +1721,11 @@ HOOKFUNC(int, sendmmsg, int sockfd, struct mmsghdr* msgvec, unsigned int vlen, i if(pAddr6 != NULL){ free(pAddr6); } - + MUTEX_UNLOCK(&relay_chains_mutex); goto freeAndExit; } + MUTEX_UNLOCK(&relay_chains_mutex); //Drop the MSG_DONTROUTE flag if it exists if(flags & MSG_DONTROUTE){ @@ -1750,10 +1800,14 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){ PDEBUG("sockfd %d's address family is AF_INET or AF_INET6\n", sockfd); + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd); if(relay_chain == NULL){ // No chain is opened for this socket PDEBUG("sockfd %d does not corresponds to any opened relay chain, returning to true_recvmsg\n", sockfd); + MUTEX_UNLOCK(&relay_chains_mutex); return true_recvmsg(sockfd,msg, flags); } PDEBUG("sockfd %d is associated with udp_relay_chain %x\n", sockfd, relay_chain); @@ -1787,6 +1841,7 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){ bytes_received = true_recvmsg(sockfd, &tmp_msg, flags); if(-1 == bytes_received){ PDEBUG("true_recvmsg returned -1, errno: %d, %s\n", errno,strerror(errno)); + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } if(RECV_BUFFER_SIZE == bytes_received){ @@ -1814,7 +1869,7 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){ memcpy(msg->msg_name, tmp_msg.msg_name, min); msg->msg_namelen = min; } - + MUTEX_UNLOCK(&relay_chains_mutex); return trunc?bytes_received:written; //if MSG_TRUNC flag is set, return the real length of the packet/datagram even when it was longer than the passed buffer (msg->msg_iov) } @@ -1828,6 +1883,7 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){ size_t udp_data_len = 0; rc = unsocksify_udp_packet(buffer, bytes_received, *relay_chain, &src_ip, &src_port, &udp_data); + MUTEX_UNLOCK(&relay_chains_mutex); if(rc != SUCCESS){ PDEBUG("error unSOCKSing the UDP packet\n"); return -1; @@ -1940,11 +1996,14 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags, PDEBUG("sockfd %d's address family is AF_INET or AF_INET6\n", sockfd); - + PDEBUG("waiting for mutex\n"); + MUTEX_LOCK(&relay_chains_mutex); + PDEBUG("got mutex\n"); udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd); if(relay_chain == NULL){ // No chain is opened for this socket PDEBUG("sockfd %d does not corresponds to any opened relay chain, returning to true_recvfrom\n", sockfd); + MUTEX_UNLOCK(&relay_chains_mutex); return true_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); } PDEBUG("sockfd %d is associated with udp_relay_chain %x\n", sockfd, relay_chain); @@ -1964,6 +2023,7 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags, bytes_received = true_recvfrom(sockfd, buffer, sizeof(buffer), flags, (struct sockaddr*)&from, &from_len); if(-1 == bytes_received){ PDEBUG("true_recvfrom returned -1\n"); + MUTEX_UNLOCK(&relay_chains_mutex); return -1; } if(RECV_BUFFER_SIZE == bytes_received){ @@ -1987,7 +2047,7 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags, memcpy(src_addr, &from, min_addr_len); *addrlen = min_addr_len; } - + MUTEX_UNLOCK(&relay_chains_mutex); return trunc?bytes_received:min; //if MSG_TRUNC flag is set, return the real length of the packet/datagram even when it was longer than the passed buffer (buf) } PDEBUG("packet received from the proxy chain's head\n"); @@ -1996,6 +2056,7 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags, void* udp_data = NULL; size_t udp_data_len = 0; rc = unsocksify_udp_packet(buffer, bytes_received, *relay_chain, &src_ip, &src_port, &udp_data); + MUTEX_UNLOCK(&relay_chains_mutex); if(rc != SUCCESS){ PDEBUG("error unsocksifying the UDP packet\n"); return -1; @@ -2054,7 +2115,7 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags, *addrlen = sizeof(src_addr_v6); }else { if(addrlen < sizeof(struct sockaddr_in)){ - PDEBUG("addrlen too short for ipv4\n"); + PDEBUG("addrlen too short for ipv4\n"); } src_addr_v4 = (struct sockaddr_in*)src_addr; src_addr_v4->sin_family = AF_INET;