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 #include"SS5Main.h"
20 #include"SS5Mod_authorization.h"
21 #include"SS5OpenLdap.h"
22 #ifdef SS5_USE_MYSQL
23 #include"SS5MySql.h"
24 #include<mysql/mysql.h>
25 #endif
26 #include"SS5Utils.h"
27 
28 #define _XOPEN_SOURCE /* glibc2 needs this */
29 
30 #ifdef SOLARIS
31   #include<lber.h>
32 #endif
33 
34 #include<ldap.h>
35 
36 char *ss5ver=SS5_VERSION;
37 
InitModule(struct _module * m)38 UINT InitModule( struct _module *m )
39 {
40   m->PreAuthorization  = PreAuthorization;
41   m->PostAuthorization = PostAuthorization;
42   m->AddAcl  = AddAcl;
43   m->FreeAcl = FreeAcl;
44   m->GetAcl  = GetAcl;
45   m->FreeAuthoCache = FreeAuthoCache;
46   m->SrvAuthorization  = SrvAuthorization;
47   m->UpdateAuthoCache  = UpdateAuthoCache;
48 
49   return OK;
50 }
51 
PreAuthorization(struct _SS5ClientInfo * ci,struct _SS5RequestInfo * ri,struct _SS5Facilities * fa)52 UINT PreAuthorization( struct _SS5ClientInfo *ci, struct _SS5RequestInfo *ri, struct _SS5Facilities *fa )
53 {
54   UINT i,l,me,me2;
55 
56   INT err;
57 
58   INT err2 = ERR;
59 
60   pid_t pid;
61 
62   char logString[256];
63 
64   /*
65   * Get child/thread pid
66   */
67   if( NOTTHREADED() )
68     pid = getpid();
69   else
70     pid = (UINT)(uintmax_t)pthread_self();
71 
72   strncpy(fa->Group,ci->Username,sizeof(fa->Group));
73   STRSCAT(fa->Group,"\0");
74 
75   if( THREADED() ) {
76     if( SS5SocksOpt.AuthoCacheAge ) {
77 
78       /*
79        *  Look for permit line into authorization cache
80        */
81       LOCKMUTEXAC()
82 
83 // TEST FTP FIXUP
84   if( (err2=GetAuthoCache(ci->SrcAddr,ri->DstAddr,21,ci->Username,fa,0)) == (OK+100) )
85   ;
86   else
87 // END TEST FTP FIXUP
88       err2 = GetAuthoCache(ci->SrcAddr,ri->DstAddr,ri->DstPort,ci->Username,fa,1);
89 
90       UNLOCKMUTEXAC()
91       if( err2 == ERR_AUTHOCACHE_EXPIRED ) {
92         /*
93          * Update the entry into authorization cache
94          */
95         LOCKMUTEXAC()
96         UpdateAuthoCache(ci->SrcAddr,ri->DstAddr,ri->DstPort,ci->Username,0);
97         UNLOCKMUTEXAC()
98 
99         if( VERBOSE() ) {
100           snprintf(logString,128,"[%u] [VERB] Cache authorization  expired for user %s.",pid,ci->Username);
101           SS5Modules.mod_logging.Logging(logString);
102         }
103       }
104     }
105   }
106 
107   if( err2 <= ERR ) {
108     switch( ri->Cmd ) {
109       case CONNECT:
110         if( ri->ATyp == DOMAIN )
111           err = GetAcl(inet_network(ci->SrcAddr),ci->SrcPort,S5StrHash(ri->DstAddr),ri->DstPort,fa,&me,&me2);
112         else
113           err = GetAcl(inet_network(ci->SrcAddr),ci->SrcPort,inet_network(ri->DstAddr),ri->DstPort,fa,&me,&me2);
114         if( err >= ERR ) {
115 
116           if( ( me == ci->Method ) || ( me == NOAUTH ) || ( me == FAKEPWD ) || ( me2 == ci->Method ) || ( me2 == NOAUTH ) || ( me2 == FAKEPWD )) {
117             if( THREADED() ) {
118               if( SS5SocksOpt.AuthoCacheAge ) {
119                 /*
120                  * Add new entry into authorization cache
121                  */
122                 LOCKMUTEXAC()
123                 AddAuthoCache(ci->SrcAddr,ri->DstAddr,ri->DstPort,ci->Username,fa);
124                 UNLOCKMUTEXAC()
125                 if( VERBOSE() ) {
126                   snprintf(logString,128,"[%u] [VERB] Cache  autorization  updated for user %s.",pid,ci->Username);
127                   SS5Modules.mod_logging.Logging(logString);
128                 }
129               }
130             }
131             return OK;
132           }
133         }
134       break;
135       case BIND:
136         if( ri->ATyp == DOMAIN )
137           err = GetAcl(S5StrHash(ri->DstAddr),ri->DstPort,inet_network(ci->SrcAddr),ci->SrcPort,fa,&me,&me2);
138         else
139           err = GetAcl(inet_network(ri->DstAddr),ri->DstPort,inet_network(ci->SrcAddr),ci->SrcPort,fa,&me,&me2);
140 
141         if( err >= ERR ) {
142           if( ( me == ci->Method ) || ( me == NOAUTH ) || ( me == FAKEPWD ) || ( me2 == ci->Method ) || ( me2 == NOAUTH ) || ( me2 == FAKEPWD )) {
143             if( THREADED() ) {
144               if( SS5SocksOpt.AuthoCacheAge ) {
145                 /*
146                  * Add new entry into authorization cache
147                  */
148                 LOCKMUTEXAC()
149                 AddAuthoCache(ci->SrcAddr,ri->DstAddr,ri->DstPort,ci->Username,fa);
150                 UNLOCKMUTEXAC()
151                 if( VERBOSE() ) {
152                   snprintf(logString,128,"[%u] [VERB] Cache  autorization  updated for user %s.",pid,ci->Username);
153                   SS5Modules.mod_logging.Logging(logString);
154                 }
155               }
156             }
157             return OK;
158           }
159         }
160       break;
161     }
162   }
163   else if( THREADED() ) {
164     if( SS5SocksOpt.AuthoCacheAge ) {
165       /*
166        * Entry in cache
167        */
168       if( VERBOSE() ) {
169         snprintf(logString,128,"[%u] [VERB] Cache authorization  verified for user %s.",pid,ci->Username);
170         SS5Modules.mod_logging.Logging(logString);
171       }
172 
173       return OK;
174     }
175   }
176 
177   return ERR;
178 }
179 
PostAuthorization(struct _SS5ClientInfo * ci,struct _SS5RequestInfo * ri,struct _SS5Facilities * fa)180 UINT PostAuthorization(  struct _SS5ClientInfo *ci,
181                              struct _SS5RequestInfo *ri, struct _SS5Facilities *fa )
182 {
183   UINT i,l,me,me2;
184 
185   INT err;
186 
187   strncpy(fa->Group,ci->Username,sizeof(fa->Group));
188   STRSCAT(fa->Group,"\0");
189 
190   switch( ri->Cmd ) {
191     case UDP_ASSOCIATE:
192       if( ri->ATyp == DOMAIN )
193         err = GetAcl(inet_network(ci->udpSrcAddr),ci->udpSrcPort,S5StrHash(ri->udpDstAddr),ri->udpDstPort,fa,&me,&me2);
194       else
195         err = GetAcl(inet_network(ci->udpSrcAddr),ci->udpSrcPort,inet_network(ri->udpDstAddr),ri->udpDstPort,fa,&me,&me2);
196       if( err >= ERR ) {
197         if( ( me == ci->Method ) || ( me == NOAUTH ) || ( me == FAKEPWD )|| ( me2 == ci->Method ) || ( me2 == NOAUTH ) || ( me2 == FAKEPWD ) ) {
198           return OK;
199         }
200     }
201     break;
202   }
203   return ERR;
204 }
205 
ListAutho(UINT s)206 UINT ListAutho( UINT s )
207 {
208   UINT count;
209 
210   struct _S5AclNode *lnode, *node;
211 
212   char buf[553];
213 
214   for(count = 0;count < MAXACLLIST; count++) {
215     if( (node=S5AclList[count]) != NULL) {
216 
217       lnode=node;
218       do {
219         if(lnode != NULL ) {
220           snprintf(buf,sizeof(buf),"%3u\n%16lu\n%64s\n%2u\n%16lu\n%5u\n%5u\n%16lu\n%64s\n%2u\n%16lu\n%5u\n%5u\n%16s\n%256s\n%16lu\n%10s\n%1u\n",
221                    lnode->Method,lnode->SrcAddr,lnode->SrcAddrFqdn,lnode->SrcMask,lnode->SrcPort,lnode->SrcRangeMin,lnode->SrcRangeMax,
222                    lnode->DstAddr,lnode->DstAddrFqdn,lnode->DstMask,lnode->DstPort,lnode->DstRangeMin,lnode->DstRangeMax,
223                    lnode->Fixup,lnode->Group,lnode->Bandwidth,lnode->ExpDate,lnode->Type);
224 
225           lnode=lnode->next;
226         }
227 
228         /* Send response to SS5SRV */
229         if( send(s,buf,sizeof(buf),0) == -1) {
230           perror("Send err:");
231           return ERR;
232         }
233       } while( lnode != NULL );
234     }
235   }
236   return OK;
237 }
238 
ListAuthoCache(UINT s)239 UINT ListAuthoCache( UINT s )
240 {
241   UINT count;
242 
243   struct _S5AuthoCacheNode *lnode, *node;
244 
245   char buf[230];
246 
247   for(count = 0;count < MAXAUTHOCACHELIST; count++) {
248     if( (node=S5AuthoCacheList[count]) != NULL) {
249 
250       lnode=node;
251       do {
252         if(lnode != NULL ) {
253           snprintf(buf,sizeof(buf),"%64s\n%5u\n%64s\n%5u\n%64s\n%16lu\n%5u\n",lnode->Sa,lnode->Sp,lnode->Da,lnode->Dp,lnode->Us,lnode->ttl,lnode->Flg);
254           lnode=lnode->next;
255         }
256 
257         if( send(s,buf,sizeof(buf),0) == -1) {
258           perror("Send err:");
259           return ERR;
260         }
261       } while( lnode != NULL );
262     }
263   }
264   return OK;
265 }
266 
SrvAuthorization(struct _SS5ClientInfo * ci,struct _SS5Socks5Data * sd)267 INT SrvAuthorization( struct _SS5ClientInfo *ci, struct _SS5Socks5Data *sd )
268 {
269   UINT type,
270                method,
271                method2=NOMETHOD,
272                srcMask,
273                dstMask;
274 
275   char me[1],sa[64],sp[16],da[64],dp[16],fu[16],grp[256],ba[16],ed[10];
276 
277   struct _SS5Facilities fa;
278 
279   char srvResponse[544];
280 
281   if( STREQ(sd->MethodRequest,"ET /list=AUTHORIZATION HTTP/1.",sizeof("ET /list=AUTHORIZATION HTTP/1.") - 1) ) {
282     ListAutho(ci->Socket);
283     return OK;
284   }
285   else if( STREQ(sd->MethodRequest,"ET /list=AUTHOCACHE HTTP/1.",sizeof("ET /list=AUTHOCACHE HTTP/1.") - 1) ) {
286     ListAuthoCache(ci->Socket);
287     return OK;
288   }
289   else if( STREQ(sd->MethodRequest,"DD /permit=",sizeof("DD /permit=") - 1)  || STREQ(sd->MethodRequest,"DD /deny=",sizeof("DD /deny=") - 1) ) {
290 
291     if( STREQ(sd->MethodRequest,"DD /permit=",sizeof("DD /permit=") - 1) ) {
292       sscanf(sd->MethodRequest,"DD /permit=%1s\n%64s\n%16s\n%64s\n%16s\n%16s\n%256s\n%16s\n%10s\n",me,sa,sp,da,dp,fu,grp,ba,ed);
293       type=PERMIT;
294     }
295     else {
296       sscanf(sd->MethodRequest,"DD /deny=%1s\n%64s\n%16s\n%64s\n%16s\n%16s\n%256s\n%16s\n%10s\n",me,sa,sp,da,dp,fu,grp,ba,ed);
297       type=DENY;
298     }
299 
300     switch(me[0]) {
301       case '-':    method=NOAUTH;    break;
302       case 'u':    method=USRPWD;    break;
303       case 'n':    method=FAKEPWD;   break;
304       case 's':    method=S_USER_PWD;  break;
305 #ifdef SS5_USE_GSSAPI
306       case 'k':    method=GSSAPI;      break;
307 #endif
308       default:     SS5Modules.mod_logging.Logging("[ERRO] Method unknown in permit line.");    return ERR;    break;
309     }
310 
311     if( ba[0] == '-' )
312       strncpy(ba,"0\0",2);
313 
314     strncpy(fa.Fixup,fu,sizeof(fa.Fixup));
315     strncpy(fa.Group,grp,sizeof(fa.Group));
316     fa.Bandwidth=atoi(ba);
317     strncpy(fa.ExpDate,ed,sizeof(fa.ExpDate));
318 
319     srcMask=S5GetNetmask(sa);
320     dstMask=S5GetNetmask(da);
321 
322     if( (sa[0] > 64) && (da[0] >64) ) {
323       if( AddAcl(ONLINE, type,S5StrHash(sa),sa, S5GetRange(sp), S5StrHash(da),da,S5GetRange(dp),32-srcMask,32-dstMask,method,method2,&fa)  &&
324           (NAclList < MAXACLLIST) ) {
325         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
326         NAclList++;
327       }
328       else
329         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
330     }
331     else if( da[0] >64 ) {
332       if( AddAcl(ONLINE, type,inet_network(sa),"-", S5GetRange(sp), S5StrHash(da),da,S5GetRange(dp),32-srcMask,32-dstMask,method,method2,&fa) &&
333           (NAclList < MAXACLLIST) ) {
334         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
335         NAclList++;
336       }
337       else
338         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
339     }
340     else if ( sa[0] > 64 ) {
341       if( AddAcl(ONLINE,type,S5StrHash(sa),sa,S5GetRange(sp), inet_network(da),"-",S5GetRange(dp),32-srcMask,32-dstMask,method,method2,&fa) &&
342           (NAclList < MAXACLLIST) ) {
343         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
344         NAclList++;
345       }
346       else
347         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
348     }
349     else {
350       if( AddAcl(ONLINE,type,inet_network(sa),"-", S5GetRange(sp),inet_network(da),"-",S5GetRange(dp),32-srcMask,32-dstMask,method,method2,&fa) &&
351           (NAclList < MAXACLLIST) ) {
352         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
353         NAclList++;
354       }
355       else
356         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
357     }
358 
359     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
360       perror("Send err:");
361       return ERR;
362     }
363     return OK;
364   }
365   else if( STREQ(sd->MethodRequest,"EL /permit=",sizeof("EL /permit=") - 1) || STREQ(sd->MethodRequest,"EL /deny=",sizeof("EL /deny=") - 1) ) {
366 
367     if( STREQ(sd->MethodRequest,"EL /permit=",sizeof("EL /permit=") - 1) ) {
368       sscanf(sd->MethodRequest,"EL /permit=%1s\n%64s\n%16s\n%64s\n%16s\n%16s\n%256s\n%16s\n%10s\n",me,sa,sp,da,dp,fu,grp,ba,ed);
369       type=PERMIT;
370     }
371     else {
372       sscanf(sd->MethodRequest,"EL /deny=%1s\n%64s\n%16s\n%64s\n%16s\n%16s\n%256s\n%16s\n%10s\n",me,sa,sp,da,dp,fu,grp,ba,ed);
373       type=DENY;
374     }
375 
376     switch(me[0]) {
377       case '-':    method=NOAUTH;    break;
378       case 'u':    method=USRPWD;    break;
379       case 'n':    method=FAKEPWD;   break;
380       case 's':    method=S_USER_PWD;  break;
381 #ifdef SS5_USE_GSSAPI
382       case 'k':    method=GSSAPI;      break;
383 #endif
384       default:     SS5Modules.mod_logging.Logging("[ERRO] Method unknown in permit line.");    return ERR;    break;
385     }
386 
387     if( ba[0] == '-' )
388       strncpy(ba,"0\0",2);
389 
390     strncpy(fa.Fixup,fu,sizeof(fa.Fixup));
391     strncpy(fa.Group,grp,sizeof(fa.Group));
392     fa.Bandwidth=atoi(ba);
393     strncpy(fa.ExpDate,ed,sizeof(fa.ExpDate));
394 
395     srcMask=S5GetNetmask(sa);
396     dstMask=S5GetNetmask(da);
397 
398     if( (sa[0] > 64) && (da[0] >64) ) {
399       if( DelAcl(PERMIT,S5StrHash(sa),sa, S5GetRange(sp), S5StrHash(da),da,S5GetRange(dp),32-srcMask,32-dstMask,method,&fa)  &&
400           (NAclList < MAXACLLIST) ) {
401         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
402         NAclList++;
403       }
404       else
405         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
406     }
407     else if( da[0] >64 ) {
408       if( DelAcl(PERMIT,inet_network(sa),"-", S5GetRange(sp), S5StrHash(da),da,S5GetRange(dp),32-srcMask,32-dstMask,method,&fa) &&
409           (NAclList < MAXACLLIST) ) {
410         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
411         NAclList++;
412       }
413       else
414         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
415     }
416     else if ( sa[0] > 64 ) {
417       if( DelAcl(PERMIT,S5StrHash(sa),sa,S5GetRange(sp), inet_network(da),"-",S5GetRange(dp),32-srcMask,32-dstMask,method,&fa) &&
418           (NAclList < MAXACLLIST) ) {
419         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
420         NAclList++;
421       }
422       else
423         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
424     }
425     else {
426       if( DelAcl(PERMIT,inet_network(sa),"-", S5GetRange(sp),inet_network(da),"-",S5GetRange(dp),32-srcMask,32-dstMask,method,&fa) &&
427           (NAclList < MAXACLLIST) ) {
428         strncpy(srvResponse,"OK\0",sizeof("OK\0"));
429         NAclList++;
430       }
431       else
432         strncpy(srvResponse,"ERR\0",sizeof("ERR\0"));
433     }
434 
435     if( send(ci->Socket,srvResponse,strlen(srvResponse),0) == -1) {
436       perror("Send err:");
437       return ERR;
438     }
439     return OK;
440   }
441 
442   return ERR_SRV_REQUEST;
443 }
444 
FileCheck(char * group,char * user)445 inline UINT FileCheck( char *group, char *user )
446 {
447   FILE *groupFile;
448 
449   UINT i,l;
450 
451   pid_t pid;
452 
453   char groupFileName[512];
454   char userName[64];
455 
456   char logString[128];
457 
458    /*
459    *    Get child/thread pid
460    */
461   if( NOTTHREADED() )
462     pid=getpid();
463   else
464     pid=(UINT)(uintmax_t)pthread_self();
465 
466   if( SS5SocksOpt.Profiling == FILE_PROFILING ) {
467     strncpy(groupFileName,S5ProfilePath,sizeof(groupFileName));
468     STRSCAT(groupFileName,"/");
469     STRSCAT(groupFileName,group);
470 
471     if( (groupFile = fopen(groupFileName,"r")) == NULL ) {
472       ERRNO(pid)
473       return ERR;
474     }
475 
476     /*
477      *    Check for username into configuration file for access profile
478      */
479     while( fscanf(groupFile,"%64s",userName) != EOF ) {
480       if( userName[0] != '#' )
481         if( STRCASEEQ(userName,user,64) ) {
482           fclose(groupFile);
483           return OK;
484         }
485     }
486     fclose(groupFile);
487     return ERR;
488   }
489   return ERR;
490 }
491 
S5CheckexpDate(char * expdate)492 UINT S5CheckexpDate(char *expdate)
493 {
494   time_t t;
495   struct tm *currentDate;
496   struct tm tm;
497 
498   char ps[128];
499 
500   if( expdate[0] == '-' )
501     return OK;
502 
503   strncpy(ps,expdate,sizeof(ps));
504   strncat(ps," 00:00:00",sizeof(ps));
505   strptime(ps, "%d-%m-%Y %H:%M:%S", &tm);
506 
507   t=time(NULL);
508   currentDate=gmtime(&t);
509 
510   if( tm.tm_year < currentDate->tm_year )
511     return ERR;
512   else if( tm.tm_year > currentDate->tm_year )
513     return OK;
514   else if( tm.tm_mon < currentDate->tm_mon )
515     return ERR;
516   else if( tm.tm_mon > currentDate->tm_mon )
517     return OK;
518   else if( tm.tm_mday < currentDate->tm_mday )
519     return ERR;
520   else
521     return OK;
522 }
523 
S5CheckPort(char * port,UINT s5port)524 UINT S5CheckPort(char *port, UINT s5port)
525 {
526   register UINT idx1;
527   register UINT idx2;
528 
529   UINT p1 = 0;
530   UINT p2 = 0;
531   UINT len;
532 
533   char s1[6];
534   char s2[6];
535 
536   len = strlen(port);
537   for(idx1 = 0; (port[idx1]) != '-' && (idx1 < len); idx1++)
538     s1[idx1] = port[idx1];
539   if( (p1 = atoi(s1)) > 65535 )
540           return ERR;
541   idx1++;
542   for(idx2 = 0; idx1 < len; idx2++, idx1++)
543           s2[idx2] = port[idx1];
544   if( (p2 = atoi(s2)) > 65535 )
545           return ERR;
546   if( p2 ) {
547     if( p2 < p1 )
548       return ERR;
549     else if( s5port < p1 || s5port > p2 )
550       return ERR;
551   }
552   else if( p1 != s5port )
553     return ERR;
554 
555   return OK;
556 }
557 
558 
559 /* ******************************** HASH for ACL ******** **************************** */
AclHash(ULINT sa,ULINT da,UINT dp)560 inline UINT AclHash( ULINT sa, ULINT da, UINT dp )
561 {
562   register UINT idx;
563   register UINT len;
564 
565   register long int hashVal = 0;
566 
567   char s[256];
568 
569   snprintf(s,sizeof(s) - 1,"%lu%lu%u",sa,da,dp);
570 
571   len = strlen(s);
572   for(idx = 0; idx < len; idx++)
573     hashVal = 37*hashVal + s[idx];
574 
575   hashVal %= MAXACLLIST;
576   if(hashVal < 0)
577     hashVal += MAXACLLIST;
578 
579   return hashVal;
580 }
581 
GetAcl(ULINT sa,UINT sp,ULINT da,UINT dp,struct _SS5Facilities * fa,UINT * me,UINT * me2)582 INT GetAcl(ULINT sa, UINT sp, ULINT da, UINT dp, struct _SS5Facilities *fa, UINT *me, UINT *me2)
583 {
584   register UINT index;
585   register UINT srcnm;
586   register UINT dstnm;
587 
588   register ULINT n_sa;
589   register ULINT n_da;
590 
591   UINT err = ERR;
592 
593   struct _S5AclNode *node;
594 
595   /*
596    * 1° hash cicle: check <SrcIP/Net> <DstIP> <DstPort>
597    */
598   for(srcnm=0;srcnm<=32;srcnm++) {
599     if( srcnm < 32)
600       n_sa=((sa >> srcnm) << srcnm);
601     else
602       n_sa=0;
603     index=AclHash( n_sa, da, dp );
604 
605     if( S5AclList[index]!= NULL ) {
606       node=S5AclList[index];
607       do {
608         if( (node->SrcAddr == n_sa) && (node->SrcMask == srcnm) && (node->DstAddr == da) && (node->DstPort == dp) ) {
609           if( ((sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax)) || (node->SrcPort == sp) ) {
610             if( S5CheckexpDate(node->ExpDate) ) {
611              if( node->Group[0] != '-' ) {
612                /*
613                 * Look for username into group (file or directory) defined in permit line
614                 */
615                if( SS5SocksOpt.Profiling == FILE_PROFILING )
616                  err=FileCheck(node->Group,fa->Group);
617                else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
618                  err=DirectoryCheck(node->Group,fa->Group);
619 #ifdef SS5_USE_MYSQL
620                else if( SS5SocksOpt.Profiling == MYSQL_PROFILING )
621                  err=MySqlCheck(node->Group,fa->Group);
622 #endif
623                if( err ) {
624                  *me=node->Method;
625                  *me2=node->Method2;
626                  strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
627                  fa->Bandwidth=node->Bandwidth;
628                  if(node->Type == PERMIT ) {
629                    return OK;
630                  }
631                  return ERR_DENY;
632                }
633              }
634              else {
635                *me=node->Method;
636                *me2=node->Method2;
637                strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
638                fa->Bandwidth=node->Bandwidth;
639                if(node->Type == PERMIT ) {
640                  return OK;
641                }
642                return ERR_DENY;
643              }
644            }
645           }
646         }
647         node=node->next;
648       } while(node != NULL );
649     }
650   }
651   /*
652    * 2° hash cicle: check <SrcIP/Net> <DstIP> <0-65535 (DstPort)>
653    */
654   for(srcnm=0;srcnm<=32;srcnm++) {
655     if( srcnm < 32)
656       n_sa=((sa >> srcnm) << srcnm);
657     else
658       n_sa=0;
659     index=AclHash( n_sa, da, 0 );
660 
661     if( S5AclList[index]!= NULL ) {
662       node=S5AclList[index];
663       do {
664         if( (node->SrcAddr == n_sa) && (node->SrcMask == srcnm) && (node->DstAddr == da) && (dp >= node->DstRangeMin) && (dp <= node->DstRangeMax) ) {
665           if( ((sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax)) || (node->SrcPort == sp) ) {
666             if( S5CheckexpDate(node->ExpDate) ) {
667               if( node->Group[0] != '-' ) {
668                 /*
669                  * Look for username into group (file or directory) defined in permit line
670                  */
671                 if( SS5SocksOpt.Profiling == FILE_PROFILING )
672                   err=FileCheck(node->Group,fa->Group);
673                 else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
674                   err=DirectoryCheck(node->Group,fa->Group);
675 #ifdef SS5_USE_MYSQL
676                 else if( SS5SocksOpt.Profiling == MYSQL_PROFILING )
677                   err=MySqlCheck(node->Group,fa->Group);
678 #endif
679                 if( err ) {
680                   *me=node->Method;
681                   *me2=node->Method2;
682                   strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
683                   fa->Bandwidth=node->Bandwidth;
684                   if(node->Type == PERMIT )
685                     return OK;
686                   return ERR_DENY;
687                 }
688               }
689               else {
690                 *me=node->Method;
691                 *me2=node->Method2;
692                 strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
693                 fa->Bandwidth=node->Bandwidth;
694                 if(node->Type == PERMIT ) {
695                   return OK;
696                 }
697                 return ERR_DENY;
698               }
699             }
700           }
701         }
702         node=node->next;
703       } while(node != NULL );
704     }
705   }
706 
707 
708   /*
709    * 3° hash cicle: check <SrcIP> <DstIP/Net> <DstPort>
710    */
711   for(dstnm=0;dstnm<=32;dstnm++) {
712     if( dstnm < 32)
713       n_da=((da >> dstnm) << dstnm);
714     else
715       n_da=0;
716     index=AclHash( sa, n_da, dp );
717 
718     if( S5AclList[index]!= NULL ) {
719       node=S5AclList[index];
720       do {
721         if( (node->SrcAddr == sa) && (node->DstAddr == n_da) && (node->DstMask == dstnm) && (node->DstPort == dp) ) {
722           if( ((sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax)) || (node->SrcPort == sp) ) {
723             if( S5CheckexpDate(node->ExpDate) ) {
724               if( node->Group[0] != '-' ) {
725                 /*
726                  * Look for username into group (file or directory) defined in permit line
727                  */
728                 if( SS5SocksOpt.Profiling == FILE_PROFILING )
729                   err=FileCheck(node->Group,fa->Group);
730                 else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
731                   err=DirectoryCheck(node->Group,fa->Group);
732 #ifdef SS5_USE_MYSQL
733                 else if( SS5SocksOpt.Profiling == MYSQL_PROFILING )
734                   err=MySqlCheck(node->Group,fa->Group);
735 #endif
736                 if( err ) {
737                   *me=node->Method;
738                   *me2=node->Method2;
739                   strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
740                   fa->Bandwidth=node->Bandwidth;
741                   if(node->Type == PERMIT )
742                     return OK;
743                   return ERR_DENY;
744                 }
745               }
746               else {
747                 *me=node->Method;
748                 *me2=node->Method2;
749                 strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
750                 fa->Bandwidth=node->Bandwidth;
751                 if(node->Type == PERMIT ) {
752                   return OK;
753                 }
754                 return ERR_DENY;
755               }
756             }
757           }
758         }
759         node=node->next;
760       } while(node != NULL );
761     }
762   }
763 
764   /*
765    * 4° hash cicle: check <SrcIP> <DstIP/Net> <0-65535 (DstPort)>
766    */
767   for(dstnm=0;dstnm<=32;dstnm++) {
768     if( dstnm < 32)
769       n_da=((da >> dstnm) << dstnm);
770     else
771       n_da=0;
772     index=AclHash( sa, n_da, 0 );
773 
774     if( S5AclList[index]!= NULL ) {
775       node=S5AclList[index];
776       do {
777         if( (node->SrcAddr == sa) && (node->DstAddr == n_da) && (node->DstMask == dstnm) && (dp >= node->DstRangeMin) && (dp <= node->DstRangeMax) ) {
778           if( ((sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax)) || (node->SrcPort == sp) ) {
779             if( S5CheckexpDate(node->ExpDate) ) {
780               if( node->Group[0] != '-' ) {
781                 /*
782                  * Look for username into group (file or directory) defined in permit line
783                  */
784                 if( SS5SocksOpt.Profiling == FILE_PROFILING )
785                   err=FileCheck(node->Group,fa->Group);
786                 else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
787                   err=DirectoryCheck(node->Group,fa->Group);
788 #ifdef SS5_USE_MYSQL
789                 else if( SS5SocksOpt.Profiling == MYSQL_PROFILING )
790                   err=MySqlCheck(node->Group,fa->Group);
791 #endif
792                 if( err ) {
793                   *me=node->Method;
794                   *me2=node->Method2;
795                   strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
796                   fa->Bandwidth=node->Bandwidth;
797                   if(node->Type == PERMIT )
798                     return OK;
799                   return ERR_DENY;
800                 }
801               }
802               else {
803                 *me=node->Method;
804                 *me2=node->Method2;
805                 strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
806                 fa->Bandwidth=node->Bandwidth;
807                 if(node->Type == PERMIT ) {
808                   return OK;
809                 }
810                 return ERR_DENY;
811               }
812             }
813           }
814         }
815         node=node->next;
816       } while(node != NULL );
817     }
818   }
819 
820   /*
821    * 5° hash cicle: check <SrcIP/Net> <DstIP/Net> <DstPort>
822    */
823   for(dstnm=1;dstnm<=32;dstnm++) {
824     if( dstnm < 32)
825       n_da=((da >> dstnm) << dstnm);
826     else
827       n_da=0;
828 
829     for(srcnm=1;srcnm<=32;srcnm++) {
830       if( srcnm < 32)
831         n_sa=((sa >> srcnm) << srcnm);
832       else
833         n_sa=0;
834       index=AclHash( n_sa, n_da, dp );
835 
836       if( S5AclList[index]!= NULL ) {
837         node=S5AclList[index];
838         do {
839           if( (node->SrcAddr == n_sa) && (node->SrcMask == srcnm) && (node->DstAddr == n_da) && (node->DstMask == dstnm) && (node->DstPort == dp) ) {
840             if( ((sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax)) || (node->SrcPort == sp) ) {
841               if( S5CheckexpDate(node->ExpDate) ) {
842                 if( node->Group[0] != '-' ) {
843                   /*
844                    * Look for username into group (file or directory) defined in permit line
845                    */
846                   if( SS5SocksOpt.Profiling == FILE_PROFILING )
847                     err=FileCheck(node->Group,fa->Group);
848                   else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
849                     err=DirectoryCheck(node->Group,fa->Group);
850 #ifdef SS5_USE_MYSQL
851                   else if( SS5SocksOpt.Profiling == MYSQL_PROFILING )
852                     err=MySqlCheck(node->Group,fa->Group);
853 #endif
854                   if( err ) {
855                     *me=node->Method;
856                     *me2=node->Method2;
857                     strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
858                     fa->Bandwidth=node->Bandwidth;
859                     if(node->Type == PERMIT )
860                       return OK;
861 
862                     return ERR_DENY;
863                   }
864                 }
865                 else {
866                   *me=node->Method;
867                   *me2=node->Method2;
868                   strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
869                   fa->Bandwidth=node->Bandwidth;
870                   if(node->Type == PERMIT ) {
871                     return OK;
872                   }
873                   return ERR_DENY;
874                 }
875               }
876             }
877           }
878           node=node->next;
879         } while(node != NULL );
880       }
881     }
882   }
883   /*
884    * 6° hash cicle: check <SrcIP/Net> <DstIP/Net> <DstPort>
885    */
886   for(dstnm=1;dstnm<=32;dstnm++) {
887     if( dstnm < 32)
888       n_da=((da >> dstnm) << dstnm);
889     else
890       n_da=0;
891 
892     for(srcnm=1;srcnm<=32;srcnm++) {
893       if( srcnm < 32)
894         n_sa=((sa >> srcnm) << srcnm);
895       else
896         n_sa=0;
897       index=AclHash( n_sa, n_da, 0 );
898 
899       if( S5AclList[index]!= NULL ) {
900         node=S5AclList[index];
901         do {
902           if( (node->SrcAddr == n_sa) && (node->SrcMask == srcnm) && (node->DstAddr == n_da) && (node->DstMask == dstnm) && (dp >= node->DstRangeMin) && (dp <= node->DstRangeMax) ) {
903             if( ((sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax)) || (node->SrcPort == sp) ) {
904               if( S5CheckexpDate(node->ExpDate) ) {
905                 if( node->Group[0] != '-' ) {
906                   /*
907                    * Look for username into group (file or directory) defined in permit line
908                    */
909                   if( SS5SocksOpt.Profiling == FILE_PROFILING )
910                     err=FileCheck(node->Group,fa->Group);
911                   else if( SS5SocksOpt.Profiling == LDAP_PROFILING )
912                     err=DirectoryCheck(node->Group,fa->Group);
913 #ifdef SS5_USE_MYSQL
914                   else if( SS5SocksOpt.Profiling == MYSQL_PROFILING )
915                     err=MySqlCheck(node->Group,fa->Group);
916 #endif
917                   if( err ) {
918                     *me=node->Method;
919                     *me2=node->Method2;
920                     strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
921                     fa->Bandwidth=node->Bandwidth;
922                     if(node->Type == PERMIT )
923                       return OK;
924                     return ERR_DENY;
925                   }
926                 }
927                 else {
928                   *me=node->Method;
929                   *me2=node->Method2;
930                   strncpy(fa->Fixup,node->Fixup,sizeof(fa->Fixup));
931                   fa->Bandwidth=node->Bandwidth;
932                   if(node->Type == PERMIT ) {
933                     return OK;
934                   }
935                   return ERR_DENY;
936                 }
937               }
938             }
939           }
940           node=node->next;
941         } while(node != NULL );
942       }
943     }
944   }
945   return ERR_NOACLFOUND;
946 }
947 
AddAcl(UINT ctx,UINT type,ULINT sa,char sfqdn[64],ULINT sp,ULINT da,char dfqdn[64],ULINT dp,UINT srcmask,UINT dstmask,UINT method,UINT method2,struct _SS5Facilities * fa)948 UINT AddAcl(UINT ctx, UINT type, ULINT sa, char sfqdn[64],ULINT sp, ULINT da, char dfqdn[64],ULINT dp, UINT srcmask, UINT dstmask, UINT method, UINT method2, struct _SS5Facilities *fa)
949 {
950   int index;
951   struct _S5AclNode *node, *prevnode;
952 
953   if( dp > 65535 )
954     index=AclHash( sa, da, 0 );
955   else
956     index=AclHash( sa, da, dp );
957 
958 
959   if( ctx == OFFLINE )
960     node=_tmp_S5AclList[index];
961   else
962     node=S5AclList[index];
963 
964   if( node== NULL ) {
965     if( (node=(struct _S5AclNode *)calloc(1,sizeof(struct _S5AclNode))) == NULL )
966       return ERR;
967 
968     node->SrcAddr=sa;
969     strncpy(node->SrcAddrFqdn,sfqdn,sizeof(node->SrcAddrFqdn));
970     node->Type=type;
971 
972 
973     if( sp > 65535 ) {
974       node->SrcPort=sp;
975       node->SrcRangeMax=sp;
976       node->SrcRangeMax >>= 16;
977       node->SrcRangeMax <<= 16;
978       node->SrcRangeMin = sp - node->SrcRangeMax;
979       node->SrcRangeMax >>= 16;
980     }
981     else
982       node->SrcPort=sp;
983 
984 
985     node->SrcMask=srcmask;
986     node->DstAddr=da;
987     strncpy(node->DstAddrFqdn,dfqdn,sizeof(node->DstAddrFqdn));
988 
989     if( dp > 65535 ) {
990       node->DstPort=dp;
991       node->DstRangeMax=dp;
992       node->DstRangeMax >>= 16;
993       node->DstRangeMax <<= 16;
994       node->DstRangeMin = dp - node->DstRangeMax;
995       node->DstRangeMax >>= 16;
996     }
997     else
998       node->DstPort=dp;
999 
1000 
1001     node->DstMask=dstmask;
1002     node->Method=method;
1003     node->Method2=method2;
1004     strncpy(node->Fixup,fa->Fixup,sizeof(fa->Fixup));
1005     strncpy(node->Group,fa->Group,sizeof(fa->Group));
1006     node->Bandwidth=fa->Bandwidth;
1007     strncpy(node->ExpDate,fa->ExpDate,sizeof(fa->ExpDate));
1008     node->next=NULL;
1009 
1010     if( ctx == OFFLINE )
1011       _tmp_S5AclList[index]=node;
1012     else
1013       S5AclList[index]=node;
1014 
1015   }
1016   else {
1017 
1018     if( ctx == OFFLINE )
1019       node=_tmp_S5AclList[index];
1020     else
1021       node=S5AclList[index];
1022 
1023     do {
1024       if( (node->SrcAddr == sa) && (node->SrcMask == srcmask) && (node->DstAddr == da) && (node->DstMask == dstmask) )
1025         if( (node->DstPort == dp) && (node->SrcPort == sp))  {
1026           return ERR;
1027         }
1028 
1029       prevnode=node;
1030       node=node->next;
1031 
1032     } while( node != NULL );
1033 
1034     if( (node=(struct _S5AclNode *)calloc(1,sizeof(struct _S5AclNode))) == NULL )
1035       return ERR;
1036 
1037 
1038     node->SrcAddr=sa;
1039     strncpy(node->SrcAddrFqdn,sfqdn,sizeof(node->SrcAddrFqdn));
1040     node->Type=type;
1041 
1042     if( sp > 65535 ) {
1043       node->SrcPort=sp;
1044       node->SrcRangeMax=sp;
1045       node->SrcRangeMax >>= 16;
1046       node->SrcRangeMax <<= 16;
1047       node->SrcRangeMin = sp - node->SrcRangeMax;
1048       node->SrcRangeMax >>= 16;
1049     }
1050     else
1051       node->SrcPort=sp;
1052 
1053     node->SrcMask=srcmask;
1054     node->DstAddr=da;
1055     strncpy(node->DstAddrFqdn,dfqdn,sizeof(node->DstAddrFqdn));
1056 
1057     if( dp > 65535 ) {
1058       node->DstPort=dp;
1059       node->DstRangeMax=dp;
1060       node->DstRangeMax >>= 16;
1061       node->DstRangeMax <<= 16;
1062       node->DstRangeMin = dp - node->DstRangeMax;
1063       node->DstRangeMax >>= 16;
1064     }
1065     else
1066       node->DstPort=dp;
1067 
1068     node->DstMask=dstmask;
1069     node->Method=method;
1070     node->Method2=method2;
1071     strncpy(node->Fixup,fa->Fixup,sizeof(fa->Fixup));
1072     strncpy(node->Group,fa->Group,sizeof(fa->Group));
1073     node->Bandwidth=fa->Bandwidth;
1074     strncpy(node->ExpDate,fa->ExpDate,sizeof(fa->ExpDate));
1075     node->next=NULL;
1076 
1077     prevnode->next=node;
1078   }
1079 
1080   return OK;
1081 }
1082 
1083 
DelAcl(UINT type,ULINT sa,char sfqdn[64],ULINT sp,ULINT da,char dfqdn[64],ULINT dp,UINT srcmask,UINT dstmask,UINT method,struct _SS5Facilities * fa)1084 UINT DelAcl(UINT type, ULINT sa, char sfqdn[64],ULINT sp, ULINT da, char dfqdn[64],ULINT dp, UINT srcmask, UINT dstmask, UINT method, struct _SS5Facilities *fa)
1085 {
1086   int index;
1087   struct _S5AclNode *node, *prevnode=NULL;
1088 
1089   if( dp > 65535 )
1090     index=AclHash( sa, da, 0 );
1091   else
1092     index=AclHash( sa, da, dp );
1093 
1094   node=S5AclList[index];
1095 
1096   if( node == NULL )
1097     return ERR;
1098 
1099   if( (node->SrcAddr == sa) && (node->SrcMask == srcmask) && (node->DstAddr == da) && (node->DstMask == dstmask) ) {
1100     if( (node->Type == type) && (node->DstPort == dp) && (node->SrcPort == sp))  {
1101       if( node->next == NULL ) {
1102 
1103         free(node);
1104         S5AclList[index]=NULL;
1105         return OK;
1106       }
1107       else {
1108         S5AclList[index]=node->next;
1109         free(node);
1110         return OK;
1111       }
1112     }
1113   }
1114 
1115   while( node->next != NULL ) {
1116     prevnode=node;
1117     node=node->next;
1118 
1119     if( (node->SrcAddr == sa) && (node->SrcMask == srcmask) && (node->DstAddr == da) && (node->DstMask == dstmask) )
1120       if( (node->Type == type) && (node->DstPort == dp) && (node->SrcPort == sp))  {
1121         if( node->next != NULL )
1122           prevnode->next=node->next;
1123         else
1124           prevnode->next=NULL;
1125 
1126         free(node);
1127         node=NULL;
1128         return OK;
1129       }
1130   }
1131   return ERR;
1132 }
1133 
1134 
1135 
FreeAcl(struct _S5AclNode ** node)1136 UINT FreeAcl( struct _S5AclNode **node )
1137 {
1138   struct _S5AclNode *lnode;
1139   struct _S5AclNode *lnode_prev=NULL;
1140 
1141   lnode=*node;
1142 
1143   if( lnode != NULL ) {
1144     do {
1145       while( lnode->next != NULL ) {
1146         lnode_prev=lnode;
1147         lnode=lnode->next;
1148       }
1149       free(lnode);
1150       if( lnode_prev != NULL ) {
1151         lnode_prev->next=NULL;
1152         lnode=lnode_prev;
1153         lnode_prev=NULL;
1154       }
1155       else
1156         lnode=NULL;
1157     } while( (lnode) != NULL );
1158   }
1159   *node=NULL;
1160 
1161   return OK;
1162 }
1163 
1164 
1165 /* ***************************** HASH for AUTHORIZATION CACHE **************************** */
S5AuthoCacheHash(char * sa,char * da,UINT dp,char * u)1166 inline UINT S5AuthoCacheHash( char *sa, char *da, UINT dp, char *u )
1167 {
1168   register int idx;
1169   register int len;
1170   register long int hashVal = 0;
1171   char s[256];
1172 
1173   s[0] = '\0';
1174 
1175   snprintf(s,256 - 1,"%s%s%u%s",sa,da,dp,u);
1176 
1177   len = strlen(s);
1178   for(idx = 0; idx < len; idx++)
1179     hashVal = 37*hashVal + s[idx];
1180 
1181   hashVal %= MAXAUTHOCACHELIST;
1182   if(hashVal < 0)
1183     hashVal += MAXAUTHOCACHELIST;
1184 
1185   return hashVal;
1186 
1187 }
1188 
GetAuthoCache(char * sa,char * da,UINT dp,char * u,struct _SS5Facilities * fa,UINT f)1189 UINT GetAuthoCache( char *sa, char *da, UINT dp, char *u, struct _SS5Facilities *fa, UINT f )
1190 {
1191   register UINT index;
1192   struct _S5AuthoCacheNode *node;
1193 
1194     index=S5AuthoCacheHash( sa, da, dp, u );
1195 
1196     if( S5AuthoCacheList[index]!= NULL ) {
1197       node=S5AuthoCacheList[index];
1198       do {
1199         if( STREQ(sa,node->Sa,sizeof(node->Sa)) && STREQ(da,node->Da,sizeof(node->Da)) && (dp == node->Dp) && STREQ(u,node->Us,sizeof(node->Us))) {
1200           if( node->ttl > time(NULL) ) {
1201             strncpy(fa->Fixup,node->Fa.Fixup,sizeof(S5AuthoCacheList[index]->Fa.Fixup));
1202             fa->Bandwidth = node->Fa.Bandwidth;
1203             node->Flg += f;
1204             if( node->Flg )
1205               return OK+100;
1206             else
1207               return OK;
1208           }
1209           else {
1210             node->Flg += f;
1211             return ERR_AUTHOCACHE_EXPIRED;
1212           }
1213         }
1214         node=node->next;
1215       } while(node != NULL );
1216     }
1217 
1218   return ERR;
1219 }
1220 
AddAuthoCache(char * sa,char * da,UINT dp,char * u,struct _SS5Facilities * fa)1221 UINT AddAuthoCache( char *sa,  char *da, UINT dp, char *u, struct _SS5Facilities *fa )
1222 {
1223   register UINT index;
1224 
1225   struct _S5AuthoCacheNode *node, *prevnode;
1226 
1227   index=S5AuthoCacheHash( sa, da, dp, u );
1228 
1229   if( S5AuthoCacheList[index]== NULL ) {
1230     if( (S5AuthoCacheList[index]=(struct _S5AuthoCacheNode *)calloc(1,sizeof(struct _S5AuthoCacheNode))) == NULL )
1231       return ERR;
1232 
1233     strncpy(S5AuthoCacheList[index]->Sa,sa,sizeof(S5AuthoCacheList[index]->Sa));
1234     strncpy(S5AuthoCacheList[index]->Da,da,sizeof(S5AuthoCacheList[index]->Da));
1235     S5AuthoCacheList[index]->Dp = dp;
1236     strncpy(S5AuthoCacheList[index]->Us,u,sizeof(S5AuthoCacheList[index]->Us));
1237     strncpy(S5AuthoCacheList[index]->Fa.Fixup,fa->Fixup,sizeof(S5AuthoCacheList[index]->Fa.Fixup));
1238     S5AuthoCacheList[index]->Fa.Bandwidth = fa->Bandwidth;
1239     S5AuthoCacheList[index]->ttl = (time(NULL) + SS5SocksOpt.AuthoCacheAge);
1240     S5AuthoCacheList[index]->Flg += 1;
1241     S5AuthoCacheList[index]->next = NULL;
1242   }
1243   else {
1244     node=S5AuthoCacheList[index];
1245     do {
1246       if( STREQ(sa,node->Sa,sizeof(node->Sa)) && STREQ(da,node->Da,sizeof(node->Da)) && (dp == node->Dp) && STREQ(u,node->Us,sizeof(node->Us)))
1247         return ERR;
1248 
1249       prevnode=node;
1250       node=node->next;
1251 
1252     } while( node != NULL );
1253 
1254     if( (node=(struct _S5AuthoCacheNode *)calloc(1,sizeof(struct _S5AuthoCacheNode))) == NULL )
1255       return ERR;
1256 
1257     node->ttl = (time(NULL) + SS5SocksOpt.AuthoCacheAge);
1258     strncpy(node->Sa,sa,sizeof(S5AuthoCacheList[index]->Sa));
1259     strncpy(node->Da,da,sizeof(S5AuthoCacheList[index]->Da));
1260     node->Dp = dp;
1261     strncpy(node->Us,u,sizeof(S5AuthoCacheList[index]->Us));
1262     strncpy(node->Fa.Fixup,fa->Fixup,sizeof(S5AuthoCacheList[index]->Fa.Fixup));
1263     node->Fa.Bandwidth = fa->Bandwidth;
1264     node->Flg = +1;
1265     node->next = NULL;
1266 
1267     prevnode->next=node;
1268   }
1269   return OK;
1270 }
1271 
UpdateAuthoCache(char * sa,char * da,UINT dp,char * u,UINT f)1272 UINT UpdateAuthoCache( char *sa, char *da, UINT dp, char *u, UINT f )
1273 {
1274   register UINT index;
1275   struct _S5AuthoCacheNode *node;
1276 
1277     index=S5AuthoCacheHash( sa, da, dp, u );
1278 
1279     if( S5AuthoCacheList[index]!= NULL ) {
1280       node=S5AuthoCacheList[index];
1281       do {
1282         if( STREQ(sa,node->Sa,sizeof(node->Sa)) && STREQ(da,node->Da,sizeof(node->Da)) && (dp == node->Dp) && STREQ(u,node->Us,sizeof(node->Us))) {
1283           if( f == 0 )
1284             node->ttl=(time(NULL) + SS5SocksOpt.AuthoCacheAge);
1285           else
1286             node->Flg += f;
1287           return OK;
1288         }
1289         node=node->next;
1290       } while(node != NULL );
1291     }
1292 
1293   return ERR;
1294 }
1295 
1296 
1297 
FreeAuthoCache(struct _S5AuthoCacheNode ** node)1298 UINT FreeAuthoCache( struct _S5AuthoCacheNode **node )
1299 {
1300   struct _S5AuthoCacheNode *lnode;
1301   struct _S5AuthoCacheNode *lnode_prev=NULL;
1302 
1303   lnode=*node;
1304 
1305   if( lnode != NULL ) {
1306     do {
1307       while( lnode->next != NULL ) {
1308         lnode_prev=lnode;
1309         lnode=lnode->next;
1310       }
1311       free(lnode);
1312       if( lnode_prev != NULL ) {
1313         lnode_prev->next=NULL;
1314         lnode=lnode_prev;
1315         lnode_prev=NULL;
1316       }
1317       else
1318         lnode=NULL;
1319     } while( (lnode) != NULL );
1320   }
1321   *node=NULL;
1322 
1323   return OK;
1324 
1325 }
1326 
1327