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