Skip to content

Commit 1c8f8e4

Browse files
committed
alternatively allow specifying proxy addresses via URL-style strings
e.g. socks5://user:pass@ip:port code taken from my library "rocksock"[0]. [0]: https://github.com/rofl0r/rocksock
1 parent d21af71 commit 1c8f8e4

1 file changed

Lines changed: 102 additions & 3 deletions

File tree

src/libproxychains.c

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,103 @@ static void gcc_init(void) {
160160
}
161161
#endif
162162

163+
164+
typedef enum {
165+
RS_PT_NONE = 0,
166+
RS_PT_SOCKS4,
167+
RS_PT_SOCKS5,
168+
RS_PT_HTTP
169+
} rs_proxyType;
170+
171+
/*
172+
proxy_from_string() taken from rocksock network I/O library (C) rofl0r
173+
valid inputs:
174+
socks5://user:[email protected]:port
175+
socks5://proxy.domain.com:port
176+
socks4://proxy.domain.com:port
177+
http://user:[email protected]:port
178+
http://proxy.domain.com:port
179+
180+
supplying port number is obligatory.
181+
user:pass@ part is optional for http and socks5.
182+
however, user:pass authentication is currently not implemented for http proxies.
183+
return 1 on success, 0 on error.
184+
*/
185+
static int proxy_from_string(const char *proxystring,
186+
char *type_buf,
187+
char* host_buf,
188+
int *port_n,
189+
char *user_buf,
190+
char* pass_buf)
191+
{
192+
const char* p;
193+
rs_proxyType proxytype;
194+
195+
size_t next_token = 6, ul = 0, pl = 0, hl;
196+
if(!proxystring[0] || !proxystring[1] || !proxystring[2] || !proxystring[3] || !proxystring[4] || !proxystring[5]) goto inv_string;
197+
if(*proxystring == 's') {
198+
switch(proxystring[5]) {
199+
case '5': proxytype = RS_PT_SOCKS5; break;
200+
case '4': proxytype = RS_PT_SOCKS4; break;
201+
default: goto inv_string;
202+
}
203+
} else if(*proxystring == 'h') {
204+
proxytype = RS_PT_HTTP;
205+
next_token = 4;
206+
} else goto inv_string;
207+
if(
208+
proxystring[next_token++] != ':' ||
209+
proxystring[next_token++] != '/' ||
210+
proxystring[next_token++] != '/') goto inv_string;
211+
const char *at = strchr(proxystring+next_token, '@');
212+
if(at) {
213+
if(proxytype == RS_PT_SOCKS4)
214+
return 0;
215+
p = strchr(proxystring+next_token, ':');
216+
if(!p || p >= at) goto inv_string;
217+
const char *u = proxystring+next_token;
218+
ul = p-u;
219+
p++;
220+
pl = at-p;
221+
if(proxytype == RS_PT_SOCKS5 && (ul > 255 || pl > 255))
222+
return 0;
223+
memcpy(user_buf, u, ul);
224+
user_buf[ul]=0;
225+
memcpy(pass_buf, p, pl);
226+
pass_buf[pl]=0;
227+
next_token += 2+ul+pl;
228+
} else {
229+
user_buf[0]=0;
230+
pass_buf[0]=0;
231+
}
232+
const char* h = proxystring+next_token;
233+
p = strchr(h, ':');
234+
if(!p) goto inv_string;
235+
hl = p-h;
236+
if(hl > 255)
237+
return 0;
238+
memcpy(host_buf, h, hl);
239+
host_buf[hl]=0;
240+
*port_n = atoi(p+1);
241+
switch(proxytype) {
242+
case RS_PT_SOCKS4:
243+
strcpy(type_buf, "socks4");
244+
break;
245+
case RS_PT_SOCKS5:
246+
strcpy(type_buf, "socks5");
247+
break;
248+
case RS_PT_HTTP:
249+
strcpy(type_buf, "http");
250+
break;
251+
default:
252+
return 0;
253+
}
254+
return 1;
255+
inv_string:
256+
return 0;
257+
}
258+
259+
163260
/* get configuration from config file */
164261
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct) {
165262
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
202299

203300
int ret = sscanf(buff, "%s %s %d %s %s", type, host, &port_n, pd[count].user, pd[count].pass);
204301
if(ret < 3 || ret == EOF) {
205-
inv:
206-
fprintf(stderr, "error: invalid item in proxylist section: %s", buff);
207-
exit(1);
302+
if(!proxy_from_string(buff, type, host, &port_n, pd[count].user, pd[count].pass)) {
303+
inv:
304+
fprintf(stderr, "error: invalid item in proxylist section: %s", buff);
305+
exit(1);
306+
}
208307
}
209308

210309
memset(&pd[count].ip, 0, sizeof(pd[count].ip));

0 commit comments

Comments
 (0)