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