1 /* Socks Server 5
2  * Copyright (C) 2002 - 2011 by Matteo Ricchetti - <matteo.ricchetti@libero.it>
3 
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 
19 
20 #include"SS5Main.h"
21 #include"SS5Defs.h"
22 #include"SS5Utils.h"
23 #include"SS5Mod_socks5.h"
24 #include"SS5Mod_authorization.h"
25 #include"SS5OpenLdap.h"
26 #include"SS5Mod_log.h"
27 
28 #ifdef SS5_USE_GSSAPI
29 #include"SS5GSSApi.h"
30 #endif
31 
32 char *ss5ver=SS5_VERSION;
33 
InitModule(struct _module * m)34 UINT InitModule( struct _module *m )
35 {
36   m->MethodParsing=MethodParsing;
37   m->RequestParsing=RequestParsing;
38   m->UpstreamServing=UpstreamServing;
39   m->ConnectServing=ConnectServing;
40   m->BindServing=BindServing;
41   m->UdpAssociateServing=UdpAssociateServing;
42   m->UdpAssociateResponse=UdpAssociateResponse;
43   m->AddMethod=AddMethod;
44   m->FreeMethod=FreeMethod;
45   m->GetMethod=GetMethod;
46   m->AddRoute=AddRoute;
47   m->FreeRoute=FreeRoute;
48   m->GetRoute=GetRoute;
49   m->AddProxy=AddProxy;
50   m->FreeProxy=FreeProxy;
51   m->GetProxy=GetProxy;
52   m->SrvSocks5=SrvSocks5;
53 
54   return OK;
55 }
56 
ListRoute(UINT s)57 UINT ListRoute( UINT s)
58 {
59   UINT count;
60 
61   struct _S5RouteNode *node, *lnode;
62 
63   char buf[106];
64 
65   for(count = 0;count < MAXROUTELIST; count++) {
66     if( (node=S5RouteList[count]) != NULL) {
67 
68       lnode=node;
69       do {
70         if(lnode != NULL ) {
71           snprintf(buf,sizeof(buf),"%16lu\n%2u\n%16lu\n%64s\n%3u\n",lnode->SrcAddr,lnode->Mask,lnode->SrcIf,lnode->Group,lnode->sd);
72           lnode=lnode->next;
73         }
74 
75         if( send(s,buf,sizeof(buf),0) == -1) {
76           perror("Send err:");
77           return ERR;
78         }
79       } while( lnode != NULL );
80     }
81   }
82   return OK;
83 }
84 
ListMethod(UINT s)85 UINT ListMethod( UINT s)
86 {
87   UINT count;
88 
89   struct _S5MethodNode *lnode, *node;
90 
91   char buf[57];
92 
93   for(count = 0;count < MAXMETHODLIST; count++) {
94     if( (node=S5MethodList[count]) != NULL) {
95 
96       lnode=node;
97       do {
98         if(lnode != NULL ) {
99           snprintf(buf,sizeof(buf),"%3u\n%16lu\n%2u\n%16lu\n%5u\n%5u\n",lnode->Method,lnode->SrcAddr,lnode->Mask,lnode->SrcPort,
100                    lnode->SrcRangeMin,lnode->SrcRangeMax);
101           lnode=lnode->next;
102         }
103 
104         if( send(s,buf,sizeof(buf),0) == -1) {
105           perror("Send err:");
106           return ERR;
107         }
108       } while( lnode != NULL );
109     }
110   }
111   return OK;
112 }
113 
ListProxy(UINT s)114 UINT ListProxy( UINT s)
115 {
116   UINT count;
117 
118   struct _S5ProxyNode *node, *lnode;
119 
120   char buf[80];
121 
122   for(count = 0;count < MAXPROXYLIST; count++) {
123     if( (node=S5ProxyList[count]) != NULL) {
124       lnode=node;
125 
126       do {
127         if(lnode != NULL ) {
128           snprintf(buf,sizeof(buf),"%16lu\n%2u\n%16lu\n%5u\n%5u\n%16lu\n%5u\n%3u\n%3u\n",lnode->DstAddr,lnode->Mask,lnode->DstPort,
129                lnode->DstRangeMin,lnode->DstRangeMax,lnode->ProxyAddr,lnode->ProxyPort,lnode->SocksVer,lnode->Type);
130           lnode=lnode->next;
131         }
132 
133         if( send(s,buf,sizeof(buf),0) == -1) {
134           perror("Send err:");
135           return ERR;
136         }
137       } while( lnode != NULL );
138     }
139   }
140   return OK;
141 }
142 
SrvSocks5(struct _SS5ClientInfo * ci,struct _SS5Socks5Data * sd)143 INT SrvSocks5( struct _SS5ClientInfo *ci, struct _SS5Socks5Data *sd )
144 {
145   UINT method,method2,
146        srcMask,
147        dstMask,
148        socksver,
149        sdr;
150 
151   char logString[128];
152 
153   pid_t pid;
154 
155   struct in_addr in;
156 
157   char sa[64]="\0",
158        sp[16]="\0",
159        da[64]="\0",
160        dp[16]="\0",
161        pa[16]="\0",
162        pp[5]="\0",
163        si[16]="\0",
164        sv[1]="\0",
165        me[1]="\0",
166        me2[1]="\0",
167        grp[64]="\0",
168        dir[1]="\0";
169 
170 
171   char srvResponse[128];
172 
173   /*
174    * Get child/thread pid
175    */
176   if( NOTTHREADED() )
177     pid=getpid();
178   else
179     pid=(UINT)(uintmax_t)pthread_self();
180 
181   if( STREQ(sd->MethodRequest,"ET /list=METHOD HTTP/1.",sizeof("ET /list=METHOD HTTP/1.") - 1) ) {
182 
183     ListMethod(ci->Socket);
184     return OK;
185   }
186   else if( STREQ(sd->MethodRequest,"DD /method=",sizeof("DD /method=") - 1) ) {
187     /*
188      *    Create response
189      */
190     sscanf(sd->MethodRequest,"DD /method=%20s\n%16s\n%1s%1s\n",sa,sp,me,me2);
191 
192     switch(me[0]) {
193       case '-':    method=NOAUTH;      break;
194       case 'u':    method=USRPWD;      break;
195       case 'n':    method=FAKEPWD;     break;
196       case 's':    method=S_USER_PWD;  break;
197 #ifdef SS5_USE_GSSAPI
198       case 'k':    method=GSSAPI;      break;
199 #endif
200     }
201 
202     switch(me2[0]) {
203       case '-':    method2=NOAUTH;      break;
204       case 'u':    method2=USRPWD;      break;
205       case 'n':    method2=FAKEPWD;     break;
206       case 's':    method2=S_USER_PWD;  break;
207 #ifdef SS5_USE_GSSAPI
208       case 'k':    method2=GSSAPI;      break;
209 #endif
210     }
211 
212 
213     srcMask=S5GetNetmask(sa);
214 
215     if( AddMethod(ONLINE,inet_network(sa),S5GetRange(sp),method,method2,32-srcMask) && ( NMethodList < MAXMETHODLIST) ) {
216       strncpy(srvResponse,"OK\0",sizeof("OK\0"));
217       NMethodList++;
218     }
219     else
220       strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
221 
222     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
223       perror("Send err:");
224       return ERR;
225     }
226     return OK;
227   }
228   else if( STREQ(sd->MethodRequest,"EL /method=",sizeof("EL /method=") - 1) ) {
229     /*
230      *    Create response
231      */
232     sscanf(sd->MethodRequest,"EL /method=%20s\n%16s\n%1s%1s\n",sa,sp,me,me2);
233 
234     switch(me[0]) {
235       case '-':    method=NOAUTH;      break;
236       case 'u':    method=USRPWD;      break;
237       case 'n':    method=FAKEPWD;     break;
238       case 's':    method=S_USER_PWD;  break;
239 #ifdef SS5_USE_GSSAPI
240       case 'k':    method=GSSAPI;      break;
241 #endif
242     }
243 
244     switch(me2[0]) {
245       case '-':    method2=NOAUTH;      break;
246       case 'u':    method2=USRPWD;      break;
247       case 'n':    method2=FAKEPWD;     break;
248       case 's':    method2=S_USER_PWD;  break;
249 #ifdef SS5_USE_GSSAPI
250       case 'k':    method2=GSSAPI;      break;
251 #endif
252     }
253 
254     srcMask=S5GetNetmask(sa);
255 
256     if( DelMethod(inet_network(sa),S5GetRange(sp),method,method2,32-srcMask) && (NMethodList > 0) ) {
257       strncpy(srvResponse,"OK\0",sizeof("OK\0"));
258       NMethodList--;
259     }
260     else
261       strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
262 
263     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
264       perror("Send err:");
265       return ERR;
266     }
267     return OK;
268   }
269   else if( STREQ(sd->MethodRequest,"DD /route=",sizeof("DD /route=") - 1) ) {
270     /*
271      *    Create response
272      */
273     sscanf(sd->MethodRequest,"DD /route=%20s\n%16s\n%64s\n%1s\n",sa,si,grp,dir);
274 
275      switch(dir[0]) {
276         case '-':    sdr=SRC_ROUTE;    break;
277         case 's':    sdr=SRC_ROUTE;    break;
278         case 'd':    sdr=DST_ROUTE;    break;
279         default:     SS5Modules.mod_logging.Logging("[ERRO] SS5SRV: Type unknown in route line.");    return ERR;    break;
280     }
281 
282     srcMask=S5GetNetmask(sa);
283     in.s_addr=inet_addr(si);
284 
285     if( AddRoute(ONLINE,inet_network(sa),in.s_addr,grp,32-srcMask,sdr) && ( NRouteList < MAXROUTELIST ) ) {
286       strncpy(srvResponse,"OK\0",sizeof("OK\0"));
287       NRouteList++;
288     }
289     else
290       strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
291 
292     SS5SocksOpt.IsUpstream = OK;
293 
294     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
295       perror("Send err:");
296       return ERR;
297     }
298     return OK;
299   }
300   else if( STREQ(sd->MethodRequest,"EL /route=",sizeof("EL /route=") - 1) ) {
301     /*
302      *    Create response
303      */
304     sscanf(sd->MethodRequest,"EL /route=%20s\n%16s\n%64s\n%1s\n",sa,si,grp,dir);
305 
306      switch(dir[0]) {
307         case '-':    sdr=SRC_ROUTE;    break;
308         case 's':    sdr=SRC_ROUTE;    break;
309         case 'd':    sdr=DST_ROUTE;    break;
310         default:     SS5Modules.mod_logging.Logging("[ERRO] SS5SRV: Type unknown in route line.");    return ERR;    break;
311     }
312 
313     srcMask=S5GetNetmask(sa);
314     in.s_addr=inet_addr(si);
315 
316     if( DelRoute(inet_network(sa),in.s_addr,grp,32-srcMask,sdr) && ( NRouteList > 0 ) ) {
317       strncpy(srvResponse,"OK\0",sizeof("OK\0"));
318       NRouteList--;
319     }
320     else
321       strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
322 
323     SS5SocksOpt.IsUpstream = OK;
324 
325     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
326       perror("Send err:");
327       return ERR;
328     }
329     return OK;
330   }
331   else if( STREQ(sd->MethodRequest,"DD /proxy=",sizeof("DD /proxy=") - 1) ) {
332     /*
333      *    Create response
334      */
335     sscanf(sd->MethodRequest,"DD /proxy=%20s\n%16s\n%16s\n%5s\n%1s\n",da,dp,pa,pp,sv);
336 
337     switch(sv[0]) {
338       case '-':    socksver=SOCKS5_VERSION;    break;
339       case '5':    socksver=SOCKS5_VERSION;    break;
340       case '4':    socksver=SOCKS4_VERSION;    break;
341       default:     SS5Modules.mod_logging.Logging("[ERRO] Version unknown in proxy line.");    return ERR;    break;
342     }
343 
344     dstMask=S5GetNetmask(da);
345 
346     in.s_addr=inet_addr(pa);
347 
348     if( da[0] >64 ) {
349       if( AddProxy(ONLINE,PROXY,S5StrHash(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver) && ( NProxyList < MAXPROXYLIST ) ) {
350         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
351         NProxyList++;
352       }
353       else
354         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
355     }
356     else
357       if( AddProxy(ONLINE,PROXY,inet_network(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver) && ( NProxyList < MAXPROXYLIST ) ) {
358         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
359         NProxyList++;
360       }
361       else
362         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
363 
364     SS5SocksOpt.IsUpstream = OK;
365 
366     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
367       perror("Send err:");
368       return ERR;
369     }
370     return OK;
371   }
372   else if( STREQ(sd->MethodRequest,"DD /noproxy=",sizeof("DD /noproxy=") - 1) ) {
373     /*
374      *    Create response
375      */
376     sscanf(sd->MethodRequest,"DD /noproxy=%20s\n%16s\n%16s\n%5s\n%1s\n",da,dp,pa,pp,sv);
377 
378     switch(sv[0]) {
379       case '-':    socksver=SOCKS5_VERSION;    break;
380       case '5':    socksver=SOCKS5_VERSION;    break;
381       case '4':    socksver=SOCKS4_VERSION;    break;
382       default:     SS5Modules.mod_logging.Logging("[ERRO] Version unknown in proxy line.");    return ERR;    break;
383     }
384 
385     dstMask=S5GetNetmask(da);
386 
387     in.s_addr=inet_addr(pa);
388 
389     if( da[0] >64 ) {
390       if( AddProxy(ONLINE, NOPROXY,S5StrHash(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver) && ( NProxyList < MAXPROXYLIST ) ) {
391         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
392         NProxyList++;
393       }
394       else
395         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
396     }
397     else
398       if( AddProxy(ONLINE,NOPROXY,inet_network(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver) ) {
399         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
400         NProxyList++;
401       }
402       else
403         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
404 
405     SS5SocksOpt.IsUpstream = OK;
406 
407     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
408       perror("Send err:");
409       return ERR;
410     }
411     return OK;
412   }
413   else if( STREQ(sd->MethodRequest,"EL /proxy=",sizeof("EL /proxy=") - 1) ) {
414     /*
415      *    Create response
416      */
417     sscanf(sd->MethodRequest,"EL /proxy=%20s\n%16s\n%16s\n%5s\n%1s\n",da,dp,pa,pp,sv);
418 
419     switch(sv[0]) {
420       case '-':    socksver=SOCKS5_VERSION;    break;
421       case '5':    socksver=SOCKS5_VERSION;    break;
422       case '4':    socksver=SOCKS4_VERSION;    break;
423       default:     SS5Modules.mod_logging.Logging("[ERRO] Version unknown in proxy line.");    return ERR;    break;
424     }
425 
426     dstMask=S5GetNetmask(da);
427 
428     in.s_addr=inet_addr(pa);
429 
430     if( da[0] >64 ) {
431       if( DelProxy(PROXY,S5StrHash(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver) && ( NProxyList > 0 ) ) {
432         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
433         NProxyList--;
434       }
435       else
436         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
437     }
438     else
439       if( DelProxy(PROXY,inet_network(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver) && ( NProxyList > 0 ) ) {
440         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
441         NProxyList--;
442       }
443       else
444         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
445 
446     if( NProxyList == 0 )
447       SS5SocksOpt.IsUpstream = ERR;
448 
449     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
450       perror("Send err:");
451       return ERR;
452     }
453     return OK;
454   }
455   else if( STREQ(sd->MethodRequest,"EL /noproxy=",sizeof("EL /noproxy=") - 1) ) {
456     /*
457      *    Create response
458      */
459     sscanf(sd->MethodRequest,"EL /noproxy=%20s\n%16s\n%16s\n%5s\n%1s\n",da,dp,pa,pp,sv);
460 
461     switch(sv[0]) {
462       case '-':    socksver=SOCKS5_VERSION;    break;
463       case '5':    socksver=SOCKS5_VERSION;    break;
464       case '4':    socksver=SOCKS4_VERSION;    break;
465       default:     SS5Modules.mod_logging.Logging("[ERRO] Version unknown in proxy line.");    return ERR;    break;
466     }
467 
468     dstMask=S5GetNetmask(da);
469 
470     in.s_addr=inet_addr(pa);
471 
472     if( da[0] >64 ) {
473       if( DelProxy(NOPROXY,S5StrHash(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver) && ( NProxyList > 0 ) ) {
474         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
475         NProxyList--;
476       }
477       else
478         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
479     }
480     else
481       if( DelProxy(NOPROXY,inet_network(da),S5GetRange(dp),in.s_addr,atoi(pp),32-dstMask,socksver)&& ( NProxyList > 0 ) ) {
482         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
483         NProxyList++;
484       }
485       else
486         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
487 
488     if( NProxyList == 0 )
489       SS5SocksOpt.IsUpstream = ERR;
490 
491     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
492       perror("Send err:");
493       return ERR;
494     }
495     return OK;
496   }
497   else if( STREQ(sd->MethodRequest,"ET /list=PROXY HTTP/1.",sizeof("ET /list=PROXY HTTP/1.") - 1) ) {
498     ListProxy(ci->Socket);
499     return OK;
500   }
501   else if( STREQ(sd->MethodRequest,"ET /list=ROUTE HTTP/1.",sizeof("ET /list=ROUTE HTTP/1.") - 1) ) {
502     ListRoute(ci->Socket);
503     return OK;
504   }
505 
506   return ERR_SRV_REQUEST;
507 }
508 
509 
MethodParsing(struct _SS5ClientInfo * ci,struct _SS5Socks5Data * sd)510 UINT MethodParsing( struct _SS5ClientInfo *ci, struct _SS5Socks5Data *sd)
511 {
512 
513   register UINT i;
514 
515   char logString[128];
516 
517   pid_t pid;
518 
519   /*
520   * Get child/thread pid
521   */
522   if( NOTTHREADED() )
523     pid=getpid();
524   else
525     pid=(UINT)(uintmax_t)pthread_self();
526 
527   /*
528    * Receive socks version
529    */
530   if( recv(ci->Socket,(unsigned short *)&ci->Ver,1,0) <= 0 ) {
531     ERRNO(pid)
532     return ERR;
533   }
534   if( DEBUG() ) {
535     snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [METHOD PACKET] Receiving socks version: %d.",pid,ci->Ver);
536     LOGUPDATE()
537   }
538 
539 #ifdef SS5_USE_GSSAPI
540   /*
541    * Reset GSS encapsulation flag
542    */
543   ci->GssEnc=GSS_NO_ENC;
544 #endif
545 
546   switch( ci->Ver ) {
547 
548     case SOCKS4_VERSION:
549 
550       ci->NMeth=0;
551       ci->NoAuth=ERR;
552       ci->BasicAuth=ERR;
553       ci->GssApiAuth=ERR;
554       ci->SecureBasicAuth=ERR;
555 
556       return OK;
557     break;
558 
559     case SOCKS5_VERSION:
560       /*
561        * Receive the number of method
562        */
563       if( recv(ci->Socket,(unsigned short *)&ci->NMeth,1,0) <= 0 ) {
564         ERRNO(pid)
565         return ERR;
566       }
567       if( DEBUG() ) {
568         snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [METHOD PACKET] Receiving number of methods: %d.",pid,ci->NMeth);
569         LOGUPDATE()
570       }
571 
572       /*
573        * Buffer validate
574        */
575       if( ci->NMeth > sizeof(sd->MethodRequest) )
576         ci->NMeth=sizeof(sd->MethodRequest);
577 
578       /*
579        * Receive the list of methods
580        */
581       if( sd->MethodBytesReceived=recv(ci->Socket,(void *)sd->MethodRequest,ci->NMeth,0) <= 0 ) {
582         ERRNO(pid)
583         return ERR;
584       }
585 
586       for(i=0;i<(ci->NMeth);i++) {
587         switch(sd->MethodRequest[i]) {
588 
589           case NOAUTH:     ci->NoAuth=OK;          break;
590           case USRPWD:     ci->BasicAuth=OK;       break;
591           case S_USER_PWD: ci->SecureBasicAuth=OK; break;
592 #ifdef SS5_USE_GSSAPI
593           case GSSAPI:     ci->GssApiAuth=OK;      break;
594 #endif
595         }
596         if( DEBUG() ) {
597           snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [METHOD PACKET] Receiving supported client methods: %d.",pid,sd->MethodRequest[i]);
598           LOGUPDATE()
599         }
600       }
601 
602       /*
603        * Create response method
604        */
605       sd->MethodResponse[0]=SOCKS5_VERSION;
606 
607       switch( GetMethod(ci) ) {
608 
609         case NOAUTH:     sd->MethodResponse[1] = NOAUTH;     ci->Method = NOAUTH;     break;
610         case USRPWD:     sd->MethodResponse[1] = USRPWD;     ci->Method = USRPWD;     break;
611         case FAKEPWD:    sd->MethodResponse[1] = USRPWD;     ci->Method = FAKEPWD;    break;
612         case S_USER_PWD: sd->MethodResponse[1] = S_USER_PWD; ci->Method = S_USER_PWD; break;
613 #ifdef SS5_USE_GSSAPI
614         case GSSAPI:     sd->MethodResponse[1] = GSSAPI;     ci->Method = GSSAPI;
615                          ci->GssEnc=GSS_ENC_NOINT;                                    break;
616 #endif
617         default:
618           sd->MethodResponse[1] = NOMETHOD; ci->Method = NOMETHOD;
619 
620           /*
621            * Send response V5 to client containing supported methods
622            */
623           if( (sd->MethodBytesSent = send(ci->Socket,sd->MethodResponse,sizeof(sd->MethodResponse),SS5_SEND_OPT)) == -1) {
624             ERRNO(pid)
625             return ERR;
626           }
627           return ERR;
628         break;
629       }
630 
631       /*
632        * Send response V5 to client containing supported methods
633        */
634       if( (sd->MethodBytesSent = send(ci->Socket,sd->MethodResponse,sizeof(sd->MethodResponse),SS5_SEND_OPT)) == -1) {
635         ERRNO(pid);
636         return ERR;
637       }
638       return OK;
639 
640     break;
641 
642     /* WRONG socks version or SS5SRV request */
643     default:
644       if( VERBOSE() ) {
645         snprintf(logString,sizeof(logString) - 1,"[%u] [VERB] SOCKS protocol version not supported.",pid);
646         LOGUPDATE()
647       }
648       /*
649        * Try receiving a SS5SRV request
650        */
651       if( recv(ci->Socket,sd->MethodRequest,sizeof(sd->MethodRequest),0) <= 0 ) {
652         ERRNO(pid);
653         return ERR;
654       }
655       return ERR_SRV_REQUEST;
656     break;
657   }
658 
659   return ERR;
660 }
661 
662 
RequestParsing(struct _SS5ClientInfo * ci,struct _SS5Socks5Data * sd,struct _SS5RequestInfo * ri)663 UINT RequestParsing(struct _SS5ClientInfo *ci, struct _SS5Socks5Data *sd, struct _SS5RequestInfo *ri)
664 {
665   UINT i=0,
666        c=0,
667        len=0;
668 
669   SINT rsv=0,
670        l=0;
671 
672   char logString[256];
673 
674   unsigned char *oubuf =NULL;
675 
676   pid_t pid;
677 
678   /*
679   * Get child/thread pid
680   */
681   if( NOTTHREADED() )
682     pid=getpid();
683   else
684     pid=(UINT)(uintmax_t)pthread_self();
685 
686   memset((char *)sd->TcpRequest, 0, sizeof(sd->TcpRequest));
687 
688 #ifdef SS5_USE_GSSAPI
689  /*
690   * If GSS method, receive payload and decode client token
691   */
692   if( GSSAPI() && GSSINTEGRITY() ) {
693     if( (sd->TcpRBytesReceived=recv(ci->Socket,sd->TcpRequest,sizeof(sd->TcpRequest),0)) <= 0 ) {
694       ERRNO(pid)
695       return ERR;
696     }
697 
698     len=sd->TcpRBytesReceived;
699     if( S5GSSApiDecode(ci->GssContext, ci->GssEnc, sd->TcpRequest, &oubuf, &len) ) {
700 
701       memcpy(sd->TcpRequest,oubuf,len);
702       if( oubuf ) {
703         free(oubuf);
704         oubuf=NULL;
705       }
706     }
707     else
708       return ERR;
709 
710     ri->Ver=(unsigned char)sd->TcpRequest[0];
711     ri->Cmd=(unsigned char)sd->TcpRequest[1];
712 
713     /*
714      * Validate SOCKS5 command field
715      */
716     if( (ri->Cmd > 3) || (ri->Cmd < 1) )
717       return ERR;
718 
719     switch( sd->TcpRequest[3] ) {
720       case IPV4:
721         /*
722          * Destination address is dot notation
723          */
724         ri->ATyp=IPV4;
725 
726         ri->DstPort=0;
727         ri->DstPort +=(unsigned char)sd->TcpRequest[8];
728         ri->DstPort <<=8;
729         ri->DstPort +=(unsigned char)sd->TcpRequest[9];
730 
731         snprintf(ri->DstAddr,sizeof(ri->DstAddr),"%hu.%hu.%hu.%hu",(unsigned char)sd->TcpRequest[4],
732                                                                    (unsigned char)sd->TcpRequest[5],
733                                                                    (unsigned char)sd->TcpRequest[6],
734                                                                    (unsigned char)sd->TcpRequest[7]);
735       break;
736 
737       case IPV6: /* Not supported */
738         return (-1 * S5REQUEST_ADDNOTSUPPORT);
739       break;
740 
741       case DOMAIN:
742         /*
743          * Destination address is FQDN
744          */
745         len=(unsigned char)sd->TcpRequest[4] + 5;
746         ri->DstPort=0;
747         ri->DstPort +=(unsigned char)sd->TcpRequest[len];
748         ri->DstPort <<=8;
749         ri->DstPort +=(unsigned char)sd->TcpRequest[len+1];
750 
751         for(c=0,i=5;i<len;i++,c++ )
752           ri->DstAddr[c]=(unsigned char)sd->TcpRequest[i];
753 
754         ri->DstAddr[c]='\0';
755         ri->ATyp=DOMAIN;
756       break;
757     }
758   }
759   else {
760 #endif
761     /*
762      * Receive socks protocol version
763      */
764     if( (sd->TcpRBytesReceived=recv(ci->Socket,(short int *)&ri->Ver,1,0)) <= 0 ) {
765       ERRNO(pid)
766       return ERR;
767     }
768     if( DEBUG() ) {
769       snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [S5 REQUEST PACKET] Receiving request protocol version: %hu",pid,ri->Ver);
770       LOGUPDATE()
771     }
772 
773     /*
774      * Receive socks protocol command
775      */
776     if( (sd->TcpRBytesReceived=recv(ci->Socket,(short int *)&ri->Cmd,1,0)) <= 0 ) {
777       ERRNO(pid)
778       return ERR;
779     }
780     if( DEBUG() ) {
781       snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [S5 REQUEST PACKET] Receiving request protocol command: %hu",pid,ri->Cmd);
782       LOGUPDATE()
783     }
784 
785     /*
786      * Receive socks protocol RSV field
787      */
788     if( (sd->TcpRBytesReceived=recv(ci->Socket,(short int *)&rsv,1,0)) <= 0 ) {
789       ERRNO(pid)
790       return ERR;
791     }
792     if( DEBUG() ) {
793       snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [S5 REQUEST PACKET] Receiving request protocol RSV field: %hu",pid,rsv);
794       LOGUPDATE()
795     }
796 
797     /*
798      * Receive socks protocol address type
799      */
800     if( (sd->TcpRBytesReceived=recv(ci->Socket,(short int *)&ri->ATyp,1,0)) <= 0 ) {
801       ERRNO(pid)
802       return ERR;
803     }
804     if( DEBUG() ) {
805       snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [S5 REQUEST PACKET] Receiving request protocol address type: %hu",pid,ri->ATyp);
806       LOGUPDATE()
807     }
808 
809     switch( ri->ATyp ) {
810       case IPV4:
811         /*
812          * Destination address is dot notation. Receive destination ip and port
813          */
814         if( (sd->TcpRBytesReceived=recv(ci->Socket,sd->TcpRequest,6,0)) <= 0 ) {
815           ERRNO(pid)
816           return ERR;
817         }
818         ri->ATyp=IPV4;
819 
820         ri->DstPort=0;
821         ri->DstPort +=(unsigned char)sd->TcpRequest[4];
822         ri->DstPort <<=8;
823         ri->DstPort +=(unsigned char)sd->TcpRequest[5];
824 
825         snprintf(ri->DstAddr,sizeof(ri->DstAddr),"%hu.%hu.%hu.%hu",(unsigned char)sd->TcpRequest[0],
826                                                                    (unsigned char)sd->TcpRequest[1],
827                                                                    (unsigned char)sd->TcpRequest[2],
828                                                                    (unsigned char)sd->TcpRequest[3]);
829       break;
830 
831       case IPV6: /* Not supported */
832         return (-1 * S5REQUEST_ADDNOTSUPPORT);
833       break;
834 
835       case DOMAIN:
836         /*
837          * Destination address is FQDN. Receive socks protocol FQDN length
838          */
839         if( (sd->TcpRBytesReceived=recv(ci->Socket,(SINT *)&l,1,0)) <= 0 ) {
840           ERRNO(pid)
841           return ERR;
842         }
843         if( DEBUG() ) {
844           snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [S5 REQUEST PACKET] Receiving request protocol FQDN length: %hu",pid,l);
845           LOGUPDATE()
846         }
847 
848         /*
849          * Validate FQDN length
850          */
851          if( l > sizeof(ri->DstAddr) )
852            l=sizeof(ri->DstAddr);
853 
854         /*
855          * Receive socks protocol destination FQDN
856          */
857         if( (sd->TcpRBytesReceived=recv(ci->Socket,ri->DstAddr,l,0)) <= 0 ) {
858           ERRNO(pid)
859           return ERR;
860         }
861         ri->DstAddr[l+1]='\0';
862 
863         /*
864          * Receive socks protocol destination port
865          */
866         if( (sd->TcpRBytesReceived=recv(ci->Socket,&sd->TcpRequest,2,0)) <= 0 ) {
867           ERRNO(pid)
868           return ERR;
869         }
870         ri->DstPort=0;
871         ri->DstPort +=(unsigned char)sd->TcpRequest[0];
872         ri->DstPort <<=8;
873         ri->DstPort +=(unsigned char)sd->TcpRequest[1];
874 
875       break;
876 
877     }
878 
879     if( DEBUG() ) {
880       snprintf(logString,sizeof(logString) - 1,"[%u] [DEBU] [S5 REQUEST PACKET] Receiving request protocol destination address and port: %s:%u",pid,ri->DstAddr,ri->DstPort);
881       LOGUPDATE()
882     }
883 
884 #ifdef SS5_USE_GSSAPI
885   }
886 #endif
887 
888   return OK;
889 }
890 
891 
UpstreamServing(struct _SS5ClientInfo * ci,struct _SS5RequestInfo * ri,struct _SS5Socks5Data * sd)892 UINT UpstreamServing(struct _SS5ClientInfo *ci, struct _SS5RequestInfo *ri, struct _SS5Socks5Data *sd)
893 {
894   UINT i,len,ln2;
895 
896   struct sockaddr_in applicationSsin,
897                      bindInterfaceSsin;
898 
899   char logString[128];
900 
901   pid_t pid;
902 
903   struct in_addr in;
904 
905   int bytes;
906 
907   /*
908    *    Get child/thread pid
909    */
910   if( NOTTHREADED() )
911     pid=getpid();
912   else
913     pid=(UINT)(uintmax_t)pthread_self();
914 
915   if ( (ci->appSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
916     ERRNO(pid)
917     return( -1 * S5REQUEST_ISERROR );
918   }
919 
920   /*
921    * SS5: set bind interface if configured
922    */
923   if( ROUTE() ) {
924     if( (in.s_addr=(ULINT)GetRoute(inet_network(ci->SrcAddr), inet_network(ri->DstAddr), ci->Username)) ) {
925 
926       memset((char *)&bindInterfaceSsin, 0, sizeof(struct sockaddr_in));
927 
928       if( (bindInterfaceSsin.sin_addr.s_addr=in.s_addr) ) {
929         bindInterfaceSsin.sin_family      = AF_INET;
930         bindInterfaceSsin.sin_port        = htons(0);
931 
932         if ( bind(ci->appSocket, (struct sockaddr *)&bindInterfaceSsin, sizeof(struct sockaddr_in)) == -1 ) {
933           ERRNO(pid)
934           return( -1 * S5REQUEST_ISERROR );
935         }
936       }
937     }
938   }
939 
940   memset((char *)&applicationSsin, 0, sizeof(struct sockaddr_in));
941   applicationSsin.sin_family      = AF_INET;
942   applicationSsin.sin_port        = htons(ri->upDstPort);
943   applicationSsin.sin_addr.s_addr = (ULINT)ri->upDstAddr;
944 
945   if( connect(ci->appSocket,(struct sockaddr *)&applicationSsin,sizeof(struct sockaddr_in)) != -1 ) {
946     /*
947      * If upstream is requested in V5
948      * proxy client methods towards upstream socks server
949      */
950     if( (ri->upSocksVer == SOCKS5_VERSION) && (ci->Ver == SOCKS5_VERSION) ) {
951       if( send(ci->appSocket,&ci->Ver,1,SS5_SEND_OPT) == -1) {
952         ERRNO(pid)
953         return( -1 * S5REQUEST_ISERROR );
954       }
955       if( send(ci->appSocket,&ci->NMeth,1,SS5_SEND_OPT) == -1) {
956         ERRNO(pid)
957         return( -1 * S5REQUEST_ISERROR );
958       }
959       if( send(ci->appSocket,sd->MethodRequest,ci->NMeth,SS5_SEND_OPT) == -1) {
960         ERRNO(pid)
961         return( -1 * S5REQUEST_ISERROR );
962       }
963       if( recv(ci->appSocket,sd->MethodResponse,sizeof(sd->MethodResponse),0) <= 0 ) {
964         ERRNO(pid)
965         return( -1 * S5REQUEST_ISERROR );
966       }
967 
968       /*
969        * If needed, proxy username and password
970        */
971       if (ci->Method == USRPWD || ci->Method == FAKEPWD ) {
972 
973         if( VERBOSE() ) {
974           snprintf(logString,sizeof(logString) - 1,"[%u] [VERB] Sending user credentials for authentication.",pid);
975           LOGUPDATE()
976         }
977 
978         ci->Request[0]=1;
979         len=strlen(ci->Username);
980         ci->Request[1]=len;
981 
982         for(i=0;i<len;i++)
983           ci->Request[i+2]=ci->Username[i];
984 
985         ln2=strlen(ci->Password);
986         ci->Request[len+2]=ln2;
987 
988         for(i=0;i<ln2;i++)
989           ci->Request[len+i+3]=ci->Password[i];
990 
991         if( send(ci->appSocket,ci->Request,len+ln2+3,SS5_SEND_OPT) == -1) {
992           ERRNO(pid)
993           return( -1 * S5REQUEST_ISERROR );
994         }
995 
996         if( recv(ci->appSocket,ci->Response,sizeof(ci->Response),0) <= 0 ) {
997           ERRNO(pid)
998           return( -1 * S5REQUEST_ISERROR );
999         }
1000       }
1001     }
1002 
1003     /*
1004      * If upstream is requested in V4, ss5 converts V5 request to V4 request before sending
1005      * it to upstream socks server
1006      */
1007     memset((char *)sd->TcpRequest, 0, sizeof(sd->TcpRequest));
1008 
1009     if( (ri->upSocksVer == SOCKS4_VERSION) && (ci->Ver == SOCKS5_VERSION) ) {
1010 
1011       if( (ri->Cmd == CONNECT) ) {
1012         sd->TcpRequest[0]=4;
1013         sd->TcpRequest[1]=ri->Cmd;
1014 
1015         if( send(ci->appSocket,sd->TcpRequest,2,SS5_SEND_OPT) == -1) {
1016           ERRNO(pid)
1017           return( -1 * S5REQUEST_ISERROR );
1018         }
1019 
1020         memset((char *)sd->TcpRequest, 0, sizeof(sd->TcpRequest));
1021 
1022         SETPORT_R(sd->TcpRequest,ri->DstPort,0)
1023         SETADDR(sd->TcpRequest,inet_addr(ri->DstAddr),2)
1024 
1025         if( send(ci->appSocket,sd->TcpRequest,6,SS5_SEND_OPT) == -1) {
1026           ERRNO(pid)
1027           return( -1 * S5REQUEST_ISERROR );
1028         }
1029 
1030         memset((char *)sd->TcpRequest, 0, sizeof(sd->TcpRequest));
1031 
1032         if( ci->Method == NOAUTH )
1033           strncpy(ci->Username,"NOAUTH",strlen("NOAUTH"));
1034 
1035         memcpy(sd->TcpRequest,ci->Username,strlen(ci->Username));
1036 
1037         if( send(ci->appSocket,sd->TcpRequest,strlen(ci->Username)+1,SS5_SEND_OPT) == -1) {
1038           ERRNO(pid)
1039           return( -1 * S5REQUEST_ISERROR );
1040         }
1041         /*
1042          * If SOCKS 4A draft, send FQDN at the end of SOCKS 4 request
1043          */
1044         if( ri->ATyp == DOMAIN ) {
1045           memset((char *)sd->TcpRequest, 0, sizeof(sd->TcpRequest));
1046 
1047           memcpy(sd->TcpRequest,ri->DstAddr,strlen(ri->DstAddr));
1048 
1049           if( send(ci->appSocket,sd->TcpRequest,strlen(ri->DstAddr)+1,SS5_SEND_OPT) == -1) {
1050             ERRNO(pid)
1051             return( -1 * S5REQUEST_ISERROR );
1052           }
1053         }
1054 
1055         if( VERBOSE() ) {
1056           snprintf(logString,sizeof(logString) - 1,"[%u] [VERB] %s V5 request converted to V4 before sending to remote socks.",pid,(ri->Cmd==CONNECT)?"CONNECT":"BIND");
1057           LOGUPDATE()
1058         }
1059       }
1060       else {
1061         if( VERBOSE() ) {
1062           snprintf(logString,sizeof(logString) - 1,"[%u] [VERB] V5 conversion to V4 not supported with BIND or UDP_ASSOCIATE  command.",pid);
1063           LOGUPDATE()
1064         }
1065 
1066         ERRNO(pid)
1067         return( -1 * S5REQUEST_ISERROR );
1068       }
1069     }
1070     else {
1071 
1072       /*
1073        * Proxy client connect request to upstream socks server
1074        */
1075 
1076       sd->TcpRequest[0]=ri->Ver;
1077       sd->TcpRequest[1]=ri->Cmd;
1078       sd->TcpRequest[2]=0;
1079       sd->TcpRequest[3]=ri->ATyp;
1080 
1081       if( send(ci->appSocket,sd->TcpRequest,4,SS5_SEND_OPT) == -1) {
1082         ERRNO(pid)
1083         return( -1 * S5REQUEST_ISERROR );
1084       }
1085 
1086       SETADDR(sd->TcpRequest,inet_addr(ri->DstAddr),0)
1087       SETPORT_R(sd->TcpRequest,ri->DstPort,4)
1088       if( send(ci->appSocket,sd->TcpRequest,6,SS5_SEND_OPT) == -1) {
1089         ERRNO(pid)
1090         return( -1 * S5REQUEST_ISERROR );
1091       }
1092     }
1093 
1094 
1095     if( ri->Cmd == CONNECT ) {
1096       if( (sd->TcpRBytesReceived=recv(ci->appSocket,sd->Response,sizeof(sd->Response),0)) <= 0 ) {
1097         ERRNO(pid)
1098         return( -1 * S5REQUEST_ISERROR );
1099       }
1100 
1101       /*
1102        * If upstream is requested in V4, only for CONNECT, ss5 converts V4 response to V5 response before sending
1103        * it back to client
1104        */
1105       bytes=sd->TcpRBytesReceived;
1106 
1107       if( (ri->upSocksVer == SOCKS4_VERSION) && (ci->Ver=SOCKS5_VERSION) )
1108         bytes=V42V5Response(sd, ri, ci);
1109 
1110       if( send(ci->Socket,sd->Response,bytes,SS5_SEND_OPT) == -1) {
1111         ERRNO(pid)
1112         return( -1 * S5REQUEST_ISERROR );
1113       }
1114     }
1115 
1116     if( ri->Cmd == BIND ) {
1117       /*
1118        * Proxy client bind request towards upstream socks server
1119        */
1120       if( (sd->TcpRBytesReceived=recv(ci->appSocket,sd->Response,sizeof(sd->Response),0)) <= 0 ) {
1121         ERRNO(pid)
1122         return( -1 * S5REQUEST_ISERROR );
1123       }
1124       /*
1125        * Intercept bind ip address: if equal 0.0.0.0, replace it
1126        */
1127       if( sd->Response[4] == 0 && sd->Response[5] == 0 && sd->Response[6] == 0 && sd->Response[7] == 0 ) {
1128 
1129         SETADDR_R(sd->Response,ri->upDstAddr,4)
1130       }
1131 
1132       if( (ri->upSocksVer == SOCKS4_VERSION) && (ci->Ver=SOCKS5_VERSION) ) {
1133         if( VERBOSE() )
1134           SS5Modules.mod_logging.Logging("[VERB] Upstream conversion from 5 to 4 not permitted with BIND request.");
1135 
1136         return( -1 * S5REQUEST_ISERROR );
1137       }
1138 
1139       if( send(ci->Socket,sd->Response,sd->TcpRBytesReceived,SS5_SEND_OPT) == -1) {
1140         ERRNO(pid)
1141         return( -1 * S5REQUEST_ISERROR );
1142       }
1143     }
1144     return OK;
1145   }
1146   else {
1147     return( -1 * S5REQUEST_HOSTUNREACH );
1148   }
1149 
1150   return OK;
1151 }
1152 
1153 
ConnectServing(struct _SS5ClientInfo * ci,struct _SS5RequestInfo * ri,struct _SS5Socks5Data * sd)1154 UINT ConnectServing(struct _SS5ClientInfo *ci, struct _SS5RequestInfo *ri, struct _SS5Socks5Data *sd)
1155 {
1156   register UINT i,index;
1157 
1158   UINT len;
1159 
1160   char logString[128];
1161 
1162   unsigned char *oubuf=NULL;
1163 
1164   UINT err=S5REQUEST_SUCCEDED;
1165 
1166   UINT resolvedHostNumber=0;
1167 
1168   struct _S5HostList resolvedHostList[MAXDNS_RESOLV];
1169 
1170   struct sockaddr_in applicationSsin,
1171                      bindInterfaceSsin;
1172 
1173   struct in_addr in;
1174 
1175   pid_t pid;
1176 
1177   /*
1178   * Get child/thread pid
1179   */
1180   if( NOTTHREADED() )
1181     pid=getpid();
1182   else
1183     pid=(UINT)(uintmax_t)pthread_self();
1184 
1185   /*
1186    * SS5: Resolve hostname before connecting
1187    */
1188   if( ri->ATyp == DOMAIN ) {
1189     if( S5ResolvHostName(ri, (struct _S5HostList *)resolvedHostList, &resolvedHostNumber) == ERR )
1190       err=S5REQUEST_ISERROR;
1191   }
1192 
1193   if( err == S5REQUEST_SUCCEDED ) {
1194     if ( (ci->appSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1195       ERRNO(pid)
1196       err=S5REQUEST_ISERROR;
1197     }
1198     else {
1199       /*
1200        * SS5: set bind interface if configured
1201        */
1202       if( ci->framedRoute.sin_addr.s_addr ) {
1203         memset((char *)&bindInterfaceSsin, 0, sizeof(struct sockaddr_in));
1204         bindInterfaceSsin.sin_family      = AF_INET;
1205         bindInterfaceSsin.sin_port        = htons(0);
1206 
1207         bindInterfaceSsin.sin_addr.s_addr=ci->framedRoute.sin_addr.s_addr;
1208 
1209         if ( bind(ci->appSocket, (struct sockaddr *)&bindInterfaceSsin, sizeof(struct sockaddr_in)) == -1 ) {
1210           ERRNO(pid)
1211           err=S5REQUEST_ISERROR;
1212         }
1213       }
1214       else if( ROUTE() ) {
1215         /*
1216          * SS5: set bind interface if configured
1217          */
1218         if( (in.s_addr=(ULINT)GetRoute(inet_network(ci->SrcAddr), inet_network(ri->DstAddr), ci->Username)) ) {
1219 
1220           memset((char *)&bindInterfaceSsin, 0, sizeof(struct sockaddr_in));
1221           if( (bindInterfaceSsin.sin_addr.s_addr=in.s_addr) )
1222           {
1223             bindInterfaceSsin.sin_family      = AF_INET;
1224             bindInterfaceSsin.sin_port        = htons(0);
1225 
1226             if ( bind(ci->appSocket, (struct sockaddr *)&bindInterfaceSsin, sizeof(struct sockaddr_in)) == -1 ) {
1227               ERRNO(pid)
1228               err=S5REQUEST_ISERROR;
1229             }
1230           }
1231         }
1232       }
1233 
1234       if( err == S5REQUEST_SUCCEDED ) {
1235         bzero((char *)&applicationSsin, sizeof(struct sockaddr_in));
1236         applicationSsin.sin_family      = AF_INET;
1237         applicationSsin.sin_port        = htons(ri->DstPort);
1238         applicationSsin.sin_addr.s_addr = inet_addr(ri->DstAddr);
1239 
1240         if( connect(ci->appSocket,(struct sockaddr *)&applicationSsin,sizeof(struct sockaddr_in)) == -1 ) {
1241           ERRNO(pid)
1242           err=S5REQUEST_CONNREFUSED;
1243           /*
1244            * Try connecting to other destinations in case of multiple dns answers
1245            */
1246           for(index=1;index<resolvedHostNumber;index++) {
1247             strncpy(ri->DstAddr,resolvedHostList[index].NextHost,sizeof(ri->DstAddr));
1248 
1249             applicationSsin.sin_addr.s_addr = inet_addr(ri->DstAddr);
1250 
1251             if( connect(ci->appSocket,(struct sockaddr *)&applicationSsin,sizeof(struct sockaddr_in)) == 0 ) {
1252               err=S5REQUEST_SUCCEDED;
1253               break;
1254             }
1255           }
1256         }
1257       }
1258     }
1259   }
1260 
1261   /*
1262    * Prepare and send socks V5 response
1263    */
1264   len=10;
1265   memcpy(sd->Response,sd->TcpRequest,32);
1266 
1267   sd->Response[0]=SOCKS5_VERSION;
1268   sd->Response[1]=err;
1269   sd->Response[2]=0;
1270   sd->Response[3]=IPV4;
1271 
1272   SETADDR(sd->Response,inet_addr(ri->DstAddr),4)
1273   SETPORT_R(sd->Response,ri->DstPort,8)
1274 
1275 #ifdef SS5_USE_GSSAPI
1276  /*
1277   * If GSS method, encode response before sending to client
1278   */
1279   if( GSSAPI() && GSSINTEGRITY() ) {
1280     if( S5GSSApiEncode(ci->GssContext, ci->GssEnc, sd->Response, &oubuf, &len) ) {
1281 
1282       memcpy(sd->Response,oubuf,len);
1283       if( oubuf ) {
1284         free(oubuf);
1285         oubuf = NULL;
1286       }
1287     }
1288     else
1289       return( -1 * S5REQUEST_GSSERROR);
1290   }
1291 #endif
1292 
1293   switch( ri->ATyp ) {
1294     /*
1295      *    Socks V5 Header is 10 bytes
1296      */
1297     case IPV4:
1298     case DOMAIN:
1299       if( send(ci->Socket,sd->Response,len,SS5_SEND_OPT) == -1) {
1300         ERRNO(pid)
1301         err=S5REQUEST_ISERROR;
1302       }
1303       break;
1304     /*
1305      *    Socks V5 Header is 22 bytes but IPV6 is not supported
1306      */
1307     case IPV6:    err=S5REQUEST_ADDNOTSUPPORT;    break;
1308   }
1309 
1310   if( err != S5REQUEST_SUCCEDED )
1311      return (-1 * err);
1312   else
1313     return OK;
1314 }
1315 
BindServing(struct _SS5ClientInfo * ci,struct _SS5RequestInfo * ri,struct _SS5Socks5Data * sd)1316 UINT BindServing(struct _SS5ClientInfo *ci, struct _SS5RequestInfo *ri, struct _SS5Socks5Data *sd)
1317 {
1318   register int i;
1319 
1320   UINT len;
1321 
1322   int cb = 0;
1323 
1324   unsigned char *oubuf=NULL;
1325 
1326   char addr[16];
1327 
1328   IFSELECT( UINT fd; );
1329   IFSELECT( struct timeval tv; )
1330   IFSELECT( fd_set fdset; )
1331 
1332   UINT resolvedHostNumber=1;
1333 
1334   struct _S5HostList resolvedHostList[MAXDNS_RESOLV];
1335 
1336   struct in_addr in;
1337 
1338   struct sockaddr_in applicationSsin,
1339                      clientBindSsin;
1340 
1341   char logString[128];
1342 
1343   UINT err=S5REQUEST_SUCCEDED;
1344 
1345   pid_t pid;
1346 
1347   IFEPOLL( struct epoll_event ev; )
1348   IFEPOLL( struct epoll_event events[5]; )
1349   IFEPOLL( int nfds; )
1350   IFEPOLL( int kdpfd; )
1351 
1352   /*
1353   * Get child/thread pid
1354   */
1355   if( NOTTHREADED() )
1356     pid=getpid();
1357   else
1358     pid=(UINT)(uintmax_t)pthread_self();
1359 
1360   /*
1361    * SS5: Resolve hostname before binding
1362    */
1363   if( ri->ATyp == DOMAIN ) {
1364     if( S5ResolvHostName(ri, (struct _S5HostList *)resolvedHostList, &resolvedHostNumber) == ERR ) {
1365       err = S5REQUEST_ISERROR;
1366     }
1367   }
1368 
1369   if( err == S5REQUEST_SUCCEDED ) {
1370     /*
1371      * Create application socket
1372      */
1373     if ((ci->appSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1374       ERRNO(pid)
1375       err = S5REQUEST_ISERROR;
1376     }
1377     else {
1378       /*
1379        * Create client socket for bind
1380        */
1381       if ((cb = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1382         ERRNO(pid)
1383         err = S5REQUEST_ISERROR;
1384       }
1385       else {
1386         memset((char *)&clientBindSsin, 0, sizeof(struct sockaddr_in));
1387         clientBindSsin.sin_family      = AF_INET;
1388         clientBindSsin.sin_port        = htons(0);
1389 
1390         /*
1391          * Look for the right interface for binding
1392          */
1393         if( S5GetBindIf(ri->DstAddr,addr) == ERR ) {
1394           /* Match with destination address in socks request */
1395           clientBindSsin.sin_addr.s_addr = htonl(INADDR_ANY);
1396         }
1397         else
1398           clientBindSsin.sin_addr.s_addr = inet_addr(addr);
1399 
1400         /*
1401          * SS5: set bind interface if configured
1402          */
1403         if( ROUTE() ) {
1404           if( (in.s_addr=(ULINT)GetRoute(inet_network(ci->SrcAddr), inet_network(ri->DstAddr), ci->Username)) )
1405             clientBindSsin.sin_addr.s_addr = in.s_addr;
1406         }
1407         if (bind(cb, (struct sockaddr *)&clientBindSsin, sizeof(struct sockaddr_in)) == -1) {
1408           ERRNO(pid)
1409           err = S5REQUEST_ISERROR;
1410         }
1411         else {
1412           /*
1413            * Get clientbind info
1414            */
1415           len=sizeof(struct sockaddr);
1416           getsockname(cb,(struct sockaddr *)&clientBindSsin,&len);
1417            in.s_addr= clientBindSsin.sin_addr.s_addr;
1418           /*
1419            * SS5: listen for a queue length equal to one
1420            */
1421           if (listen(cb, 1) == -1) {
1422             ERRNO(pid)
1423             err = S5REQUEST_ISERROR;
1424           }
1425         }
1426       }
1427     }
1428   }
1429 
1430   /*
1431    * Send socks response
1432    */
1433   len=10;
1434   memcpy(sd->Response,sd->TcpRequest,32);
1435 
1436   sd->Response[0]=SOCKS5_VERSION;
1437   sd->Response[1]=err;
1438   sd->Response[2]=0;
1439 
1440   SETADDR(sd->Response,clientBindSsin.sin_addr.s_addr,4)
1441   //SETPORT_R(sd->Response,clientBindSsin.sin_port,8)
1442   SETPORT(sd->Response,clientBindSsin.sin_port,8)
1443 
1444   switch( ri->ATyp ) {
1445     /* Socks V5 Header is 10 bytes */
1446     case IPV4:
1447     case DOMAIN:
1448       sd->Response[3]=IPV4;
1449     break;
1450     /*
1451      *    Socks V5 Header is 22 bytes but IPV6 is not supported
1452      */
1453     case IPV6:
1454       return (-1 * S5REQUEST_ADDNOTSUPPORT);
1455     break;
1456   }
1457 
1458 #ifdef SS5_USE_GSSAPI
1459  /*
1460   * If GSS method, encode response before sending to client
1461   */
1462   if( GSSAPI() && GSSINTEGRITY() ) {
1463     if( S5GSSApiEncode(ci->GssContext, ci->GssEnc, sd->Response, &oubuf, &len) ) {
1464 
1465       memcpy(sd->Response,oubuf,len);
1466       if( oubuf ) {
1467         free(oubuf);
1468         oubuf = NULL;
1469       }
1470     }
1471     else
1472       return( -1 * S5REQUEST_GSSERROR);
1473   }
1474 #endif
1475 
1476   /*
1477    * Send socks response
1478    */
1479   if( send(ci->Socket,sd->Response,len,SS5_SEND_OPT) == -1) {
1480     ERRNO(pid)
1481     return(-1 * S5REQUEST_ISERROR);
1482   }
1483 
1484   if( err == S5REQUEST_SUCCEDED ) {
1485     /*
1486      * Wait for BIND_TIMEOUT before closing listen port
1487      */
1488     bzero((char *)&applicationSsin, sizeof(struct sockaddr_in));
1489     len = sizeof (struct sockaddr_in);
1490 
1491     IFSELECT( FD_ZERO(&fdset); )
1492     IFSELECT( FD_SET(cb,&fdset); )
1493 
1494     IFSELECT( tv.tv_sec=BIND_TIMEOUT; )
1495     IFSELECT( tv.tv_usec=0; )
1496 
1497     IFEPOLL( kdpfd=epoll_create(5); )
1498     IFEPOLL( ev.events = EPOLLIN; )
1499     IFEPOLL( ev.data.fd = cb; )
1500     IFEPOLL( epoll_ctl(kdpfd, EPOLL_CTL_ADD, cb, &ev); )
1501 
1502     IFSELECT( if( (fd=select(cb+1,&fdset,NULL,NULL,&tv)) ) { )
1503     IFEPOLL(  if( (nfds = epoll_wait(kdpfd, events, 5, BIND_TIMEOUT*1000)) ) { )
1504     IFSELECT( if( FD_ISSET(cb,&fdset) ) { )
1505     IFEPOLL(  if( events[0].data.fd == cb ) { )
1506         if ((ci->appSocket = accept(cb, (struct sockaddr *)&applicationSsin, &len)) == -1) {
1507           ERRNO(pid)
1508 
1509           IFEPOLL( close(kdpfd); )
1510           close(cb);
1511           return (-1 * S5REQUEST_TTLEXPIRED);
1512         }
1513       }
1514     }
1515     else {
1516       /*
1517        * Timeout expired accepting connection from remote application
1518        */
1519       IFEPOLL( close(kdpfd); )
1520       close(cb);
1521       return (-1 * S5REQUEST_TTLEXPIRED);
1522     }
1523 
1524     IFEPOLL( close(kdpfd); )
1525 
1526     /*
1527      * Socks response packet
1528      */
1529     sd->Response[1]=S5REQUEST_SUCCEDED;
1530 
1531     switch( ri->ATyp ) {
1532       /*
1533        *    Socks V5 Header is 10 bytes
1534        */
1535       case IPV4:
1536       case DOMAIN:
1537         if( send(ci->Socket,sd->Response,10,SS5_SEND_OPT) == -1) {
1538           ERRNO(pid)
1539           return(-1 * S5REQUEST_ISERROR);
1540         }
1541       break;
1542 
1543       /*
1544        *    Socks V5 Header is 22 bytes but IPV6 is not supported
1545        */
1546       case IPV6:    return (-1 * S5REQUEST_ADDNOTSUPPORT);    break;
1547     }
1548   }
1549 
1550   if( err != S5REQUEST_SUCCEDED )
1551      return (-1 * err);
1552   else
1553     return OK;
1554 
1555 }
1556 
1557 
1558 UINT UdpAssociateServing(struct _SS5ClientInfo *ci, struct _SS5RequestInfo *ri, struct _SS5Socks5Data *sd, struct _SS5ProxyData *pd)
1559 {
1560   register UINT i,j;
1561 
1562   UINT len;
1563 
1564   IFSELECT( UINT fd; )
1565 
1566   unsigned short ipA,
1567                  ipB,
1568                  ipC,
1569                  ipD;
1570 
1571   unsigned char *oubuf=NULL;
1572 
1573   char addr[16];
1574 
1575   unsigned char gssHeader[4];
1576 
1577   char logString[256];
1578 
1579   pid_t pid;
1580 
1581   IFSELECT( fd_set fdset; )
1582   IFSELECT( struct timeval tv; )
1583 
1584   UINT resolvedHostNumber=1;
1585 
1586   struct _S5HostList resolvedHostList[MAXDNS_RESOLV];
1587 
1588   struct in_addr in;
1589 
1590   struct sockaddr_in serverbind_ssin,
1591                      clientBindSsin;
1592 
1593   IFEPOLL( struct epoll_event ev; )
1594   IFEPOLL( struct epoll_event events[5]; )
1595   IFEPOLL( int nfds; )
1596   IFEPOLL( int kdpfd; )
1597 
1598   /*
1599    *    Get child/thread pid
1600    */
1601   if( NOTTHREADED() )
1602     pid=getpid();
1603   else
1604     pid=(UINT)(uintmax_t)pthread_self();
1605 
1606 
1607   UINT err=S5REQUEST_SUCCEDED;
1608 
1609   //if( ci->Stream == BEGIN_STREAM ) {
1610     /*
1611      * SS5: Resolve hostname before binding
1612      */
1613     if( ri->ATyp == DOMAIN ) {
1614       if( S5ResolvHostName(ri, (struct _S5HostList *)resolvedHostList, &resolvedHostNumber) == ERR ) {
1615         if( VERBOSE() ) {
1616            snprintf(logString,256 - 1,"[%u] [VERB] Failed resolving FQDN request.",pid);
1617            LOGUPDATE()
1618         }
1619 
1620         err=S5REQUEST_ISERROR;
1621       }
1622     }
1623 
1624     if( err == S5REQUEST_SUCCEDED ) {
1625       /*
1626        * Create server socket vs client
1627        */
1628       if ((ci->udpSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
1629         ERRNO(pid)
1630         err=S5REQUEST_ISERROR;
1631       }
1632       else {
1633         memset((char *)&serverbind_ssin, 0, sizeof(struct sockaddr_in));
1634         serverbind_ssin.sin_family      = AF_INET;
1635         serverbind_ssin.sin_port        = htons(0);
1636 
1637         /*
1638          * Look for the right interface to bind before
1639          * receiving socks request from client (UDP)
1640          */
1641         if( S5GetBindIf(ri->DstAddr,addr) ) {
1642           /* Match with destination address in socks request */
1643           serverbind_ssin.sin_addr.s_addr = inet_addr(addr);
1644         }
1645         else if( S5GetBindIf(ci->SrcAddr,addr) ) {
1646           /* Match with client source address*/
1647           serverbind_ssin.sin_addr.s_addr = inet_addr(addr);
1648         }
1649         else {
1650           /* Bind ANY (if option set) */
1651           len = sizeof (struct sockaddr_in);
1652           getsockname(ci->Socket,(struct sockaddr *)&serverbind_ssin,&len);
1653         }
1654 
1655         /*
1656          * SS5: bind socket to manage request vs client
1657          */
1658         if( bind(ci->udpSocket,(struct sockaddr *)&serverbind_ssin,sizeof(struct sockaddr_in)) ) {
1659           ERRNO(pid)
1660           err=S5REQUEST_ISERROR;
1661         }
1662         else {
1663           /*
1664            * Get information about ip and port after bind operation
1665            * to send to client
1666            */
1667           len = sizeof (struct sockaddr_in);
1668           getsockname(ci->udpSocket,(struct sockaddr *)&serverbind_ssin,&len);
1669 
1670           in.s_addr=serverbind_ssin.sin_addr.s_addr;
1671           strncpy(addr,(char *)inet_ntoa(in),sizeof(addr));
1672           if( DEBUG() ) {
1673             snprintf(logString,256 - 1,"[%u] [DEBU] [UDP RELAY] Bound on %s:%d for udp proxy.",pid,addr,ntohs(serverbind_ssin.sin_port));
1674             LOGUPDATE()
1675           }
1676         }
1677       }
1678     }
1679 
1680     /*
1681      * SS5: create response to send to client
1682      */
1683     len=10;
1684     memset(sd->Response,0,sizeof(sd->Response));
1685 
1686     sd->Response[0]=SOCKS5_VERSION;
1687     sd->Response[1]=err;
1688     sd->Response[2]=0;
1689 
1690     SETADDR(sd->Response,serverbind_ssin.sin_addr.s_addr,4)
1691     SETPORT(sd->Response,serverbind_ssin.sin_port,8)
1692 
1693     switch( ri->ATyp ) {
1694       /* Socks V5 Header 10 Bytes */
1695       case IPV4:
1696         sd->Response[3]=IPV4;
1697       break;
1698       /* Socks V5 Header 10 Bytes */
1699       case DOMAIN:
1700         sd->Response[3]=DOMAIN;
1701       break;
1702       /*
1703        *    Socks V5 Header is 22 Bytesi but is not supported
1704        */
1705       case IPV6:
1706         return (-1 * S5REQUEST_ADDNOTSUPPORT);
1707       break;
1708     }
1709 
1710 #ifdef SS5_USE_GSSAPI
1711    /*
1712     * If GSS method, encode response before sending to client
1713     */
1714     if( GSSAPI() && GSSINTEGRITY() ) {
1715       if( S5GSSApiEncode(ci->GssContext, ci->GssEnc, sd->Response, &oubuf, &len) ) {
1716         memcpy(sd->Response,oubuf,len);
1717         if( oubuf ) {
1718           free(oubuf);
1719           oubuf = NULL;
1720         }
1721       }
1722       else
1723         return( -1 * S5REQUEST_GSSERROR ); ;
1724     }
1725 #endif
1726 
1727    /*
1728     *    Socks V5 Header is 10 bytes
1729     */
1730     if( send(ci->Socket,sd->Response,len,SS5_SEND_OPT) == -1) {
1731       ERRNO(pid)
1732       return( -1 * S5REQUEST_ISERROR);
1733     }
1734 
1735   //} /* End UDP stream */
1736 
1737   return OK;
1738 }
1739 
1740 
1741 UINT UdpAssociateResponse(struct _SS5ClientInfo *ci,struct _SS5RequestInfo *ri,  struct _SS5Socks5Data *sd, struct _SS5ProxyData *pd)
1742 {
1743   register int i;
1744 
1745   UINT len, datalen;
1746 
1747   pid_t pid;
1748 
1749   char logString[128];
1750 
1751   unsigned char *oubuf=NULL;
1752 
1753   struct sockaddr_in clientBindSsin;
1754 
1755   /*
1756    *    Get child/thread pid
1757    */
1758   if( NOTTHREADED() )
1759     pid=getpid();
1760   else
1761     pid=(UINT)(uintmax_t)pthread_self();
1762 
1763   memset((char *)&clientBindSsin, 0, sizeof(struct sockaddr_in));
1764   clientBindSsin.sin_family      = AF_INET;
1765   clientBindSsin.sin_port        = htons(ci->udpSrcPort);
1766   clientBindSsin.sin_addr.s_addr = inet_addr(ci->udpSrcAddr);
1767 
1768   memset(sd->UdpRequest,0,sizeof(sd->UdpRequest));
1769 
1770   datalen=pd->UdpRBufLen+10;
1771 
1772   switch( ri->udpATyp ) {
1773     case IPV4:
1774     case DOMAIN:
1775       sd->UdpRequest[0]=0;
1776       sd->UdpRequest[1]=0;
1777       sd->UdpRequest[2]=ri->udpFrag;
1778       sd->UdpRequest[3]=ri->udpATyp;
1779 
1780       SETADDR(sd->UdpRequest,inet_addr(ri->udpDstAddr),4)
1781       SETPORT_R(sd->UdpRequest,ri->udpDstPort,8)
1782 
1783     break;
1784     /*
1785      *    Socks V5 Header is 22 bytes but IPV6 is not supported
1786      */
1787     case IPV6:    return (-1 * S5REQUEST_ADDNOTSUPPORT);    break;
1788   }
1789 
1790   /*
1791    * Send response to client
1792    */
1793   for(i=0;i<(pd->UdpRBufLen);i++)
1794     sd->UdpRequest[i+10]=pd->UdpRecv[i];
1795 
1796 #ifdef SS5_USE_GSSAPI
1797  /*
1798   * If GSS method, encode response before sending to client
1799   */
1800   if( GSSAPI() && GSSINTEGRITY() ) {
1801     if( S5GSSApiEncode(ci->GssContext, ci->GssEnc, sd->UdpRequest, &oubuf, &datalen) ) {
1802       memcpy(sd->Response,oubuf,datalen);
1803       if( oubuf ) {
1804           free(oubuf);
1805           oubuf = NULL;
1806       }
1807     }
1808     else
1809       return ERR;
1810   }
1811 #endif
1812 
1813   /*
1814    * Relay application response to client
1815    */
1816   len=sizeof(struct sockaddr_in);
1817 
1818   if( (sd->UdpRBytesSent=sendto(ci->udpSocket,sd->UdpRequest,datalen,0,(struct sockaddr *)&clientBindSsin,(socklen_t)len)) == -1 ) {
1819     ERRNO(pid)
1820     return (-1 * S5REQUEST_ISERROR);
1821   }
1822   if( VERBOSE() ) {
1823     snprintf(logString,256 - 1,"[%u] [VERB] Sending UDP SOCKS response to client.",pid);
1824     LOGUPDATE()
1825   }
1826   if( DEBUG() ) {
1827     snprintf(logString,256 - 1,"[%u] [DEBU] [UDP RELAY] UDP SOCKS response sent to %s on port %d.",pid,ci->udpSrcAddr,ci->udpSrcPort);
1828     LOGUPDATE()
1829   }
1830 
1831 
1832   return OK;
1833 }
1834 
1835 
1836 UINT S5GetBindIf( char *applicationIp, char *clientBind )
1837 {
1838   int index;
1839 
1840   bzero(clientBind,16);
1841 
1842   if( (index=S5IfMatch(applicationIp)) != -1 ) {
1843     strncpy(clientBind,S5Interface[index]->IP,sizeof(S5Interface[index]->IP) - 1);
1844     return OK;
1845   }
1846   return ERR;
1847 }
1848 
1849 
1850 UINT S5UdpResolvHostName( struct _SS5RequestInfo *ri, struct _S5HostList *resolvedHostList, UINT *resolvedHostNumber)
1851 {
1852   register UINT index,count;
1853 
1854   struct addrinfo *result;
1855   struct addrinfo *res;
1856   int error;
1857 
1858   char hostname[32], logString[128];
1859 
1860   pid_t pid;
1861   /*
1862   * Get child/thread pid
1863   */
1864   if( NOTTHREADED() )
1865     pid=getpid();
1866   else
1867     pid=(UINT)(uintmax_t)pthread_self();
1868 
1869    /* resolve the domain name into a list of addresses */
1870   if( (error = getaddrinfo(ri->udpDstAddr, NULL, NULL, &result)) != 0 ) {
1871 
1872     return ERR;
1873   }
1874   /*
1875    * In case of multiple answers, save all
1876    */
1877   *resolvedHostNumber=0;
1878   for (index=0,res = result; res != NULL && index < MAXDNS_RESOLV; res = res->ai_next,index++) {
1879     if( (error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, 32, NULL, 0, NI_NUMERICHOST)) == 0 ) {
1880       if (*hostname && res->ai_family == PF_INET) {
1881 
1882           strncpy(resolvedHostList[*resolvedHostNumber].NextHost,hostname,sizeof(resolvedHostList[*resolvedHostNumber].NextHost));
1883           *resolvedHostNumber=*resolvedHostNumber + 1;
1884       }
1885     }
1886   }
1887   if( result )
1888     freeaddrinfo(result);
1889 
1890   /*
1891    * If request, order dns answers
1892    */
1893   if( SS5SocksOpt.DnsOrder ) {
1894     S5OrderIP(resolvedHostList, resolvedHostNumber);
1895 
1896     if( VERBOSE() ) {
1897       snprintf(logString,128,"[%u] [VERB] Ordering multiple records dns.",pid);
1898       LOGUPDATE()
1899 
1900       for(count=0;count<*resolvedHostNumber; count++) {
1901         snprintf(logString,128,"[%u] [DEBU] [DNS RESOLV] Resolved %s to %s.",pid,ri->udpDstAddr,resolvedHostList[count].NextHost);
1902         LOGUPDATE()
1903       }
1904     }
1905   }
1906 
1907   strncpy(ri->udpDstAddr,resolvedHostList[0].NextHost,sizeof(ri->udpDstAddr));
1908 
1909   return OK;
1910 }
1911 
1912 UINT S5ResolvHostName( struct _SS5RequestInfo *ri, struct _S5HostList *resolvedHostList, UINT *resolvedHostNumber)
1913 {
1914   register UINT index,count;
1915 
1916   struct addrinfo *result;
1917   struct addrinfo *res;
1918   int error;
1919 
1920   char hostname[32], logString[128];
1921 
1922   pid_t pid;
1923   /*
1924   * Get child/thread pid
1925   */
1926   if( NOTTHREADED() )
1927     pid=getpid();
1928   else
1929     pid=(UINT)(uintmax_t)pthread_self();
1930 
1931    /* resolve the domain name into a list of addresses */
1932   if( (error = getaddrinfo(ri->DstAddr, NULL, NULL, &result)) != 0 ) {
1933 
1934     return ERR;
1935   }
1936   /*
1937    * In case of multiple answers, save all
1938    */
1939   *resolvedHostNumber=0;
1940   for (index=0,res = result; res != NULL && index < MAXDNS_RESOLV; res = res->ai_next,index++) {
1941     if( (error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, 32, NULL, 0, NI_NUMERICHOST)) == 0 ) {
1942       if (*hostname && res->ai_family == PF_INET && res->ai_socktype == SOCK_STREAM) {
1943 
1944           strncpy(resolvedHostList[*resolvedHostNumber].NextHost,hostname,sizeof(resolvedHostList[*resolvedHostNumber].NextHost));
1945           *resolvedHostNumber=*resolvedHostNumber + 1;
1946       }
1947     }
1948   }
1949   if( result )
1950     freeaddrinfo(result);
1951   /*
1952    * If request, order dns answers
1953    */
1954   if( SS5SocksOpt.DnsOrder ) {
1955     S5OrderIP(resolvedHostList, resolvedHostNumber);
1956 
1957     if( VERBOSE() ) {
1958       snprintf(logString,128,"[%u] [VERB] Ordering multiple records dns.",pid);
1959       LOGUPDATE()
1960 
1961       for(count=0;count<*resolvedHostNumber; count++) {
1962         snprintf(logString,128,"[%u] [DEBU] [DNS RESOLV] Resolved %s to %s.",pid,ri->DstAddr,resolvedHostList[count].NextHost);
1963         LOGUPDATE()
1964       }
1965     }
1966   }
1967 
1968   strncpy(ri->DstAddr,resolvedHostList[0].NextHost,sizeof(ri->DstAddr));
1969 
1970   return OK;
1971 }
1972 
1973 UINT S5OrderIP( struct _S5HostList *resolvedHostList, UINT *resolvedHostNumber )
1974 {
1975   register UINT index;
1976 
1977   UINT swap;
1978 
1979   char ip_tmp[16];
1980 
1981   do {
1982     swap=0;
1983     for(index=0;index<(*resolvedHostNumber)-1;index++)
1984       if( S5CompIP(resolvedHostList[index].NextHost,resolvedHostList[index+1].NextHost) ) {
1985         strncpy(ip_tmp,resolvedHostList[index+1].NextHost,sizeof(resolvedHostList[index+1].NextHost) - 1);
1986         strncpy(resolvedHostList[index+1].NextHost,resolvedHostList[index].NextHost,sizeof(resolvedHostList[index].NextHost) - 1);
1987 	strncpy(resolvedHostList[index].NextHost,ip_tmp,sizeof(ip_tmp) - 1);
1988 	swap=1;
1989       }
1990   } while(swap);
1991 
1992   return OK;
1993 }
1994 
1995 UINT S5CompIP(char src[16],char dst[16] )
1996 {
1997   if( (ULINT)inet_network(src) > (ULINT)inet_network(dst) )
1998     return OK;
1999   else
2000     return ERR;
2001 }
2002 
2003 UINT S5VerifyBind(struct _SS5ClientInfo *ci, struct _SS5RequestInfo *ri )
2004 {
2005 
2006   if( STREQ(ci->udpSrcAddr,ri->DstAddr,sizeof(ci->udpSrcAddr) - 1) && (ci->udpSrcPort == ri->DstPort) )
2007     return OK;
2008   else if ( STREQ(ri->DstAddr,"0.0.0.0",sizeof("0.0.0.0") - 1) && (ci->udpSrcPort == ri->DstPort) )
2009     return OK;
2010   else
2011     return ERR;
2012 }
2013 
2014 inline UINT S5IfMatch(char ip[16])
2015 {
2016   UINT count;
2017 
2018 
2019   for(count=0;count<NInterF;count++) {
2020     if( (ULINT)(inet_network(S5Interface[count]->IP) & inet_network(S5Interface[count]->NetMask)) ==
2021         (ULINT)(inet_network(ip) & inet_network(S5Interface[count]->NetMask)) )
2022       return count;
2023   }
2024 
2025   return -1;
2026 }
2027 
2028 
2029 UINT FileCheck( char *group, char *user )
2030 {
2031   FILE *groupFile;
2032 
2033   UINT i,l;
2034 
2035   pid_t pid;
2036 
2037   char groupFileName[192];
2038   char userName[64];
2039 
2040   char logString[128];
2041 
2042    /*
2043    *    Get child/thread pid
2044    */
2045   if( NOTTHREADED() )
2046     pid=getpid();
2047   else
2048     pid=(UINT)(uintmax_t)pthread_self();
2049 
2050   if( SS5SocksOpt.Profiling == FILE_PROFILING ) {
2051     strncpy(groupFileName,S5ProfilePath,sizeof(groupFileName));
2052     STRSCAT(groupFileName,"/");
2053     STRSCAT(groupFileName,group);
2054 
2055     if( (groupFile = fopen(groupFileName,"r")) == NULL ) {
2056       ERRNO(pid)
2057       return ERR;
2058     }
2059 
2060     /*
2061      *    Check for username into configuration file for access profile
2062      */
2063     while( fscanf(groupFile,"%64s",userName) != EOF ) {
2064       if( userName[0] != '#' )
2065         if( STRCASEEQ(userName,user,64) ) {
2066           fclose(groupFile);
2067           return OK;
2068         }
2069     }
2070     fclose(groupFile);
2071     return ERR;
2072   }
2073   return ERR;
2074 }
2075 
2076 
2077 /* ***************************** HASH for ROUTING TABLE **************************** */
2078 inline UINT S5RouteHash( ULINT sa )
2079 {
2080   return ( sa % MAXROUTELIST );
2081 }
2082 
2083 ULINT GetRoute(ULINT sa, ULINT da, char *uname)
2084 {
2085   UINT index,nm;
2086   UINT err = ERR;
2087   struct _S5RouteNode *node;
2088   ULINT n_sa;
2089 
2090 
2091   /*
2092    * Look for src route
2093    */
2094   for(nm=0;nm<=32;nm +=1) {
2095     if( nm < 32)
2096       n_sa=((sa >> nm) << nm);
2097     else
2098       n_sa=0;
2099     index=S5RouteHash( n_sa );
2100 
2101     if( S5RouteList[index] != NULL ) {
2102       node=S5RouteList[index];
2103 
2104       do {
2105         if( (node->SrcAddr == n_sa) && (node->Mask == (nm)) && (node->sd == SRC_ROUTE) ) {
2106 
2107           if( node->Group[0] != '-' ) {
2108             /*
2109              * Look for username into group (file or directory) defined in permit line
2110              */
2111             if( SS5SocksOpt.Profiling == FILE_PROFILING )
2112               err=FileCheck(node->Group,uname);
2113             else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
2114               err=DirectoryCheck(node->Group,uname);
2115             else if( SS5SocksOpt.Profiling == MYSQL_PROFILING )
2116               err=MySqlCheck(node->Group,uname);
2117             if( err ) {
2118               return node->SrcIf;
2119             }
2120           }
2121           else
2122             return node->SrcIf;
2123         }
2124         node=node->next;
2125       } while(node != NULL );
2126     }
2127   }
2128 
2129   /*
2130    * Look for dst route
2131    */
2132   for(nm=0;nm<=32;nm +=1) {
2133     if( nm < 32)
2134       n_sa=((da >> nm) << nm);
2135     else
2136       n_sa=0;
2137     index=S5RouteHash( n_sa );
2138 
2139     if( S5RouteList[index] != NULL ) {
2140       node=S5RouteList[index];
2141 
2142       do {
2143         if( (node->SrcAddr == n_sa) && (node->Mask == (nm)) && (node->sd == DST_ROUTE) ) {
2144 
2145           if( node->Group[0] != '-' ) {
2146             /*
2147              * Look for username into group (file or directory) defined in permit line
2148              */
2149             if( SS5SocksOpt.Profiling == FILE_PROFILING )
2150               err=FileCheck(node->Group,uname);
2151             else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
2152               err=DirectoryCheck(node->Group,uname);
2153             if( err ) {
2154               return node->SrcIf;
2155             }
2156           }
2157           else
2158             return node->SrcIf;
2159         }
2160         node=node->next;
2161       } while(node != NULL );
2162     }
2163   }
2164 
2165   return ERR;
2166 }
2167 
2168 
2169 UINT DelRoute(ULINT sa, ULINT si, char *group, UINT mask, UINT sd )
2170 {
2171   int index;
2172   struct _S5RouteNode *node, *prevnode=NULL;
2173 
2174   index=S5RouteHash( sa );
2175 
2176   node=S5RouteList[index];
2177 
2178   if( node == NULL )
2179     return ERR;
2180 
2181   if( (node->SrcAddr == sa) && (node->Mask == mask) ) {
2182     if( node->next == NULL ) {
2183 
2184       free(node);
2185       S5RouteList[index]=NULL;
2186       return OK;
2187     }
2188     else {
2189       S5RouteList[index]=node->next;
2190       free(node);
2191       return OK;
2192     }
2193   }
2194 
2195   while( node->next != NULL ) {
2196     prevnode=node;
2197     node=node->next;
2198 
2199     if( (node->SrcAddr == sa) && (node->Mask == mask) ) {
2200       if( node->next != NULL )
2201         prevnode->next=node->next;
2202       else
2203         prevnode->next=NULL;
2204 
2205       free(node);
2206       node=NULL;
2207       return OK;
2208     }
2209   }
2210   return ERR;
2211 }
2212 
2213 UINT AddRoute(UINT ctx, ULINT sa, ULINT si, char *group, UINT mask, UINT sd )
2214 {
2215   int index;
2216   struct _S5RouteNode *node, *prevnode;
2217 
2218   index=S5RouteHash( sa );
2219 
2220   if( ctx == OFFLINE )
2221     node=_tmp_S5RouteList[index];
2222   else
2223     node=S5RouteList[index];
2224 
2225   if( node== NULL ) {
2226     if( (node=(struct _S5RouteNode *)calloc(1,sizeof(struct _S5RouteNode))) == NULL )
2227       return ERR;
2228     node->Mask=mask;
2229     node->SrcAddr=sa;
2230     node->SrcIf=si;
2231     node->sd=sd;
2232     strncpy(node->Group,group,sizeof(node->Group));
2233     node->next=NULL;
2234 
2235     if( ctx == OFFLINE )
2236       _tmp_S5RouteList[index]=node;
2237     else
2238       S5RouteList[index]=node;
2239   }
2240   else {
2241     if( ctx == OFFLINE )
2242       node=_tmp_S5RouteList[index];
2243     else
2244       node=S5RouteList[index];
2245 
2246     do {
2247       if( (node->SrcAddr == sa) && (node->Mask == mask) && (node->SrcIf == si) && (node->sd == sd) ) {
2248         return ERR;
2249       }
2250       prevnode=node;
2251       node=node->next;
2252 
2253     } while(node != NULL );
2254 
2255     if( (node=(struct _S5RouteNode *)calloc(1,sizeof(struct _S5RouteNode))) == NULL )
2256       return ERR;
2257 
2258     node->Mask=mask;
2259     node->SrcAddr=sa;
2260     node->SrcIf=si;
2261     node->sd=sd;
2262     strncpy(node->Group,group,sizeof(node->Group));
2263     node->next=NULL;
2264 
2265     prevnode->next=node;
2266   }
2267   return OK;
2268 }
2269 
2270 UINT FreeRoute( struct _S5RouteNode **node )
2271 {
2272   struct _S5RouteNode *lnode;
2273   struct _S5RouteNode *lnode_prev=NULL;
2274 
2275   lnode=*node;
2276 
2277   if( lnode != NULL ) {
2278     do {
2279       while( lnode->next != NULL ) {
2280         lnode_prev=lnode;
2281         lnode=lnode->next;
2282       }
2283       free(lnode);
2284       if( lnode_prev != NULL ) {
2285         lnode_prev->next=NULL;
2286         lnode=lnode_prev;
2287         lnode_prev=NULL;
2288       }
2289       else
2290         lnode=NULL;
2291     } while( (lnode) != NULL );
2292   }
2293   *node=NULL;
2294 
2295   return OK;
2296 }
2297 
2298 /* ***************************** HASH for UPSTREAM PROXY **************************** */
2299 inline UINT S5ProxyHash( ULINT da, UINT dp )
2300 {
2301   register UINT i;
2302   register long int hashVal = 0;
2303   register UINT len;
2304   char s[24];
2305 
2306   snprintf(s,sizeof(s),"%lu%u",da,dp);
2307 
2308   len=strlen(s);
2309   for(i=0; i<len;i++)
2310     hashVal= 37*hashVal + s[i];
2311 
2312   hashVal %= 997;
2313   if(hashVal < 0)
2314     hashVal +=997;
2315 
2316   return hashVal;
2317 
2318 }
2319 
2320 UINT GetProxy(ULINT da, UINT dp, struct _SS5RequestInfo *ri)
2321 {
2322   register UINT index,nm;
2323   register ULINT n_da;
2324   struct _S5ProxyNode *node;
2325 
2326   for(nm=0;nm<=32;nm++) {
2327     if( nm < 32)
2328       n_da=((da >> nm) << nm);
2329     else
2330       n_da=0;
2331 
2332     index=S5ProxyHash( n_da, dp );
2333 
2334     if( S5ProxyList[index]!= NULL ) {
2335       node=S5ProxyList[index];
2336       do {
2337         if( (node->DstAddr == n_da) && (node->Mask == nm) && (node->DstPort == dp) ) {
2338           ri->upDstAddr=node->ProxyAddr;
2339           ri->upDstPort=node->ProxyPort;
2340           ri->upSocksVer=node->SocksVer;
2341           if( node->Type == PROXY ) {
2342             return OK;
2343           }
2344           return ERR_NOPROXY;
2345         }
2346         node=node->next;
2347       } while(node != NULL );
2348     }
2349   }
2350 
2351   for(nm=0;nm<=32;nm++) {
2352     if( nm < 32)
2353       n_da=((da >> nm) << nm);
2354     else
2355       n_da=0;
2356 
2357     index=S5ProxyHash( n_da, 0 );
2358 
2359     if( S5ProxyList[index]!= NULL ) {
2360       node=S5ProxyList[index];
2361       do {
2362         if( (node->DstAddr == n_da ) && (node->Mask == nm) && (dp >= node->DstRangeMin) && (dp <= node->DstRangeMax) ) {
2363           ri->upDstAddr=node->ProxyAddr;
2364           ri->upDstPort=node->ProxyPort;
2365           ri->upSocksVer=node->SocksVer;
2366           if( node->Type == PROXY ) {
2367             return OK;
2368           }
2369           return ERR_NOPROXY;
2370         }
2371         node=node->next;
2372       } while(node != NULL );
2373     }
2374   }
2375 
2376   return ERR;
2377 }
2378 
2379 UINT DelProxy(UINT type, ULINT da, ULINT dp, ULINT pa, UINT pp, UINT mask, UINT socksver)
2380 {
2381   int index;
2382   struct _S5ProxyNode *node, *prevnode=NULL;
2383 
2384   if( dp > 65535 )
2385     index=S5ProxyHash( da, 0 );
2386   else
2387     index=S5ProxyHash( da, dp );
2388 
2389 
2390   node=S5ProxyList[index];
2391 
2392   if( node == NULL )
2393     return ERR;
2394 
2395   if( (node->Type == type) && (node->DstAddr == da) && (node->Mask == mask) && (dp == node->DstPort) ) {
2396     if( node->next == NULL ) {
2397 
2398       free(S5ProxyList[index]);
2399       S5ProxyList[index]=NULL;
2400 
2401       return OK;
2402     }
2403     else {
2404       S5ProxyList[index]=node->next;
2405       free(S5ProxyList[index]);
2406       return OK;
2407     }
2408   }
2409 
2410   while( node->next != NULL ) {
2411     prevnode=node;
2412     node=node->next;
2413 
2414     if( (node->Type == type) && (node->DstAddr == da) && (node->Mask == mask) && (dp == node->DstPort) ) {
2415       if( node->next != NULL )
2416         prevnode->next=node->next;
2417       else
2418         prevnode->next=NULL;
2419 
2420       free(node);
2421       node=NULL;
2422 
2423       return OK;
2424     }
2425   }
2426 
2427   return ERR;
2428 }
2429 
2430 
2431 UINT AddProxy(UINT ctx,UINT type, ULINT da, ULINT dp, ULINT pa, UINT pp, UINT mask, UINT socksver)
2432 {
2433   int index;
2434   struct _S5ProxyNode *node, *prevnode;
2435 
2436   if( dp > 65535 )
2437     index=S5ProxyHash( da, 0 );
2438   else
2439     index=S5ProxyHash( da, dp );
2440 
2441   if( ctx == OFFLINE )
2442     node=_tmp_S5ProxyList[index];
2443   else
2444     node=S5ProxyList[index];
2445 
2446   if( node== NULL ) {
2447     if( (node=(struct _S5ProxyNode *)calloc(1,sizeof(struct _S5ProxyNode))) == NULL )
2448       return ERR;
2449     node->Mask=mask;
2450     node->DstAddr=da;
2451     node->Type=type;
2452     node->SocksVer=socksver;
2453 
2454     if( dp > 65535 ) {
2455       node->DstPort=dp;
2456       node->DstRangeMax=dp;
2457       node->DstRangeMax >>= 16;
2458       node->DstRangeMax <<= 16;
2459       node->DstRangeMin = dp - node->DstRangeMax;
2460       node->DstRangeMax >>= 16;
2461 
2462     }
2463     else
2464       node->DstPort=dp;
2465 
2466     node->ProxyAddr=pa;
2467     node->ProxyPort=pp;
2468     node->next=NULL;
2469 
2470     if( ctx == OFFLINE )
2471       _tmp_S5ProxyList[index]=node;
2472     else
2473       S5ProxyList[index]=node;
2474   }
2475   else {
2476     if( ctx == OFFLINE )
2477       node=_tmp_S5ProxyList[index];
2478     else
2479       node=S5ProxyList[index];
2480 
2481     do {
2482       if( (node->DstAddr == da) && (node->Mask == mask) && (node->DstPort == dp) ) {
2483         return ERR;
2484       }
2485 
2486       prevnode=node;
2487       node=node->next;
2488 
2489     } while(node != NULL );
2490 
2491     if( (node=(struct _S5ProxyNode *)calloc(1,sizeof(struct _S5ProxyNode))) == NULL )
2492       return ERR;
2493     node->Mask=mask;
2494     node->DstAddr=da;
2495     node->Type=type;
2496     node->SocksVer=socksver;
2497 
2498     if( dp > 65535 ) {
2499       node->DstPort=dp;
2500       node->DstRangeMax=dp;
2501       node->DstRangeMax >>= 16;
2502       node->DstRangeMax <<= 16;
2503       node->DstRangeMin = dp - node->DstRangeMax;
2504       node->DstRangeMax >>= 16;
2505     }
2506     else
2507       node->DstPort=dp;
2508 
2509     node->ProxyAddr=pa;
2510     node->ProxyPort=pp;
2511     node->next=NULL;
2512 
2513     prevnode->next=node;
2514   }
2515   return OK;
2516 }
2517 
2518 
2519 UINT FreeProxy( struct _S5ProxyNode **node )
2520 {
2521   struct _S5ProxyNode *lnode;
2522   struct _S5ProxyNode *lnode_prev=NULL;
2523 
2524   lnode=*node;
2525 
2526   if( lnode != NULL ) {
2527     do {
2528       while( lnode->next != NULL ) {
2529         lnode_prev=lnode;
2530         lnode=lnode->next;
2531       }
2532       free(lnode);
2533       if( lnode_prev != NULL ) {
2534         lnode_prev->next=NULL;
2535         lnode=lnode_prev;
2536         lnode_prev=NULL;
2537       }
2538       else
2539         lnode=NULL;
2540     } while( (lnode) != NULL );
2541   }
2542   *node=NULL;
2543 
2544   return OK;
2545 
2546 }
2547 
2548 /* ***************************** HASH for METHOD **************************** */
2549 inline UINT S5MethodHash( ULINT sa, UINT sp )
2550 {
2551   register UINT i,len;
2552   register int hashVal = 0;
2553   char s[32];
2554 
2555   snprintf(s,sizeof(s),"%lu%u",sa,sp);
2556 
2557   len=strlen(s);
2558   for(i=0; i<len;i++)
2559     hashVal= 37*hashVal + s[i];
2560 
2561   hashVal %= 997;
2562   if(hashVal < 0)
2563     hashVal +=997;
2564 
2565   return hashVal;
2566 
2567 }
2568 
2569 unsigned char GetMethod(struct _SS5ClientInfo *ci )
2570 {
2571   register UINT index,nm;
2572   register ULINT n_sa;
2573   ULINT sa,sp;
2574   struct _S5MethodNode *node;
2575 
2576   sp=ci->SrcPort;
2577   sa=inet_network(ci->SrcAddr);
2578 
2579 
2580   for(nm=0;nm<=32;nm++) {
2581     if( nm < 32)
2582       n_sa=((sa >> nm) << nm);
2583     else
2584       n_sa=0;
2585 
2586     index=S5MethodHash( n_sa, 0 );
2587 
2588     if( S5MethodList[index]!= NULL ) {
2589 
2590       node=S5MethodList[index];
2591       do {
2592         if( (node->SrcAddr == n_sa) && (node->Mask == nm) && (sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax) ) {
2593           if( ((node->Method == NOAUTH) && ci->NoAuth) || (((node->Method == USRPWD) || (node->Method2 == FAKEPWD)) && ci->BasicAuth) || ((node->Method == GSSAPI) && ci->GssApiAuth) )
2594             return node->Method;
2595           if( ((node->Method2 == NOAUTH) && ci->NoAuth) || (((node->Method2 == USRPWD) || (node->Method2 == FAKEPWD)) && ci->BasicAuth) || ((node->Method2 == GSSAPI) && ci->GssApiAuth) )
2596             return node->Method2;
2597         }
2598         node=node->next;
2599       } while(node != NULL );
2600     }
2601   }
2602 
2603   for(nm=0;nm<=32;nm++) {
2604     if( nm < 32)
2605       n_sa=((sa >> nm) << nm);
2606     else
2607       n_sa=0;
2608 
2609     index=S5MethodHash( n_sa, sp );
2610 
2611     if( S5MethodList[index]!= NULL ) {
2612 
2613       node=S5MethodList[index];
2614       do {
2615         if( (node->SrcAddr == n_sa) && (node->Mask == nm) && (node->SrcPort == sp) ) {
2616           if( ((node->Method == NOAUTH) && ci->NoAuth) || (((node->Method == USRPWD) || (node->Method2 == FAKEPWD))  && ci->BasicAuth) || ((node->Method == GSSAPI) && ci->GssApiAuth)    )
2617             return node->Method;
2618           if( ((node->Method2 == NOAUTH) && ci->NoAuth) || (((node->Method2 == USRPWD) || (node->Method2 == FAKEPWD)) && ci->BasicAuth) || ((node->Method2 == GSSAPI) && ci->GssApiAuth)    )
2619             return node->Method2;
2620         }
2621         node=node->next;
2622       } while(node != NULL );
2623     }
2624   }
2625 
2626   return NOMETHOD;
2627 }
2628 
2629 
2630 UINT DelMethod(ULINT sa, ULINT sp, UINT me, UINT me2, UINT mask)
2631 {
2632   int index;
2633   struct _S5MethodNode *node, *prevnode=NULL;
2634 
2635   if( sp > 65535 )
2636     index=S5MethodHash( sa, 0 );
2637   else
2638     index=S5MethodHash( sa, sp );
2639 
2640 
2641   node=S5MethodList[index];
2642 
2643   if( node == NULL )
2644     return ERR;
2645 
2646   if( (node->SrcAddr == sa) && (node->Mask == mask) && (sp == node->SrcPort) ) {
2647     if( node->next == NULL ) {
2648 
2649       free(node);
2650       S5MethodList[index]=NULL;
2651       return OK;
2652     }
2653     else {
2654       S5MethodList[index]=node->next;
2655       free(node);
2656       return OK;
2657     }
2658   }
2659 
2660   while( node->next != NULL ) {
2661     prevnode=node;
2662     node=node->next;
2663 
2664     if( (node->SrcAddr == sa) && (node->Mask == mask) && (sp == node->SrcPort) ) {
2665       if( node->next != NULL )
2666         prevnode->next=node->next;
2667       else
2668         prevnode->next=NULL;
2669 
2670       free(node);
2671       node=NULL;
2672 
2673       return OK;
2674     }
2675   }
2676   return ERR;
2677 }
2678 
2679 UINT AddMethod(UINT ctx, ULINT sa, ULINT sp, UINT me, UINT me2, UINT mask)
2680 {
2681   int index;
2682   struct _S5MethodNode *node, *prevnode;
2683 
2684   if( sp > 65535 )
2685     index=S5MethodHash( sa, 0 );
2686   else
2687     index=S5MethodHash( sa, sp );
2688 
2689   if( ctx == OFFLINE )
2690     node=_tmp_S5MethodList[index];
2691   else
2692     node=S5MethodList[index];
2693 
2694   if( node == NULL ) {
2695     if( (node=(struct _S5MethodNode *)calloc(1,sizeof(struct _S5MethodNode))) == NULL )
2696       return ERR;
2697 
2698     node->Mask=mask;
2699     node->SrcAddr=sa;
2700 
2701     if( sp > 65535 ) {
2702       node->SrcPort=sp;
2703       node->SrcRangeMax=sp;
2704       node->SrcRangeMax >>= 16;
2705       node->SrcRangeMax <<= 16;
2706       node->SrcRangeMin = sp - node->SrcRangeMax;
2707       node->SrcRangeMax >>= 16;
2708     }
2709     else
2710       node->SrcPort=sp;
2711 
2712     node->Method=me;
2713     node->Method2=me2;
2714     node->next=NULL;
2715 
2716     if( ctx == OFFLINE )
2717       _tmp_S5MethodList[index]=node;
2718     else
2719       S5MethodList[index]=node;
2720   }
2721   else {
2722     if( ctx == OFFLINE )
2723       node=_tmp_S5MethodList[index];
2724     else
2725       node=S5MethodList[index];
2726 
2727     do {
2728       if( (node->SrcAddr == sa) && (node->Mask == mask) && (node->SrcPort == sp) ) {
2729         return ERR;
2730       }
2731       prevnode=node;
2732       node=node->next;
2733 
2734     } while(node != NULL );
2735 
2736     if( (node=(struct _S5MethodNode *)calloc(1,sizeof(struct _S5MethodNode))) == NULL )
2737       return ERR;
2738     node->Mask=mask;
2739     node->SrcAddr=sa;
2740 
2741     if( sp > 65535 ) {
2742       node->SrcPort=sp;
2743       node->SrcRangeMax=sp;
2744       node->SrcRangeMax >>= 16;
2745       node->SrcRangeMax <<= 16;
2746       node->SrcRangeMin = sp - node->SrcRangeMax;
2747       node->SrcRangeMax >>= 16;
2748     }
2749     else
2750       node->SrcPort=sp;
2751 
2752     node->Method=me;
2753     node->Method2=me2;
2754     node->next=NULL;
2755 
2756     prevnode->next=node;
2757   }
2758   return OK;
2759 }
2760 
2761 UINT FreeMethod( struct _S5MethodNode **node )
2762 {
2763   struct _S5MethodNode *lnode;
2764   struct _S5MethodNode *lnode_prev=NULL;
2765 
2766   lnode=*node;
2767 
2768   if( lnode != NULL ) {
2769     do {
2770       while( lnode->next != NULL ) {
2771         lnode_prev=lnode;
2772         lnode=lnode->next;
2773       }
2774       free(lnode);
2775       if( lnode_prev != NULL ) {
2776         lnode_prev->next=NULL;
2777         lnode=lnode_prev;
2778         lnode_prev=NULL;
2779       }
2780       else
2781         lnode=NULL;
2782     } while( (lnode) != NULL );
2783   }
2784   *node=NULL;
2785 
2786   return OK;
2787 
2788 }
2789 
2790 
2791 UINT V52V4Request(struct _SS5Socks5Data *sd, struct _SS5RequestInfo *ri, struct _SS5ClientInfo *ci)
2792 {
2793   register UINT i;
2794 
2795   UINT v4bytes=0;
2796 
2797   char V4TcpRequest[256];
2798 
2799   memset((char *)V4TcpRequest, 0, sizeof(V4TcpRequest));
2800 
2801   switch( sd->TcpRequest[3] ) {
2802     case IPV4:
2803       /*
2804        * Destination address is dot notation:
2805        * convert V5 socks request to V4 socks request
2806        */
2807 
2808       V4TcpRequest[0]=4;
2809       V4TcpRequest[1]=ri->Cmd;
2810       V4TcpRequest[2]=sd->TcpRequest[8];
2811       V4TcpRequest[3]=sd->TcpRequest[9];
2812       V4TcpRequest[4]=sd->TcpRequest[4];
2813       V4TcpRequest[5]=sd->TcpRequest[5];
2814       V4TcpRequest[6]=sd->TcpRequest[6];
2815       V4TcpRequest[7]=sd->TcpRequest[7];
2816 
2817       for(i = 0; (V4TcpRequest[i + 8] = ci->Username[i]); i++ );
2818 
2819       V4TcpRequest[i+8] = '\0';
2820 
2821       v4bytes=8+i+1;
2822 
2823     break;
2824 
2825     case IPV6: /* Not supported */
2826       return ERR;
2827     break;
2828 
2829     case DOMAIN:
2830       /*
2831        * Destination address is FQDN (TODO)
2832        */
2833 /*      len=(unsigned char)sd->TcpRequest[4] + 5;
2834       ri->DstPort=0;
2835       ri->DstPort +=(unsigned char)sd->TcpRequest[len];
2836       ri->DstPort <<=8;
2837       ri->DstPort +=(unsigned char)sd->TcpRequest[len+1];
2838 
2839       for(c=0,i=5;i<len;i++,c++ )
2840         ri->DstAddr[c]=(unsigned char)sd->TcpRequest[i];
2841 
2842       ri->DstAddr[c]='\0';
2843       ri->ATyp=DOMAIN;
2844 */
2845       return ERR;
2846     break;
2847   }
2848 
2849   memcpy(sd->TcpRequest,V4TcpRequest, sizeof(V4TcpRequest));
2850 
2851   return v4bytes;
2852 }
2853 
2854 UINT V42V5Response(struct _SS5Socks5Data *sd, struct _SS5RequestInfo *ri, struct _SS5ClientInfo *ci)
2855 {
2856   UINT v4bytes=0;
2857 
2858   char V5TcpResponse[256];
2859 
2860   memset((char *)V5TcpResponse, 0, sizeof(V5TcpResponse));
2861 
2862   switch( ri->ATyp ) {
2863     case IPV4:
2864       /*
2865        * Destination address is dot notation:
2866        * convert V4 socks reply to V5 socks reply
2867        */
2868       V5TcpResponse[0]=ri->Ver;
2869       V5TcpResponse[1]=sd->Response[1] - 90;
2870       V5TcpResponse[2]=0;
2871       V5TcpResponse[3]=ri->ATyp;
2872       V5TcpResponse[4]=sd->Response[4];
2873       V5TcpResponse[5]=sd->Response[5];
2874       V5TcpResponse[6]=sd->Response[6];
2875       V5TcpResponse[7]=sd->Response[7];
2876       V5TcpResponse[8]=sd->Response[2];
2877       V5TcpResponse[9]=sd->Response[3];
2878 
2879       v4bytes=10;
2880 
2881     break;
2882 
2883     case IPV6: /* Not supported */
2884       return ERR;
2885     break;
2886 
2887     case DOMAIN:
2888       /*
2889        * Destination address is FQDN (TODO)
2890        */
2891 /*      len=(unsigned char)sd->TcpRequest[4] + 5;
2892       ri->DstPort=0;
2893       ri->DstPort +=(unsigned char)sd->TcpRequest[len];
2894       ri->DstPort <<=8;
2895       ri->DstPort +=(unsigned char)sd->TcpRequest[len+1];
2896 
2897       for(c=0,i=5;i<len;i++,c++ )
2898         ri->DstAddr[c]=(unsigned char)sd->TcpRequest[i];
2899 
2900       ri->DstAddr[c]='\0';
2901       ri->ATyp=DOMAIN;
2902 */
2903       return ERR;
2904     break;
2905   }
2906 
2907   memcpy(sd->Response,V5TcpResponse, v4bytes);
2908 
2909   return v4bytes;
2910 }
2911 
2912 
2913 
2914 
2915