@@ -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 */
164261static 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