1
0
mirror of https://github.com/rofl0r/proxychains-ng synced 2025-01-25 10:53:00 +08:00

Update parser and remove most globals. Parser now supports multiple proxy chains, but the current code only uses the first one to break up the commit.

This commit is contained in:
crass 2013-06-23 15:37:27 +07:00
parent 71b7c8b7af
commit a65f0f47a0
6 changed files with 245 additions and 115 deletions

View File

@ -10,6 +10,7 @@
#include <stddef.h> #include <stddef.h>
#include <errno.h> #include <errno.h>
#include "allocator_thread.h" #include "allocator_thread.h"
#include "core.h"
#include "shm.h" #include "shm.h"
#include "debug.h" #include "debug.h"
#include "ip_type.h" #include "ip_type.h"
@ -17,6 +18,8 @@
#include "hash.h" #include "hash.h"
#include "stringdump.h" #include "stringdump.h"
extern proxy_chain_list *proxychains_chain_list;
/* stuff for our internal translation table */ /* stuff for our internal translation table */
typedef struct { typedef struct {
@ -52,13 +55,12 @@ char *string_from_internal_ip(ip_type internalip) {
return res; return res;
} }
extern unsigned int remote_dns_subnet;
ip_type make_internal_ip(uint32_t index) { ip_type make_internal_ip(uint32_t index) {
ip_type ret; ip_type ret;
index++; // so we can start at .0.0.1 index++; // so we can start at .0.0.1
if(index > 0xFFFFFF) if(index > 0xFFFFFF)
return ip_type_invalid; return ip_type_invalid;
ret.octet[0] = remote_dns_subnet & 0xFF; ret.octet[0] = proxychains_chain_list->remote_dns_subnet & 0xFF;
ret.octet[1] = (index & 0xFF0000) >> 16; ret.octet[1] = (index & 0xFF0000) >> 16;
ret.octet[2] = (index & 0xFF00) >> 8; ret.octet[2] = (index & 0xFF00) >> 8;
ret.octet[3] = index & 0xFF; ret.octet[3] = index & 0xFF;

View File

@ -40,11 +40,8 @@
#include "shm.h" #include "shm.h"
#include "allocator_thread.h" #include "allocator_thread.h"
extern int tcp_read_time_out;
extern int tcp_connect_time_out;
extern int proxychains_quiet_mode; extern int proxychains_quiet_mode;
extern unsigned int proxychains_proxy_offset; extern proxy_chain_list *proxychains_chain_list;
extern unsigned int remote_dns_subnet;
static int poll_retry(struct pollfd *fds, nfds_t nfsd, int timeout) { static int poll_retry(struct pollfd *fds, nfds_t nfsd, int timeout) {
int ret; int ret;
@ -140,7 +137,7 @@ static int read_n_bytes(int fd, char *buff, size_t size) {
pfd[0].events = POLLIN; pfd[0].events = POLLIN;
for(i = 0; i < size; i++) { for(i = 0; i < size; i++) {
pfd[0].revents = 0; pfd[0].revents = 0;
ready = poll_retry(pfd, 1, tcp_read_time_out); ready = poll_retry(pfd, 1, proxychains_chain_list->tcp_read_time_out);
if(ready != 1 || !(pfd[0].revents & POLLIN) || 1 != read(fd, &buff[i], 1)) if(ready != 1 || !(pfd[0].revents & POLLIN) || 1 != read(fd, &buff[i], 1))
return -1; return -1;
} }
@ -160,7 +157,7 @@ static int timed_connect(int sock, const struct sockaddr *addr, socklen_t len) {
PDEBUG("\nconnect ret=%d\n", ret); PDEBUG("\nconnect ret=%d\n", ret);
if(ret == -1 && errno == EINPROGRESS) { if(ret == -1 && errno == EINPROGRESS) {
ret = poll_retry(pfd, 1, tcp_connect_time_out); ret = poll_retry(pfd, 1, proxychains_chain_list->tcp_connect_time_out);
PDEBUG("\npoll ret=%d\n", ret); PDEBUG("\npoll ret=%d\n", ret);
if(ret == 1) { if(ret == 1) {
value_len = sizeof(socklen_t); value_len = sizeof(socklen_t);
@ -199,7 +196,7 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
// the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with // the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with
// the results returned from gethostbyname et al.) // the results returned from gethostbyname et al.)
// the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127 // the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127
if(ip.octet[0] == remote_dns_subnet) { if(ip.octet[0] == proxychains_chain_list->remote_dns_subnet) {
dns_len = at_get_host_for_ip(ip, hostnamebuf); dns_len = at_get_host_for_ip(ip, hostnamebuf);
if(!dns_len) goto err; if(!dns_len) goto err;
else dns_name = hostnamebuf; else dns_name = hostnamebuf;
@ -207,8 +204,8 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
PDEBUG("host dns %s\n", dns_name ? dns_name : "<NULL>"); PDEBUG("host dns %s\n", dns_name ? dns_name : "<NULL>");
size_t ulen = strlen(user); size_t ulen = (user) ? strlen(user) : 0;
size_t passlen = strlen(pass); size_t passlen = (pass) ? strlen(pass) : 0;
if(ulen > 0xFF || passlen > 0xFF || dns_len > 0xFF) { if(ulen > 0xFF || passlen > 0xFF || dns_len > 0xFF) {
proxychains_write_log(LOG_PREFIX "error: maximum size of 255 for user/pass or domain name!\n"); proxychains_write_log(LOG_PREFIX "error: maximum size of 255 for user/pass or domain name!\n");
@ -231,7 +228,7 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
snprintf((char *) buff, sizeof(buff), "CONNECT %s:%d HTTP/1.0\r\n", dns_name, snprintf((char *) buff, sizeof(buff), "CONNECT %s:%d HTTP/1.0\r\n", dns_name,
ntohs(port)); ntohs(port));
if(user[0]) { if(ulen) {
#define HTTP_AUTH_MAX ((0xFF * 2) + 1 + 1) #define HTTP_AUTH_MAX ((0xFF * 2) + 1 + 1)
// 2 * 0xff: username and pass, plus 1 for ':' and 1 for zero terminator. // 2 * 0xff: username and pass, plus 1 for ':' and 1 for zero terminator.
char src[HTTP_AUTH_MAX]; char src[HTTP_AUTH_MAX];
@ -314,9 +311,9 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
} }
break; break;
case SOCKS5_TYPE:{ case SOCKS5_TYPE:{
if(user) { if(ulen) {
buff[0] = 5; //version buff[0] = 5; //version
buff[1] = 2; //nomber of methods buff[1] = 2; //number of methods
buff[2] = 0; // no auth method buff[2] = 0; // no auth method
buff[3] = 2; /// auth method -> username / password buff[3] = 2; /// auth method -> username / password
if(4 != write_n_bytes(sock, (char *) buff, 4)) if(4 != write_n_bytes(sock, (char *) buff, 4))
@ -523,7 +520,7 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
PFUNC(); PFUNC();
if(pto->ip.octet[0] == remote_dns_subnet) { if(pto->ip.octet[0] == proxychains_chain_list->remote_dns_subnet) {
if(!at_get_host_for_ip(pto->ip, hostname_buf)) goto usenumericip; if(!at_get_host_for_ip(pto->ip, hostname_buf)) goto usenumericip;
else hostname = hostname_buf; else hostname = hostname_buf;
} else { } else {
@ -552,9 +549,12 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
return retcode; return retcode;
} }
//~ int connect_proxy_chain(int sock, ip_type target_ip,
//~ unsigned short target_port, proxy_data * pd,
//~ unsigned int proxy_count, chain_type ct, unsigned int max_chain) {
int connect_proxy_chain(int sock, ip_type target_ip, int connect_proxy_chain(int sock, ip_type target_ip,
unsigned short target_port, proxy_data * pd, unsigned short target_port,
unsigned int proxy_count, chain_type ct, unsigned int max_chain) { proxy_chain *pc) {
proxy_data p4; proxy_data p4;
proxy_data *p1, *p2, *p3; proxy_data *p1, *p2, *p3;
int ns = -1; int ns = -1;
@ -565,13 +565,18 @@ int connect_proxy_chain(int sock, ip_type target_ip,
unsigned int curr_pos = 0; unsigned int curr_pos = 0;
unsigned int looped = 0; // went back to start of list in RR mode unsigned int looped = 0; // went back to start of list in RR mode
proxy_data * pd = pc->pd;
unsigned int proxy_count = pc->count;
chain_type ct = pc->ct;
unsigned int max_chain = pc->max_chain;
p3 = &p4; p3 = &p4;
PFUNC(); PFUNC();
again: again:
rc = -1; rc = -1;
DUMP_PROXY_CHAIN(pd, proxy_count); DUMP_PROXY_CHAIN(pc);
switch (ct) { switch (ct) {
case DYNAMIC_TYPE: case DYNAMIC_TYPE:
@ -600,7 +605,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
case ROUND_ROBIN_TYPE: case ROUND_ROBIN_TYPE:
alive_count = calc_alive(pd, proxy_count); alive_count = calc_alive(pd, proxy_count);
curr_pos = offset = proxychains_proxy_offset; curr_pos = offset = pc->offset;
if(alive_count < max_chain) if(alive_count < max_chain)
goto error_more; goto error_more;
PDEBUG("1:rr_offset = %d, curr_pos = %d\n", offset, curr_pos); PDEBUG("1:rr_offset = %d, curr_pos = %d\n", offset, curr_pos);
@ -614,7 +619,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
} else if (looped && rc > 0 && offset >= curr_pos) { } else if (looped && rc > 0 && offset >= curr_pos) {
PDEBUG("GOTO MORE PROXIES 0\n"); PDEBUG("GOTO MORE PROXIES 0\n");
/* We've gone back to the start and now past our starting position */ /* We've gone back to the start and now past our starting position */
proxychains_proxy_offset = 0; pc->offset = 0;
goto error_more; goto error_more;
} }
PDEBUG("2:rr_offset = %d\n", offset); PDEBUG("2:rr_offset = %d\n", offset);
@ -638,8 +643,8 @@ int connect_proxy_chain(int sock, ip_type target_ip,
//proxychains_write_log(TP); //proxychains_write_log(TP);
p3->ip = target_ip; p3->ip = target_ip;
p3->port = target_port; p3->port = target_port;
proxychains_proxy_offset = offset+1; pc->offset = offset+1;
PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len); PDEBUG("pd_offset = %d, curr_len = %d\n", pc->offset, curr_len);
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(ns, p1, p3))
goto error; goto error;
break; break;

View File

@ -25,6 +25,8 @@
#define __CORE_HEADER #define __CORE_HEADER
#define BUFF_SIZE 8*1024 // used to read responses from proxies. #define BUFF_SIZE 8*1024 // used to read responses from proxies.
#define MAX_LOCALNET 64 #define MAX_LOCALNET 64
#define MAX_CHAIN_LISTS 64
#define MAX_CHAIN 512
#include "ip_type.h" #include "ip_type.h"
@ -77,9 +79,30 @@ typedef struct {
char pass[256]; char pass[256];
} proxy_data; } proxy_data;
typedef struct {
char *name;
chain_type ct;
proxy_data *pd;
unsigned int count;
unsigned int offset;
unsigned int max_chain;
int tcp_read_time_out;
int tcp_connect_time_out;
} proxy_chain;
typedef struct {
chain_type ct;
proxy_chain *pc[MAX_CHAIN_LISTS];
unsigned int count;
localaddr_arg localnet_addr[MAX_LOCALNET];
size_t num_localnet_addr;
int remote_dns_subnet; // -1 means no remote dns
int tcp_read_time_out;
int tcp_connect_time_out;
} proxy_chain_list;
int connect_proxy_chain (int sock, ip_type target_ip, unsigned short target_port, int connect_proxy_chain (int sock, ip_type target_ip, unsigned short target_port,
proxy_data * pd, unsigned int proxy_count, chain_type ct, proxy_chain *pc );
unsigned int max_chain );
void proxychains_write_log(char *str, ...); void proxychains_write_log(char *str, ...);

View File

@ -4,18 +4,30 @@
# include "common.h" # include "common.h"
# include "debug.h" # include "debug.h"
void DUMP_PROXY_CHAIN(proxy_data *pchain, unsigned int count) {
void DUMP_PROXY_DATA_LIST(proxy_data *plist, unsigned int count) {
char ip_buf[16]; char ip_buf[16];
for (; count; pchain++, count--) { for (; count; plist++, count--) {
pc_stringfromipv4(&pchain->ip.octet[0], ip_buf); pc_stringfromipv4(&plist->ip.octet[0], ip_buf);
PDEBUG("[%s] %s %s:%d", proxy_state_strmap[pchain->ps], PDEBUG("PDATA:[%s] %s %s:%d", proxy_state_strmap[plist->ps],
proxy_type_strmap[pchain->pt], proxy_type_strmap[plist->pt],
ip_buf, htons(pchain->port)); ip_buf, htons(plist->port));
if (*pchain->user || *pchain->pass) { if (*plist->user || *plist->pass) {
PSTDERR(" [u=%s,p=%s]", pchain->user, pchain->pass); PSTDERR(" [u=%s,p=%s]", plist->user, plist->pass);
} }
PSTDERR("\n"); PSTDERR("\n");
} }
} }
void DUMP_PROXY_CHAIN(proxy_chain *pchain) {
PDEBUG("PCHAIN:[name: \"%s\"]\n", pchain->name);
PDEBUG("PCHAIN:chain type: %s\n", chain_type_strmap[pchain->ct]);
PDEBUG("PCHAIN:tcp_read_time_out: %d\n", pchain->tcp_read_time_out);
PDEBUG("PCHAIN:tcp_connect_time_out: %d\n", pchain->tcp_connect_time_out);
PDEBUG("PCHAIN:max_chain: %d\n", pchain->max_chain);
PDEBUG("PCHAIN:offset: %d\n", pchain->offset);
PDEBUG("PCHAIN:count: %d\n", pchain->count);
DUMP_PROXY_DATA_LIST(pchain->pd, pchain->count);
}
#endif #endif

View File

@ -7,11 +7,13 @@
# define PDEBUG(fmt, args...) PSTDERR("DEBUG:"fmt, ## args) # define PDEBUG(fmt, args...) PSTDERR("DEBUG:"fmt, ## args)
# include "core.h" # include "core.h"
void DUMP_PROXY_CHAIN(proxy_data *pchain, unsigned int count); void DUMP_PROXY_DATA_LIST(proxy_data *plist, unsigned int count);
void DUMP_PROXY_CHAIN(proxy_chain *pchain);
#else #else
# define PDEBUG(fmt, args...) do {} while (0) # define PDEBUG(fmt, args...) do {} while (0)
# define DUMP_PROXY_CHAIN(args...) do {} while (0) # define DUMP_PROXY_CHAIN(args...) do {} while (0)
# define DUMP_PROXY_DATA_LIST(args...) do {} while (0)
#endif #endif
# define PFUNC() do { PDEBUG("pid[%d]:%s\n", getpid(), __FUNCTION__); } while(0) # define PFUNC() do { PDEBUG("pid[%d]:%s\n", getpid(), __FUNCTION__); } while(0)

View File

@ -43,7 +43,6 @@
#define SOCKADDR_2(x) (satosin(x)->sin_addr) #define SOCKADDR_2(x) (satosin(x)->sin_addr)
#define SOCKPORT(x) (satosin(x)->sin_port) #define SOCKPORT(x) (satosin(x)->sin_port)
#define SOCKFAMILY(x) (satosin(x)->sin_family) #define SOCKFAMILY(x) (satosin(x)->sin_family)
#define MAX_CHAIN 512
close_t true_close; close_t true_close;
connect_t true_connect; connect_t true_connect;
@ -53,25 +52,28 @@ freeaddrinfo_t true_freeaddrinfo;
getnameinfo_t true_getnameinfo; getnameinfo_t true_getnameinfo;
gethostbyaddr_t true_gethostbyaddr; gethostbyaddr_t true_gethostbyaddr;
int tcp_read_time_out; //~ int tcp_read_time_out;
int tcp_connect_time_out; //~ int tcp_connect_time_out;
chain_type proxychains_ct; //~ chain_type proxychains_ct;
proxy_data proxychains_pd[MAX_CHAIN]; //~ proxy_data proxychains_pd[MAX_CHAIN];
unsigned int proxychains_proxy_count = 0; //~ unsigned int proxychains_proxy_count = 0;
unsigned int proxychains_proxy_offset = 0; //~ unsigned int proxychains_proxy_offset = 0;
int proxychains_got_chain_data = 0; //~ unsigned int proxychains_max_chain = 1;
unsigned int proxychains_max_chain = 1;
int proxychains_quiet_mode = 0; int proxychains_quiet_mode = 0;
int proxychains_resolver = 0; int proxychains_resolver = 0;
localaddr_arg localnet_addr[MAX_LOCALNET]; //~ localaddr_arg localnet_addr[MAX_LOCALNET];
size_t num_localnet_addr = 0; //~ size_t num_localnet_addr = 0;
unsigned int remote_dns_subnet = 224; //~ unsigned int remote_dns_subnet = 224;
proxy_chain_list *proxychains_chain_list = NULL;
pthread_once_t init_once = PTHREAD_ONCE_INIT; pthread_once_t init_once = PTHREAD_ONCE_INIT;
static int init_l = 0; static int init_l = 0;
static inline void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct); static inline void get_chain_data(proxy_chain_list *pc_list);
static inline int get_chain_type(char *buff, chain_type *ct);
int proxy_chain_load_pdata(proxy_chain *pc, proxy_data *pd_list, int count);
static void* load_sym(char* symname, void* proxyfunc) { static void* load_sym(char* symname, void* proxyfunc) {
@ -104,9 +106,26 @@ static void do_init(void) {
core_initialize(); core_initialize();
at_init(); at_init();
/* Create global library data */
proxychains_chain_list = (proxy_chain_list*)malloc(sizeof(proxy_chain_list));
if (proxychains_chain_list == NULL) {
proxychains_write_log(LOG_PREFIX "Error failed to allocate proxy list object\n");
exit(1);
}
/* Initialize proxychain library data */
proxychains_chain_list->remote_dns_subnet = -1; // -1 means no remote dns
//~ proxychains_chain_list->pc = NULL;
proxychains_chain_list->count = 0;
//~ proxychains_chain_list->localnet_addr = NULL;
proxychains_chain_list->num_localnet_addr = 0;
proxychains_chain_list->tcp_read_time_out = 4 * 1000;
proxychains_chain_list->tcp_connect_time_out = 10 * 1000;
/* read the config file */ /* read the config file */
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct); get_chain_data(proxychains_chain_list);
DUMP_PROXY_CHAIN(proxychains_pd, proxychains_proxy_count); PDEBUG("Finished loading chain data\n");
DUMP_PROXY_CHAIN(proxychains_chain_list->pc[0]);
proxychains_write_log(LOG_PREFIX "DLL init\n"); proxychains_write_log(LOG_PREFIX "DLL init\n");
@ -153,21 +172,19 @@ static void gcc_init(void) {
#endif #endif
/* get configuration from config file */ /* get configuration from config file */
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct) { static void get_chain_data(proxy_chain_list *pc_list) {
static int got_chain_data = 0;
int count = 0, port_n = 0, list = 0; int count = 0, port_n = 0, list = 0;
char buff[1024], type[1024], host[1024], user[1024]; char buff[1024], type[1024], host[1024], label[1024];
char *env; char *env;
char local_in_addr_port[32]; char local_in_addr_port[32];
char local_in_addr[32], local_in_port[32], local_netmask[32]; char local_in_addr[32], local_in_port[32], local_netmask[32];
FILE *file = NULL; FILE *file = NULL;
proxy_chain *pc_curr = NULL;
proxy_data pd_list[MAX_CHAIN];
if(proxychains_got_chain_data) if(got_chain_data)
return; return;
//Some defaults
tcp_read_time_out = 4 * 1000;
tcp_connect_time_out = 10 * 1000;
*ct = DYNAMIC_TYPE;
env = get_config_path(getenv(PROXYCHAINS_CONF_FILE_ENV_VAR), buff, sizeof(buff)); env = get_config_path(getenv(PROXYCHAINS_CONF_FILE_ENV_VAR), buff, sizeof(buff));
if( ( file = fopen(env, "r") ) == NULL ) if( ( file = fopen(env, "r") ) == NULL )
@ -183,60 +200,106 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
while(fgets(buff, sizeof(buff), file)) { while(fgets(buff, sizeof(buff), file)) {
if(buff[0] != '\n' && buff[strspn(buff, " ")] != '#') { if(buff[0] != '\n' && buff[strspn(buff, " ")] != '#') {
/* proxylist has to come last */ /* proxylist has to come last */
if(list) { if(list && (buff[0] != '[')) {
if(count >= MAX_CHAIN) if(count >= MAX_CHAIN)
break; break;
memset(&pd[count], 0, sizeof(proxy_data)); memset(&pd_list[count], 0, sizeof(proxy_data));
pd[count].ps = PLAY_STATE; pd_list[count].ps = PLAY_STATE;
pc_curr->ct = DYNAMIC_TYPE;
pc_curr->tcp_read_time_out = pc_list->tcp_read_time_out;
pc_curr->tcp_connect_time_out = pc_list->tcp_connect_time_out;
port_n = 0; port_n = 0;
if(strstr(buff, "tcp_read_time_out")) {
sscanf(buff, "%s %d", label, &pc_curr->tcp_read_time_out);
} else if(strstr(buff, "tcp_connect_time_out")) {
sscanf(buff, "%s %d", label, &pc_curr->tcp_connect_time_out);
} else if(strstr(buff, "chain_len")) {
char *pc;
int len;
pc = strchr(buff, '=');
len = atoi(++pc);
pc_curr->max_chain = (len ? len : 1);
} else if(!get_chain_type(buff, &pc_curr->ct)) {
;
} else {
pd_list[count].user[0] = pd_list[count].pass[0] = '\0';
sscanf(buff, "%s %s %d %s %s", type, host, &port_n, pd_list[count].user, pd_list[count].pass);
sscanf(buff, "%s %s %d %s %s", type, host, &port_n, pd[count].user, pd[count].pass); in_addr_t host_ip = inet_addr(host);
if(host_ip == INADDR_NONE) {
fprintf(stderr, "proxy %s has invalid value or is not numeric\n", host);
exit(1);
}
pd_list[count].ip.as_int = (uint32_t) host_ip;
pd_list[count].port = htons((unsigned short) port_n);
in_addr_t host_ip = inet_addr(host); if(!strcmp(type, "http")) {
if(host_ip == INADDR_NONE) { pd_list[count].pt = HTTP_TYPE;
fprintf(stderr, "proxy %s has invalid value or is not numeric\n", host); } else if(!strcmp(type, "socks4")) {
exit(1); pd_list[count].pt = SOCKS4_TYPE;
} else if(!strcmp(type, "socks5")) {
pd_list[count].pt = SOCKS5_TYPE;
} else
continue;
} }
pd[count].ip.as_int = (uint32_t) host_ip;
pd[count].port = htons((unsigned short) port_n);
if(!strcmp(type, "http")) { if(pd_list[count].ip.as_int && port_n && pd_list[count].ip.as_int != (uint32_t) - 1)
pd[count].pt = HTTP_TYPE;
} else if(!strcmp(type, "socks4")) {
pd[count].pt = SOCKS4_TYPE;
} else if(!strcmp(type, "socks5")) {
pd[count].pt = SOCKS5_TYPE;
} else
continue;
if(pd[count].ip.as_int && port_n && pd[count].ip.as_int != (uint32_t) - 1)
count++; count++;
} else { } else {
if(strstr(buff, "[ProxyList]")) { char *s1, *s2;
if((s1=strstr(buff, "[")) && (s1 < (s2=strstr(buff, "]")))) {
/* If have a previous chain stored in the temp chain, copy
to global lists. */
if (count) {
proxy_chain_load_pdata(pc_curr, pd_list, count);
count = 0;
}
PDEBUG("Parsing chain: %s\n", buff);
if (pc_list->count >= MAX_CHAIN_LISTS) {
proxychains_write_log(LOG_PREFIX "Warning more than %d lists defined in configfile, skipping any more list definitions.\n", MAX_CHAIN_LISTS);
continue;
}
/* Create new proxy list */
pc_curr = pc_list->pc[pc_list->count++] = (proxy_chain*)malloc(sizeof(proxy_chain));
if (pc_curr == NULL) {
proxychains_write_log(LOG_PREFIX "Error failed to allocate proxy chain object\n");
exit(1);
}
pc_curr->count = 0;
pc_curr->offset = 0;
pc_curr->max_chain = 1;
pc_curr->tcp_read_time_out = pc_list->tcp_read_time_out;
pc_curr->tcp_connect_time_out = pc_list->tcp_connect_time_out;
pc_curr->name = (char*)malloc(sizeof(char)*(s2-s1));
if (pc_curr->name == NULL) {
proxychains_write_log(LOG_PREFIX "Error failed to allocate proxy chain name string\n");
exit(1);
}
strncpy(pc_curr->name, s1, s2-s1);
list = 1; list = 1;
} else if(strstr(buff, "random_chain")) { } else if(!get_chain_type(buff, &pc_list->ct)) {
*ct = RANDOM_TYPE; ;
} else if(strstr(buff, "strict_chain")) {
*ct = STRICT_TYPE;
} else if(strstr(buff, "dynamic_chain")) {
*ct = DYNAMIC_TYPE;
} else if(strstr(buff, "round_robin_chain")) {
*ct = ROUND_ROBIN_TYPE;
} else if(strstr(buff, "tcp_read_time_out")) { } else if(strstr(buff, "tcp_read_time_out")) {
sscanf(buff, "%s %d", user, &tcp_read_time_out); sscanf(buff, "%s %d", label, &pc_list->tcp_read_time_out);
} else if(strstr(buff, "tcp_connect_time_out")) { } else if(strstr(buff, "tcp_connect_time_out")) {
sscanf(buff, "%s %d", user, &tcp_connect_time_out); sscanf(buff, "%s %d", label, &pc_list->tcp_connect_time_out);
} else if(strstr(buff, "remote_dns_subnet")) { } else if(strstr(buff, "remote_dns_subnet")) {
sscanf(buff, "%s %d", user, &remote_dns_subnet); sscanf(buff, "%s %d", label, &pc_list->remote_dns_subnet);
if(remote_dns_subnet >= 256) { if(pc_list->remote_dns_subnet >= 256) {
fprintf(stderr, fprintf(stderr,
"remote_dns_subnet: invalid value. requires a number between 0 and 255.\n"); "remote_dns_subnet: invalid value. requires a number between 0 and 255.\n");
exit(1); exit(1);
} }
} else if(strstr(buff, "localnet")) { } else if(strstr(buff, "localnet")) {
if(sscanf(buff, "%s %21[^/]/%15s", user, local_in_addr_port, local_netmask) < 3) { localaddr_arg *laddr_a = &pc_list->localnet_addr[pc_list->num_localnet_addr];
if(sscanf(buff, "%s %21[^/]/%15s", label, local_in_addr_port, local_netmask) < 3) {
fprintf(stderr, "localnet format error"); fprintf(stderr, "localnet format error");
exit(1); exit(1);
} }
@ -250,38 +313,27 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
PDEBUG("added localnet: netaddr=%s, port=%s, netmask=%s\n", PDEBUG("added localnet: netaddr=%s, port=%s, netmask=%s\n",
local_in_addr, local_in_port, local_netmask); local_in_addr, local_in_port, local_netmask);
} }
if(num_localnet_addr < MAX_LOCALNET) { if(pc_list->num_localnet_addr < MAX_LOCALNET) {
int error; int error;
error = error = inet_pton(AF_INET, local_in_addr, &laddr_a->in_addr);
inet_pton(AF_INET, local_in_addr,
&localnet_addr[num_localnet_addr].in_addr);
if(error <= 0) { if(error <= 0) {
fprintf(stderr, "localnet address error\n"); fprintf(stderr, "localnet address error\n");
exit(1); exit(1);
} }
error = error = inet_pton(AF_INET, local_netmask, &laddr_a->netmask);
inet_pton(AF_INET, local_netmask,
&localnet_addr[num_localnet_addr].netmask);
if(error <= 0) { if(error <= 0) {
fprintf(stderr, "localnet netmask error\n"); fprintf(stderr, "localnet netmask error\n");
exit(1); exit(1);
} }
if(local_in_port[0]) { if(local_in_port[0]) {
localnet_addr[num_localnet_addr].port = laddr_a->port = (short) atoi(local_in_port);
(short) atoi(local_in_port);
} else { } else {
localnet_addr[num_localnet_addr].port = 0; laddr_a->port = 0;
} }
++num_localnet_addr; ++pc_list->num_localnet_addr;
} else { } else {
fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET); fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET);
} }
} else if(strstr(buff, "chain_len")) {
char *pc;
int len;
pc = strchr(buff, '=');
len = atoi(++pc);
proxychains_max_chain = (len ? len : 1);
} else if(strstr(buff, "quiet_mode")) { } else if(strstr(buff, "quiet_mode")) {
proxychains_quiet_mode = 1; proxychains_quiet_mode = 1;
} else if(strstr(buff, "proxy_dns")) { } else if(strstr(buff, "proxy_dns")) {
@ -290,9 +342,43 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
} }
} }
} }
/* If have a previous chain stored in the temp chain, copy
to global lists. This is needed for the last defined chain. */
if (count) {
proxy_chain_load_pdata(pc_curr, pd_list, count);
count = 0;
}
fclose(file); fclose(file);
*proxy_count = count; //~ *proxy_count = count;
proxychains_got_chain_data = 1; got_chain_data = 1;
}
int get_chain_type(char *buff, chain_type *ct) {
if(strstr(buff, "random_chain"))
*ct = RANDOM_TYPE;
else if(strstr(buff, "strict_chain"))
*ct = STRICT_TYPE;
else if(strstr(buff, "dynamic_chain"))
*ct = DYNAMIC_TYPE;
else if(strstr(buff, "round_robin_chain"))
*ct = ROUND_ROBIN_TYPE;
else
return 1;
return 0;
}
int proxy_chain_load_pdata(proxy_chain *pc, proxy_data *pd_list, int count) {
pc->count = count;
pc->pd = (proxy_data*)malloc(sizeof(proxy_data)*count);
if (pc->pd == NULL) {
proxychains_write_log(LOG_PREFIX "Error failed to allocate proxy data list for \"%s\" chain\n", pc->name);
exit(1);
}
memcpy(pc->pd, pd_list, sizeof(proxy_data)*count);
return 0;
} }
/******* HOOK FUNCTIONS *******/ /******* HOOK FUNCTIONS *******/
@ -336,12 +422,12 @@ int connect(int sock, const struct sockaddr *addr, unsigned int len) {
#endif #endif
// check if connect called from proxydns // check if connect called from proxydns
remote_dns_connect = (ntohl(p_addr_in->s_addr) >> 24 == remote_dns_subnet); remote_dns_connect = (ntohl(p_addr_in->s_addr) >> 24 == proxychains_chain_list->remote_dns_subnet);
for(i = 0; i < num_localnet_addr && !remote_dns_connect; i++) { for(i = 0; i < proxychains_chain_list->num_localnet_addr && !remote_dns_connect; i++) {
if((localnet_addr[i].in_addr.s_addr & localnet_addr[i].netmask.s_addr) if((proxychains_chain_list->localnet_addr[i].in_addr.s_addr & proxychains_chain_list->localnet_addr[i].netmask.s_addr)
== (p_addr_in->s_addr & localnet_addr[i].netmask.s_addr)) { == (p_addr_in->s_addr & proxychains_chain_list->localnet_addr[i].netmask.s_addr)) {
if(!localnet_addr[i].port || localnet_addr[i].port == port) { if(!proxychains_chain_list->localnet_addr[i].port || proxychains_chain_list->localnet_addr[i].port == port) {
PDEBUG("accessing localnet using true_connect\n"); PDEBUG("accessing localnet using true_connect\n");
return true_connect(sock, addr, len); return true_connect(sock, addr, len);
} }
@ -357,7 +443,7 @@ int connect(int sock, const struct sockaddr *addr, unsigned int len) {
ret = connect_proxy_chain(sock, ret = connect_proxy_chain(sock,
dest_ip, dest_ip,
SOCKPORT(*addr), SOCKPORT(*addr),
proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain); proxychains_chain_list->pc[0]);
fcntl(sock, F_SETFL, flags); fcntl(sock, F_SETFL, flags);
if(ret != SUCCESS) if(ret != SUCCESS)