diff --git a/src/libproxychains.c b/src/libproxychains.c index 9a036d3..32af0c0 100644 --- a/src/libproxychains.c +++ b/src/libproxychains.c @@ -160,6 +160,103 @@ static void gcc_init(void) { } #endif + +typedef enum { + RS_PT_NONE = 0, + RS_PT_SOCKS4, + RS_PT_SOCKS5, + RS_PT_HTTP +} rs_proxyType; + +/* + proxy_from_string() taken from rocksock network I/O library (C) rofl0r + valid inputs: + socks5://user:password@proxy.domain.com:port + socks5://proxy.domain.com:port + socks4://proxy.domain.com:port + http://user:password@proxy.domain.com:port + http://proxy.domain.com:port + + supplying port number is obligatory. + user:pass@ part is optional for http and socks5. + however, user:pass authentication is currently not implemented for http proxies. + return 1 on success, 0 on error. +*/ +static int proxy_from_string(const char *proxystring, + char *type_buf, + char* host_buf, + int *port_n, + char *user_buf, + char* pass_buf) +{ + const char* p; + rs_proxyType proxytype; + + size_t next_token = 6, ul = 0, pl = 0, hl; + if(!proxystring[0] || !proxystring[1] || !proxystring[2] || !proxystring[3] || !proxystring[4] || !proxystring[5]) goto inv_string; + if(*proxystring == 's') { + switch(proxystring[5]) { + case '5': proxytype = RS_PT_SOCKS5; break; + case '4': proxytype = RS_PT_SOCKS4; break; + default: goto inv_string; + } + } else if(*proxystring == 'h') { + proxytype = RS_PT_HTTP; + next_token = 4; + } else goto inv_string; + if( + proxystring[next_token++] != ':' || + proxystring[next_token++] != '/' || + proxystring[next_token++] != '/') goto inv_string; + const char *at = strchr(proxystring+next_token, '@'); + if(at) { + if(proxytype == RS_PT_SOCKS4) + return 0; + p = strchr(proxystring+next_token, ':'); + if(!p || p >= at) goto inv_string; + const char *u = proxystring+next_token; + ul = p-u; + p++; + pl = at-p; + if(proxytype == RS_PT_SOCKS5 && (ul > 255 || pl > 255)) + return 0; + memcpy(user_buf, u, ul); + user_buf[ul]=0; + memcpy(pass_buf, p, pl); + pass_buf[pl]=0; + next_token += 2+ul+pl; + } else { + user_buf[0]=0; + pass_buf[0]=0; + } + const char* h = proxystring+next_token; + p = strchr(h, ':'); + if(!p) goto inv_string; + hl = p-h; + if(hl > 255) + return 0; + memcpy(host_buf, h, hl); + host_buf[hl]=0; + *port_n = atoi(p+1); + switch(proxytype) { + case RS_PT_SOCKS4: + strcpy(type_buf, "socks4"); + break; + case RS_PT_SOCKS5: + strcpy(type_buf, "socks5"); + break; + case RS_PT_HTTP: + strcpy(type_buf, "http"); + break; + default: + return 0; + } + return 1; +inv_string: + return 0; +} + + /* get configuration from config file */ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct) { int count = 0, port_n = 0, list = 0; @@ -202,9 +299,11 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ int ret = sscanf(buff, "%s %s %d %s %s", type, host, &port_n, pd[count].user, pd[count].pass); if(ret < 3 || ret == EOF) { - inv: - fprintf(stderr, "error: invalid item in proxylist section: %s", buff); - exit(1); + if(!proxy_from_string(buff, type, host, &port_n, pd[count].user, pd[count].pass)) { + inv: + fprintf(stderr, "error: invalid item in proxylist section: %s", buff); + exit(1); + } } memset(&pd[count].ip, 0, sizeof(pd[count].ip));