mirror of
				https://github.com/rofl0r/proxychains-ng.git
				synced 2025-11-04 00:56:03 +00:00 
			
		
		
		
	make getaddrinfo threadsafe
This commit is contained in:
		
							
								
								
									
										92
									
								
								src/core.c
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								src/core.c
									
									
									
									
									
								
							@@ -33,6 +33,7 @@
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#ifdef THREAD_SAFE
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
pthread_mutex_t internal_ips_lock;
 | 
			
		||||
@@ -736,13 +737,9 @@ int connect_proxy_chain(int sock, ip_type target_ip,
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: all those buffers aren't threadsafe, but since no memory allocation happens there shouldnt be any segfaults
 | 
			
		||||
static struct hostent hostent_space;
 | 
			
		||||
static in_addr_t resolved_addr;
 | 
			
		||||
static char *resolved_addr_p[2];
 | 
			
		||||
static char addr_name[1024 * 8];
 | 
			
		||||
static const ip_type local_host = { {127, 0, 0, 1} };
 | 
			
		||||
struct hostent *proxy_gethostbyname(const char *name) {
 | 
			
		||||
 | 
			
		||||
struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data* data) {
 | 
			
		||||
	char buff[256];
 | 
			
		||||
	uint32_t i, hash;
 | 
			
		||||
	// yep, new_mem never gets freed. once you passed a fake ip to the client, you can't "retreat" it
 | 
			
		||||
@@ -751,20 +748,20 @@ struct hostent *proxy_gethostbyname(const char *name) {
 | 
			
		||||
 | 
			
		||||
	struct hostent *hp;
 | 
			
		||||
 | 
			
		||||
	resolved_addr_p[0] = (char *) &resolved_addr;
 | 
			
		||||
	resolved_addr_p[1] = NULL;
 | 
			
		||||
	data->resolved_addr_p[0] = (char *) &data->resolved_addr;
 | 
			
		||||
	data->resolved_addr_p[1] = NULL;
 | 
			
		||||
 | 
			
		||||
	hostent_space.h_addr_list = resolved_addr_p;
 | 
			
		||||
	data->hostent_space.h_addr_list = data->resolved_addr_p;
 | 
			
		||||
 | 
			
		||||
	resolved_addr = 0;
 | 
			
		||||
	data->resolved_addr = 0;
 | 
			
		||||
 | 
			
		||||
	gethostname(buff, sizeof(buff));
 | 
			
		||||
 | 
			
		||||
	if(!strcmp(buff, name)) {
 | 
			
		||||
		resolved_addr = inet_addr(buff);
 | 
			
		||||
		if(resolved_addr == (in_addr_t) (-1))
 | 
			
		||||
			resolved_addr = (in_addr_t) (local_host.as_int);
 | 
			
		||||
		return &hostent_space;
 | 
			
		||||
		data->resolved_addr = inet_addr(buff);
 | 
			
		||||
		if(data->resolved_addr == (in_addr_t) (-1))
 | 
			
		||||
			data->resolved_addr = (in_addr_t) (local_host.as_int);
 | 
			
		||||
		return &data->hostent_space;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(buff, 0, sizeof(buff));
 | 
			
		||||
@@ -782,7 +779,7 @@ struct hostent *proxy_gethostbyname(const char *name) {
 | 
			
		||||
	if(internal_ips.counter) {
 | 
			
		||||
		for(i = 0; i < internal_ips.counter; i++) {
 | 
			
		||||
			if(internal_ips.list[i]->hash == hash && !strcmp(name, internal_ips.list[i]->string)) {
 | 
			
		||||
				resolved_addr = make_internal_ip(i);
 | 
			
		||||
				data->resolved_addr = make_internal_ip(i);
 | 
			
		||||
				PDEBUG("got cached ip for %s\n", name);
 | 
			
		||||
				goto have_ip;
 | 
			
		||||
			}
 | 
			
		||||
@@ -802,8 +799,8 @@ struct hostent *proxy_gethostbyname(const char *name) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resolved_addr = make_internal_ip(internal_ips.counter);
 | 
			
		||||
	if(resolved_addr == (in_addr_t) - 1)
 | 
			
		||||
	data->resolved_addr = make_internal_ip(internal_ips.counter);
 | 
			
		||||
	if(data->resolved_addr == (in_addr_t) - 1)
 | 
			
		||||
		goto err_plus_unlock;
 | 
			
		||||
 | 
			
		||||
	l = strlen(name);
 | 
			
		||||
@@ -825,64 +822,69 @@ struct hostent *proxy_gethostbyname(const char *name) {
 | 
			
		||||
 | 
			
		||||
	MUTEX_UNLOCK(&internal_ips_lock);
 | 
			
		||||
 | 
			
		||||
	strncpy(addr_name, name, sizeof(addr_name));
 | 
			
		||||
	strncpy(data->addr_name, name, sizeof(data->addr_name));
 | 
			
		||||
 | 
			
		||||
	hostent_space.h_name = addr_name;
 | 
			
		||||
	hostent_space.h_length = sizeof(in_addr_t);
 | 
			
		||||
	return &hostent_space;
 | 
			
		||||
	data->hostent_space.h_name = data->addr_name;
 | 
			
		||||
	data->hostent_space.h_length = sizeof(in_addr_t);
 | 
			
		||||
	return &data->hostent_space;
 | 
			
		||||
 | 
			
		||||
	err_plus_unlock:
 | 
			
		||||
	MUTEX_UNLOCK(&internal_ips_lock);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct addrinfo_data {
 | 
			
		||||
	struct addrinfo addrinfo_space;
 | 
			
		||||
	struct sockaddr sockaddr_space;
 | 
			
		||||
	char addr_name[256];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void proxy_freeaddrinfo(struct addrinfo *res) {
 | 
			
		||||
	free(res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int proxy_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
 | 
			
		||||
	struct gethostbyname_data ghdata;
 | 
			
		||||
	struct addrinfo_data *space;
 | 
			
		||||
	struct servent *se = NULL;
 | 
			
		||||
	struct hostent *hp = NULL;
 | 
			
		||||
	struct sockaddr *sockaddr_space = NULL;
 | 
			
		||||
	struct addrinfo *addrinfo_space = NULL;
 | 
			
		||||
	struct servent se_buf;
 | 
			
		||||
	char buf[1024];
 | 
			
		||||
	int port;
 | 
			
		||||
 | 
			
		||||
//      printf("proxy_getaddrinfo node %s service %s\n",node,service);
 | 
			
		||||
	addrinfo_space = malloc(sizeof(struct addrinfo));
 | 
			
		||||
	if(!addrinfo_space)
 | 
			
		||||
		goto err1;
 | 
			
		||||
	sockaddr_space = malloc(sizeof(struct sockaddr));
 | 
			
		||||
	if(!sockaddr_space)
 | 
			
		||||
		goto err2;
 | 
			
		||||
	memset(sockaddr_space, 0, sizeof(*sockaddr_space));
 | 
			
		||||
	memset(addrinfo_space, 0, sizeof(*addrinfo_space));
 | 
			
		||||
	if(node && !inet_aton(node, &((struct sockaddr_in *) sockaddr_space)->sin_addr)) {
 | 
			
		||||
		hp = proxy_gethostbyname(node);
 | 
			
		||||
	space = calloc(1, sizeof(struct addrinfo_data));
 | 
			
		||||
	if(!space) goto err1;
 | 
			
		||||
	
 | 
			
		||||
	if(node && !inet_aton(node, &((struct sockaddr_in *) &space->sockaddr_space)->sin_addr)) {
 | 
			
		||||
		hp = proxy_gethostbyname(node, &ghdata);
 | 
			
		||||
		if(hp)
 | 
			
		||||
			memcpy(&((struct sockaddr_in *) sockaddr_space)->sin_addr,
 | 
			
		||||
			memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr,
 | 
			
		||||
			       *(hp->h_addr_list), sizeof(in_addr_t));
 | 
			
		||||
		else
 | 
			
		||||
			goto err3;
 | 
			
		||||
			goto err2;
 | 
			
		||||
	}
 | 
			
		||||
	if(service) getservbyname_r(service, NULL, &se_buf, buf, sizeof(buf), &se);
 | 
			
		||||
 | 
			
		||||
	port = se ? se->s_port : htons(atoi(service ? service : "0"));
 | 
			
		||||
	((struct sockaddr_in *) sockaddr_space)->sin_port = port;
 | 
			
		||||
	((struct sockaddr_in *) &space->sockaddr_space)->sin_port = port;
 | 
			
		||||
 | 
			
		||||
	*res = addrinfo_space;
 | 
			
		||||
	(*res)->ai_addr = sockaddr_space;
 | 
			
		||||
	*res = &space->addrinfo_space;
 | 
			
		||||
	assert((size_t)(*res) == (size_t) space);
 | 
			
		||||
	(*res)->ai_addr = &space->sockaddr_space;
 | 
			
		||||
	if(node)
 | 
			
		||||
		strcpy(addr_name, node);
 | 
			
		||||
	(*res)->ai_canonname = addr_name;
 | 
			
		||||
		strncpy(space->addr_name, node, sizeof(space->addr_name));
 | 
			
		||||
	(*res)->ai_canonname = space->addr_name;
 | 
			
		||||
	(*res)->ai_next = NULL;
 | 
			
		||||
	(*res)->ai_family = sockaddr_space->sa_family = AF_INET;
 | 
			
		||||
	(*res)->ai_family = space->sockaddr_space.sa_family = AF_INET;
 | 
			
		||||
	(*res)->ai_socktype = hints->ai_socktype;
 | 
			
		||||
	(*res)->ai_flags = hints->ai_flags;
 | 
			
		||||
	(*res)->ai_protocol = hints->ai_protocol;
 | 
			
		||||
	(*res)->ai_addrlen = sizeof(*sockaddr_space);
 | 
			
		||||
	(*res)->ai_addrlen = sizeof(space->sockaddr_space);
 | 
			
		||||
	goto out;
 | 
			
		||||
	err3:
 | 
			
		||||
	free(sockaddr_space);
 | 
			
		||||
	err2:
 | 
			
		||||
	free(addrinfo_space);
 | 
			
		||||
	free(space);
 | 
			
		||||
	err1:
 | 
			
		||||
	return 1;
 | 
			
		||||
	out:
 | 
			
		||||
 
 | 
			
		||||
@@ -123,11 +123,18 @@ extern freeaddrinfo_t true_freeaddrinfo;
 | 
			
		||||
extern getnameinfo_t true_getnameinfo;
 | 
			
		||||
extern gethostbyaddr_t true_gethostbyaddr;
 | 
			
		||||
 | 
			
		||||
struct gethostbyname_data {
 | 
			
		||||
	struct hostent hostent_space;
 | 
			
		||||
	in_addr_t resolved_addr;
 | 
			
		||||
	char *resolved_addr_p[2];
 | 
			
		||||
	char addr_name[1024 * 8];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct hostent* proxy_gethostbyname(const char *name);
 | 
			
		||||
struct hostent* proxy_gethostbyname(const char *name, struct gethostbyname_data *data);
 | 
			
		||||
 | 
			
		||||
int proxy_getaddrinfo(const char *node, const char *service, 
 | 
			
		||||
		      const struct addrinfo *hints, struct addrinfo **res);
 | 
			
		||||
void proxy_freeaddrinfo(struct addrinfo *res);
 | 
			
		||||
 | 
			
		||||
void pc_stringfromipv4(unsigned char *ip_buf_4_bytes, char *outbuf_16_bytes);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -325,13 +325,14 @@ int connect(int sock, const struct sockaddr *addr, unsigned int len) {
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct gethostbyname_data ghbndata;
 | 
			
		||||
struct hostent *gethostbyname(const char *name) {
 | 
			
		||||
	INIT();
 | 
			
		||||
 | 
			
		||||
	PDEBUG("gethostbyname: %s\n", name);
 | 
			
		||||
 | 
			
		||||
	if(proxychains_resolver)
 | 
			
		||||
		return proxy_gethostbyname(name);
 | 
			
		||||
		return proxy_gethostbyname(name, &ghbndata);
 | 
			
		||||
	else
 | 
			
		||||
		return true_gethostbyname(name);
 | 
			
		||||
 | 
			
		||||
@@ -360,10 +361,8 @@ void freeaddrinfo(struct addrinfo *res) {
 | 
			
		||||
 | 
			
		||||
	if(!proxychains_resolver)
 | 
			
		||||
		true_freeaddrinfo(res);
 | 
			
		||||
	else {
 | 
			
		||||
		free(res->ai_addr);
 | 
			
		||||
		free(res);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		proxy_freeaddrinfo(res);
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user