1 /*
2 3APA3A simpliest proxy server
3 (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
4
5 please read License Agreement
6
7 */
8
9 #include "proxy.h"
10 #ifndef _WIN32
11 #include <sys/resource.h>
12 #include <pwd.h>
13 #include <grp.h>
14 #ifndef NOPLUGINS
15 #include <dlfcn.h>
16 #endif
17 #endif
18
19 #ifndef DEFAULTCONFIG
20 #define DEFAULTCONFIG conf.stringtable[25]
21 #endif
22
23 pthread_mutex_t bandlim_mutex;
24 pthread_mutex_t connlim_mutex;
25 pthread_mutex_t tc_mutex;
26 pthread_mutex_t pwl_mutex;
27 pthread_mutex_t hash_mutex;
28 pthread_mutex_t config_mutex;
29
30 int haveerror = 0;
31 int linenum = 0;
32
33 FILE *writable;
34 struct counter_header cheader = {"3CF", (time_t)0};
35 struct counter_record crecord;
36
37 int mainfunc (int argc, char** argv);
38
39 struct proxydef childdef = {NULL, 0, 0, S_NOSERVICE, ""};
40
41 #define STRINGBUF 65535
42 #define NPARAMS 4096
43
44 #ifndef _WIN32
45 char *chrootp = NULL;
46 static pthread_attr_t pa;
47 #endif
48 char * curconf = NULL;
49
confopen()50 FILE * confopen(){
51 curconf = conf.conffile;
52 #ifndef _WIN32
53 if(chrootp){
54 if(strstr(curconf, chrootp) == curconf)
55 curconf += strlen(chrootp);
56 }
57 #endif
58 if(writable) {
59 rewind(writable);
60 return writable;
61 }
62 return fopen(curconf, "r");
63 }
64
65
66 #ifdef _WIN32
startsrv(LPVOID data)67 DWORD WINAPI startsrv(LPVOID data) {
68 #else
69 void * startsrv(void * data) {
70 #endif
71 struct child *d = (struct child *)data;
72 mainfunc(d->argc, (char **)d->argv);
73 return 0;
74 }
75
76 int included =0;
77
78 int getrotate(char c){
79 switch(c){
80 case 'c':
81 case 'C':
82 return MINUTELY;
83 case 'h':
84 case 'H':
85 return HOURLY;
86 case 'd':
87 case 'D':
88 return DAILY;
89 case 'w':
90 case 'W':
91 return WEEKLY;
92 case 'y':
93 case 'Y':
94 return ANNUALLY;
95 case 'm':
96 case 'M':
97 return MONTHLY;
98 default:
99 return NEVER;
100 }
101 }
102
103
104 unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) {
105 struct tm *ts;
106
107 ts = localtime(&t);
108 if(strchr((char *)name, '%')){
109 struct clientparam fakecli;
110
111 memset(&fakecli, 0, sizeof(fakecli));
112 dobuf2(&fakecli, buf, NULL, NULL, ts, (char *)name);
113 }
114 else switch(lt){
115 case NONE:
116 sprintf((char *)buf, "%s", name);
117 break;
118 case ANNUALLY:
119 sprintf((char *)buf, "%s.%04d", name, ts->tm_year+1900);
120 break;
121 case MONTHLY:
122 sprintf((char *)buf, "%s.%04d.%02d", name, ts->tm_year+1900, ts->tm_mon+1);
123 break;
124 case WEEKLY:
125 t = t - (ts->tm_wday * (60*60*24));
126 ts = localtime(&t);
127 sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
128 break;
129 case DAILY:
130 sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
131 break;
132 case HOURLY:
133 sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour);
134 break;
135 case MINUTELY:
136 sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min);
137 break;
138 default:
139 break;
140 }
141 if(ext){
142 strcat((char *)buf, ".");
143 strcat((char *)buf, (char *)ext);
144 }
145 return buf;
146 }
147
148 int start_proxy_thread(struct child * chp){
149 pthread_t thread;
150 #ifdef _WIN32
151 HANDLE h;
152 #endif
153
154 conf.threadinit = 1;
155 #ifdef _WIN32
156 #ifndef _WINCE
157 h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread);
158 #else
159 h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread);
160 #endif
161 if(h)CloseHandle(h);
162 #else
163 pthread_attr_init(&pa);
164 pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + (32768+conf.stacksize));
165 pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
166 pthread_create(&thread, &pa, startsrv, (void *)chp);
167 pthread_attr_destroy(&pa);
168 #endif
169 while(conf.threadinit)usleep(SLEEPTIME);
170 if(haveerror) {
171 fprintf(stderr, "Service not started on line: %d%s\n", linenum, haveerror == 2? ": insufficient memory":"");
172 return(40);
173 }
174 return 0;
175 }
176
177 static int h_proxy(int argc, unsigned char ** argv){
178 struct child ch;
179
180 ch.argc = argc;
181 ch.argv = argv;
182 if(!strcmp((char *)argv[0], "proxy")) {
183 childdef.pf = proxychild;
184 childdef.port = 3128;
185 childdef.isudp = 0;
186 childdef.service = S_PROXY;
187 childdef.helpmessage = " -n - no NTLM support\n";
188 #ifdef NOIPV6
189 if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){
190 fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, proxy may run very slow\n", linenum);
191 }
192 #endif
193 }
194 else if(!strcmp((char *)argv[0], "pop3p")) {
195 childdef.pf = pop3pchild;
196 childdef.port = 110;
197 childdef.isudp = 0;
198 childdef.service = S_POP3P;
199 childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
200 }
201 else if(!strcmp((char *)argv[0], "smtpp")) {
202 childdef.pf = smtppchild;
203 childdef.port = 25;
204 childdef.isudp = 0;
205 childdef.service = S_SMTPP;
206 childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
207 }
208 else if(!strcmp((char *)argv[0], "ftppr")) {
209 childdef.pf = ftpprchild;
210 childdef.port = 21;
211 childdef.isudp = 0;
212 childdef.service = S_FTPPR;
213 childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
214 }
215 else if(!strcmp((char *)argv[0], "socks")) {
216 childdef.pf = sockschild;
217 childdef.port = 1080;
218 childdef.isudp = 0;
219 childdef.service = S_SOCKS;
220 childdef.helpmessage = " -n - no NTLM support\n";
221 #ifdef NOIPV6
222 if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){
223 fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, socks may run very slow\n", linenum);
224 }
225 #endif
226 }
227 else if(!strcmp((char *)argv[0], "tcppm")) {
228 childdef.pf = tcppmchild;
229 childdef.port = 0;
230 childdef.isudp = 0;
231 childdef.service = S_TCPPM;
232 childdef.helpmessage = "";
233 }
234 else if(!strcmp((char *)argv[0], "udppm")) {
235 childdef.pf = udppmchild;
236 childdef.port = 0;
237 childdef.isudp = 1;
238 childdef.service = S_UDPPM;
239 childdef.helpmessage = " -s single packet UDP service for request/reply (DNS-like) services\n";
240 }
241 else if(!strcmp((char *)argv[0], "admin")) {
242 childdef.pf = adminchild;
243 childdef.port = 80;
244 childdef.isudp = 0;
245 childdef.service = S_ADMIN;
246 }
247 else if(!strcmp((char *)argv[0], "dnspr")) {
248 childdef.pf = dnsprchild;
249 childdef.port = 53;
250 childdef.isudp = 1;
251 childdef.service = S_DNSPR;
252 childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n";
253 #ifndef NOIPV6
254 if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize) || resolvfunc == fakeresolver){
255 fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum);
256 }
257 #endif
258 }
259 return start_proxy_thread(&ch);
260 }
261
262 static int h_internal(int argc, unsigned char ** argv){
263 getip46(46, argv[1], (struct sockaddr *)&conf.intsa);
264 return 0;
265 }
266
267 static int h_external(int argc, unsigned char ** argv){
268 int res;
269 #ifndef NOIPV6
270 struct sockaddr_in6 sa6;
271 memset(&sa6, 0, sizeof(sa6));
272 res = getip46(46, argv[1], (struct sockaddr *)&sa6);
273 if(!res) return 1;
274 if (*SAFAMILY(&sa6)==AF_INET) conf.extsa = sa6;
275 else conf.extsa6 = sa6;
276 #else
277 res = getip46(46, argv[1], (struct sockaddr *)&conf.extsa);
278 #endif
279 return 0;
280 }
281
282
283 static int h_log(int argc, unsigned char ** argv){
284 unsigned char tmpbuf[8192];
285 int notchanged = 0;
286
287
288 havelog = 1;
289 if(argc > 1 && conf.logtarget && !strcmp((char *)conf.logtarget, (char *)argv[1])) {
290 notchanged = 1;
291 }
292 if(!notchanged && conf.logtarget){
293 myfree(conf.logtarget);
294 conf.logtarget = NULL;
295 }
296 if(argc > 1) {
297 if(!strcmp((char *) argv[1], "/dev/null")) {
298 conf.logfunc = lognone;
299 return 0;
300 }
301 if(!notchanged) conf.logtarget = (unsigned char *)mystrdup((char *)argv[1]);
302 if(*argv[1]=='@'){
303 #ifndef _WIN32
304 conf.logfunc = logsyslog;
305 if(notchanged) return 0;
306 openlog((char *)conf.logtarget+1, LOG_PID, LOG_DAEMON);
307 #endif
308 }
309 #ifndef NOODBC
310 else if(*argv[1]=='&'){
311 if(notchanged) return 0;
312 conf.logfunc = logsql;
313 pthread_mutex_lock(&log_mutex);
314 close_sql();
315 init_sql((char *)argv[1]+1);
316 pthread_mutex_unlock(&log_mutex);
317 }
318 #endif
319 #ifndef NORADIUS
320 else if(!strcmp(argv[1],"radius")){
321 conf.logfunc = logradius;
322 }
323 #endif
324 else {
325 if(argc > 2) {
326 conf.logtype = getrotate(*argv[2]);
327 }
328 conf.logfunc = logstdout;
329 if(notchanged) return 0;
330 conf.logtime = time(0);
331 if(conf.logname)myfree(conf.logname);
332 conf.logname = (unsigned char *)mystrdup((char *)argv[1]);
333 if(conf.stdlog) conf.stdlog = freopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a", conf.stdlog);
334 else conf.stdlog = fopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a");
335 if(!conf.stdlog){
336 perror((char *)tmpbuf);
337 return 1;
338 }
339
340 }
341 }
342 else conf.logfunc = logstdout;
343 return 0;
344 }
345
346 static int h_stacksize(int argc, unsigned char **argv){
347 conf.stacksize = atoi((char *)argv[1]);
348 return 0;
349 }
350
351
352 static int h_force(int argc, unsigned char **argv){
353 conf.noforce = 0;
354 return 0;
355 }
356
357 static int h_noforce(int argc, unsigned char **argv){
358 conf.noforce = 1;
359 return 0;
360 }
361
362 static int h_service(int argc, unsigned char **argv){
363 return 0;
364 }
365
366 static int h_daemon(int argc, unsigned char **argv){
367 if(!conf.demon)daemonize();
368 conf.demon = 1;
369 return 0;
370 }
371
372 static int h_config(int argc, unsigned char **argv){
373 if(conf.conffile)myfree(conf.conffile);
374 conf.conffile = mystrdup((char *)argv[1]);
375 if(!conf.conffile) return 21;
376 return 0;
377 }
378
379 static int h_include(int argc, unsigned char **argv){
380 int res;
381 FILE *fp1;
382
383 fp1 = fopen((char *)argv[1], "r");
384 if(!fp1){
385 fprintf(stderr, "Unable to open included file: %s\n", argv[1]);
386 return 1;
387 }
388 res = readconfig(fp1);
389 fclose(fp1);
390 return res;
391 }
392
393 static int h_archiver(int argc, unsigned char **argv){
394 int j;
395
396 conf.archiver = myalloc(argc * sizeof(char *));
397 if(conf.archiver) {
398 conf.archiverc = argc;
399 for(j = 0; j < conf.archiverc; j++) conf.archiver[j] = (unsigned char *)mystrdup((char *)argv[j]);
400 }
401 return 0;
402 }
403
404 static int h_counter(int argc, unsigned char **argv){
405 struct counter_header ch1;
406 if(conf.counterd >=0)close(conf.counterd);
407 conf.counterd = open((char *)argv[1], O_BINARY|O_RDWR|O_CREAT, 0660);
408 if(conf.counterd<0){
409 fprintf(stderr, "Unable to open counter file %s, line %d\n", argv[1], linenum);
410 return 1;
411 }
412 if(read(conf.counterd, &ch1, sizeof(ch1))==sizeof(ch1)){
413 if(memcmp(&ch1, &cheader, 4)){
414 fprintf(stderr, "Not a counter file %s, line %d\n", argv[1], linenum);
415 return 2;
416 }
417 #ifdef _TIME64_T_DEFINED
418 #ifdef _MAX__TIME64_T
419 #define MAX_COUNTER_TIME (_MAX__TIME64_T)
420 #elif defined (MAX__TIME64_T)
421 #define MAX_COUNTER_TIME (MAX__TIME64_T)
422 #else
423 #define MAX_COUNTER_TIME (0x793406fff)
424 #endif
425 #else
426 #define MAX_COUNTER_TIME ((sizeof(time_t)>4)?(time_t)0x793406fff:(time_t)0x7fffffff)
427 #endif
428
429 if(ch1.updated < 0 || ch1.updated >= MAX_COUNTER_TIME){
430 fprintf(stderr, "Invalid or corrupted counter file %s. Use countersutil utility to convert from older version\n", argv[1]);
431 return 3;
432 }
433 cheader.updated = ch1.updated;
434 }
435 if(argc >=4) {
436 conf.countertype = getrotate(*argv[2]);
437 if(conf.counterfile) myfree(conf.counterfile);
438 conf.counterfile = mystrdup((char *)argv[3]);
439 }
440 return 0;
441 }
442
443 static int h_rotate(int argc, unsigned char **argv){
444 conf.rotate = atoi((char *)argv[1]);
445 return 0;
446 }
447
448 static int h_logformat(int argc, unsigned char **argv){
449 unsigned char * old = conf.logformat;
450 conf.logformat = (unsigned char *)mystrdup((char *)argv[1]);
451 if(old) myfree(old);
452 return 0;
453 }
454
455 static int h_timeouts(int argc, unsigned char **argv){
456 int j;
457
458 for(j = 0; conf.timeouts[j] && j + 1 < argc; j++) {
459 if((conf.timeouts[j] = atoi((char *)argv[j + 1])) <= 0 || conf.timeouts[j] > 2000000){
460 fprintf(stderr, "Invalid timeout: %s, line %d\n", argv[j + 1], linenum);
461 return(1);
462 }
463 }
464 return 0;
465 }
466
467 static int h_noop(int argc, unsigned char **argv){
468 return 0;
469 }
470
471 static int h_auth(int argc, unsigned char **argv){
472 struct auth *au, * newau;
473
474 freeauth(conf.authfuncs);
475 conf.authfuncs = NULL;
476 if(!conf.bandlimfunc)conf.bandlimfunc = bandlimitfunc;
477 for(argc--; argc; argc--){
478 for(au = authfuncs; au; au=au->next){
479 if(!strcmp((char *)argv[argc], au->desc)){
480 newau = myalloc(sizeof(struct auth));
481 if(!newau) {
482 return 21;
483 }
484 newau->next = conf.authfuncs;
485 conf.authfuncs = newau;
486 conf.authfuncs->desc = au->desc;
487 conf.authfuncs->authenticate = au->authenticate;
488 conf.authfuncs->authorize = au->authorize;
489 break;
490 }
491 }
492 if(!au) return 1;
493 }
494 conf.authfunc = doauth;
495 return 0;
496 }
497
498 static int h_users(int argc, unsigned char **argv){
499 int j;
500 unsigned char *arg;
501 struct passwords *pwl = NULL;
502
503 for (j = 1; j<argc; j++) {
504 if(!(pwl = myalloc(sizeof(struct passwords)))) {
505 return(21);
506 }
507 memset(pwl, 0, sizeof(struct passwords));
508
509 arg = (unsigned char *)strchr((char *)argv[j], ':');
510 if(!arg||!arg[1]||!arg[2]||arg[3]!=':') {
511 pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
512 pwl->pwtype = SYS;
513 }
514 else {
515 *arg = 0;
516 pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
517
518 if((arg[1] == 'C' && arg[2] == 'L' && (pwl->pwtype = CL)) ||
519 (arg[1] == 'C' && arg[2] == 'R' && (pwl->pwtype = CR)) ||
520 (arg[1] == 'N' && arg[2] == 'T' && (pwl->pwtype = NT)) ||
521 (arg[1] == 'L' && arg[2] == 'M' && (pwl->pwtype = LM))){
522 pwl->password = (unsigned char *)mystrdup((char *)arg+4);
523 }
524 else {
525 pwl->password = (unsigned char *) mystrdup((char *)arg + 1);
526 pwl->pwtype = UN;
527 }
528 if(!pwl->password) return 3;
529 }
530 if(!pwl->user) return 21;
531 pthread_mutex_lock(&pwl_mutex);
532 pwl->next = conf.pwl;
533 conf.pwl = pwl;
534 pthread_mutex_unlock(&pwl_mutex);
535
536
537 }
538 return 0;
539 }
540
541 static int h_maxconn(int argc, unsigned char **argv){
542 conf.maxchild = atoi((char *)argv[1]);
543 if(!conf.maxchild) {
544 return(1);
545 }
546 #ifndef _WIN32
547 {
548 struct rlimit rl;
549 if(!getrlimit(RLIMIT_NOFILE, &rl)){
550 if((conf.maxchild<<1) > rl.rlim_cur)
551 fprintf(stderr, "[line %d] Warning: current open file ulimits are too low (cur: %d/max: %d),"
552 " maxconn requires at least %d for every running service."
553 " Configure ulimits according to system documentation\n",
554 linenum, (int)rl.rlim_cur, (int)rl.rlim_max, (conf.maxchild<<1));
555 }
556 }
557 #endif
558 return 0;
559 }
560
561 static int h_flush(int argc, unsigned char **argv){
562 freeacl(conf.acl);
563 conf.acl = NULL;
564 return 0;
565 }
566
567 /*
568 static int h_flushusers(int argc, unsigned char **argv){
569 freepwl(conf.pwl);
570 conf.pwl = NULL;
571 return 0;
572 }
573 */
574
575 static int h_nserver(int argc, unsigned char **argv){
576 char *str;
577
578 if(numservers < MAXNSERVERS) {
579 if((str = strchr((char *)argv[1], '/')))
580 *str = 0;
581 *SAPORT(&nservers[numservers].addr) = htons(53);
582 if(parsehost(46, argv[1], (struct sockaddr *)&nservers[numservers].addr)) return 1;
583 if(str) {
584 nservers[numservers].usetcp = strstr(str + 1, "tcp")? 1:0;
585 *str = '/';
586 }
587 numservers++;
588
589 }
590 resolvfunc = myresolver;
591 return 0;
592 }
593
594 static int h_authnserver(int argc, unsigned char **argv){
595 char *str;
596
597 if((str = strchr((char *)argv[1], '/')))
598 *str = 0;
599 if(parsehost(46, argv[1], (struct sockaddr *)&authnserver.addr)) return 1;
600 *SAPORT(&authnserver.addr) = htons(53);
601 if(str) {
602 authnserver.usetcp = strstr(str + 1, "tcp")? 1:0;
603 *str = '/';
604 }
605 return 0;
606 }
607
608 static int h_fakeresolve(int argc, unsigned char **argv){
609 resolvfunc = fakeresolver;
610 return 0;
611 }
612
613 static int h_nscache(int argc, unsigned char **argv){
614 int res;
615
616 res = atoi((char *)argv[1]);
617 if(res < 256) {
618 fprintf(stderr, "Invalid NS cache size: %d\n", res);
619 return 1;
620 }
621 if(inithashtable(&dns_table, (unsigned)res)){
622 fprintf(stderr, "Failed to initialize NS cache\n");
623 return 2;
624 }
625 return 0;
626 }
627
628 static int h_parentretries(int argc, unsigned char **argv){
629 int res;
630
631 res = atoi((char *)argv[1]);
632 if(res > 0) conf.parentretries = res;
633 return 0;
634 }
635
636 static int h_nscache6(int argc, unsigned char **argv){
637 int res;
638
639 res = atoi((char *)argv[1]);
640 if(res < 256) {
641 fprintf(stderr, "Invalid NS cache size: %d\n", res);
642 return 1;
643 }
644 if(inithashtable(&dns6_table, (unsigned)res)){
645 fprintf(stderr, "Failed to initialize NS cache\n");
646 return 2;
647 }
648 return 0;
649 }
650
651 static int h_nsrecord(int argc, unsigned char **argv){
652 #ifndef NOIPV6
653 struct sockaddr_in6 sa;
654 #else
655 struct sockaddr_in sa;
656 #endif
657 memset(&sa, 0, sizeof(sa));
658 if(!getip46(46, argv[2], (struct sockaddr *)&sa)) return 1;
659
660 hashadd(*SAFAMILY(&sa)==AF_INET6?&dns6_table:&dns_table, argv[1], SAADDR(&sa), (time_t)0xffffffff);
661 return 0;
662 }
663
664 static int h_dialer(int argc, unsigned char **argv){
665 if(conf.demanddialprog) myfree(conf.demanddialprog);
666 conf.demanddialprog = mystrdup((char *)argv[1]);
667 return 0;
668 }
669
670 static int h_system(int argc, unsigned char **argv){
671 int res;
672
673 if((res = system((char *)argv[1])) == -1){
674 fprintf(stderr, "Failed to start %s\n", argv[1]);
675 return(1);
676 }
677 return 0;
678 }
679
680 static int h_pidfile(int argc, unsigned char **argv){
681 FILE *pidf;
682
683 if(!(pidf = fopen((char *)argv[1], "w"))){
684 fprintf(stderr, "Failed to open pid file %s\n", argv[1]);
685 return(1);
686 }
687 fprintf(pidf,"%u", (unsigned)getpid());
688 fclose(pidf);
689 return 0;
690 }
691
692 static int h_monitor(int argc, unsigned char **argv){
693 struct filemon * fm;
694
695 fm = myalloc(sizeof (struct filemon));
696 if(!fm) return 21;
697 if(stat((char *)argv[1], &fm->sb)){
698 myfree(fm);
699 fprintf(stderr, "Warning: file %s doesn't exist on line %d\n", argv[1], linenum);
700 }
701 else {
702 fm->path = mystrdup((char *)argv[1]);
703 if(!fm->path) return 21;
704 fm->next = conf.fmon;
705 conf.fmon = fm;
706 }
707 return 0;
708 }
709
710 static int h_parent(int argc, unsigned char **argv){
711 struct ace *acl = NULL;
712 struct chain *chains;
713 char * cidr;
714
715 acl = conf.acl;
716 while(acl && acl->next) acl = acl->next;
717 if(!acl || (acl->action && acl->action != 2)) {
718 fprintf(stderr, "Chaining error: last ACL entry was not \"allow\" or \"redirect\" on line %d\n", linenum);
719 return(1);
720 }
721 acl->action = 2;
722
723 chains = myalloc(sizeof(struct chain));
724 if(!chains){
725 return(21);
726 }
727 memset(chains, 0, sizeof(struct chain));
728 chains->weight = (unsigned)atoi((char *)argv[1]);
729 if(chains->weight == 0 || chains->weight >1000) {
730 fprintf(stderr, "Chaining error: bad chain weight %u line %d\n", chains->weight, linenum);
731 return(3);
732 }
733 if(!strcmp((char *)argv[2], "tcp"))chains->type = R_TCP;
734 else if(!strcmp((char *)argv[2], "http"))chains->type = R_HTTP;
735 else if(!strcmp((char *)argv[2], "connect"))chains->type = R_CONNECT;
736 else if(!strcmp((char *)argv[2], "socks4"))chains->type = R_SOCKS4;
737 else if(!strcmp((char *)argv[2], "socks5"))chains->type = R_SOCKS5;
738 else if(!strcmp((char *)argv[2], "connect+"))chains->type = R_CONNECTP;
739 else if(!strcmp((char *)argv[2], "socks4+"))chains->type = R_SOCKS4P;
740 else if(!strcmp((char *)argv[2], "socks5+"))chains->type = R_SOCKS5P;
741 else if(!strcmp((char *)argv[2], "socks4b"))chains->type = R_SOCKS4B;
742 else if(!strcmp((char *)argv[2], "socks5b"))chains->type = R_SOCKS5B;
743 else if(!strcmp((char *)argv[2], "pop3"))chains->type = R_POP3;
744 else if(!strcmp((char *)argv[2], "ftp"))chains->type = R_FTP;
745 else if(!strcmp((char *)argv[2], "admin"))chains->type = R_ADMIN;
746 else if(!strcmp((char *)argv[2], "extip"))chains->type = R_EXTIP;
747 else if(!strcmp((char *)argv[2], "smtp"))chains->type = R_SMTP;
748 else {
749 fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]);
750 return(4);
751 }
752 cidr = strchr(argv[3], '/');
753 if(cidr) *cidr = 0;
754 getip46(46, argv[3], (struct sockaddr *)&chains->addr);
755 chains->exthost = (unsigned char *)mystrdup((char *)argv[3]);
756 if(!chains->exthost) return 21;
757 if(cidr){
758 *cidr = '/';
759 chains->cidr = atoi(cidr + 1);
760 }
761 *SAPORT(&chains->addr) = htons((unsigned short)atoi((char *)argv[4]));
762 if(argc > 5) chains->extuser = (unsigned char *)mystrdup((char *)argv[5]);
763 if(argc > 6) chains->extpass = (unsigned char *)mystrdup((char *)argv[6]);
764 if(!acl->chains) {
765 acl->chains = chains;
766 }
767 else {
768 struct chain *tmpchain;
769
770 for(tmpchain = acl->chains; tmpchain->next; tmpchain = tmpchain->next);
771 tmpchain->next = chains;
772 }
773 return 0;
774
775 }
776
777 static int h_nolog(int argc, unsigned char **argv){
778 struct ace *acl = NULL;
779
780 acl = conf.acl;
781 if(!acl) {
782 fprintf(stderr, "Chaining error: last ACL entry was not \"allow/deny\" on line %d\n", linenum);
783 return(1);
784 }
785 while(acl->next) acl = acl->next;
786 if(argc == 1) acl->nolog = 1;
787 else acl->weight = atoi((char*)argv[1]);
788 return 0;
789 }
790
791 int scanipl(unsigned char *arg, struct iplist *dst){
792 #ifndef NOIPV6
793 struct sockaddr_in6 sa;
794 #else
795 struct sockaddr_in sa;
796 #endif
797 char * slash, *dash;
798 int masklen, addrlen;
799 int res;
800
801 if((slash = strchr((char *)arg, '/'))) *slash = 0;
802 if((dash = strchr((char *)arg,'-'))) *dash = 0;
803
804 if(afdetect(arg) == -1) {
805 if(slash)*slash = '/';
806 if(dash)*dash = '-';
807 return 1;
808 }
809 res = getip46(46, arg, (struct sockaddr *)&sa);
810 if(dash)*dash = '-';
811 if(!res) return 1;
812 memcpy(&dst->ip_from, SAADDR(&sa), SAADDRLEN(&sa));
813 dst->family = *SAFAMILY(&sa);
814 if(dash){
815 if(afdetect(dash+1) == -1) return 1;
816 if(!getip46(46, (unsigned char *)dash+1, (struct sockaddr *)&sa)) return 2;
817 memcpy(&dst->ip_to, SAADDR(&sa), SAADDRLEN(&sa));
818 if(*SAFAMILY(&sa) != dst->family || memcmp(&dst->ip_to, &dst->ip_from, SAADDRLEN(&sa)) < 0) return 3;
819 return 0;
820 }
821 memcpy(&dst->ip_to, &dst->ip_from, SAADDRLEN(&sa));
822 if(slash){
823 *slash = '/';
824 addrlen = SAADDRLEN(&sa);
825 masklen = atoi(slash+1);
826 if(masklen < 0 || masklen > (addrlen*8)) return 4;
827 else {
828 int i, nbytes = masklen / 8, nbits = (8 - (masklen % 8)) % 8;
829
830 for(i = addrlen; i>(nbytes + (nbits > 0)); i--){
831 ((unsigned char *)&dst->ip_from)[i-1] = 0x00;
832 ((unsigned char *)&dst->ip_to)[i-1] = 0xff;
833 }
834 for(;nbits;nbits--){
835 ((unsigned char *)&dst->ip_from)[nbytes] &= ~(0x01<<(nbits-1));
836 ((unsigned char *)&dst->ip_to)[nbytes] |= (0x01<<(nbits-1));
837 }
838 return 0;
839 }
840 }
841 return 0;
842 }
843
844 struct ace * make_ace (int argc, unsigned char ** argv){
845 struct ace * acl;
846 unsigned char *arg;
847 struct iplist *ipl=NULL;
848 struct portlist *portl=NULL;
849 struct userlist *userl=NULL;
850 struct hostname *hostnamel=NULL;
851 int res;
852
853 acl = myalloc(sizeof(struct ace));
854 if(!acl) return acl;
855 memset(acl, 0, sizeof(struct ace));
856 if(argc > 0 && strcmp("*", (char *)argv[0])) {
857 arg = argv[0];
858 arg = (unsigned char *)strtok((char *)arg, ",");
859 do {
860 if(!acl->users) {
861 acl->users = userl = myalloc(sizeof(struct userlist));
862 }
863 else {
864 userl->next = myalloc(sizeof(struct userlist));
865 userl = userl -> next;
866 }
867 if(!userl) {
868 fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
869 return(NULL);
870 }
871 memset(userl, 0, sizeof(struct userlist));
872 userl->user=(unsigned char*)mystrdup((char *)arg);
873 if(!userl->user) return NULL;
874 } while((arg = (unsigned char *)strtok((char *)NULL, ",")));
875 }
876 if(argc > 1 && strcmp("*", (char *)argv[1])) {
877 arg = (unsigned char *)strtok((char *)argv[1], ",");
878 do {
879 if(!acl->src) {
880 acl->src = ipl = myalloc(sizeof(struct iplist));
881 }
882 else {
883 ipl->next = myalloc(sizeof(struct iplist));
884 ipl = ipl -> next;
885 }
886 if(!ipl) {
887 fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
888 return(NULL);
889 }
890 memset(ipl, 0, sizeof(struct iplist));
891 if (scanipl(arg, ipl)) {
892 fprintf(stderr, "Invalid IP, IP range or CIDR, line %d\n", linenum);
893 return(NULL);
894 }
895 } while((arg = (unsigned char *)strtok((char *)NULL, ",")));
896 }
897 if(argc > 2 && strcmp("*", (char *)argv[2])) {
898 arg = (unsigned char *)strtok((char *)argv[2], ",");
899 do {
900 int arglen;
901 unsigned char *pattern;
902 struct iplist tmpip={NULL};
903
904 arglen = (int)strlen((char *)arg);
905 if(scanipl(arg, &tmpip)){
906 if(!arglen) continue;
907 if(!acl->dstnames) {
908 acl->dstnames = hostnamel = myalloc(sizeof(struct hostname));
909 }
910 else {
911 hostnamel->next = myalloc(sizeof(struct hostname));
912 hostnamel = hostnamel -> next;
913 }
914 if(!hostnamel){
915 fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
916 return(NULL);
917 }
918 memset(hostnamel, 0, sizeof(struct hostname));
919 hostnamel->matchtype = 3;
920 pattern = arg;
921 if(pattern[arglen-1] == '*'){
922 arglen --;
923 pattern[arglen] = 0;
924 hostnamel->matchtype ^= MATCHEND;
925 }
926 if(pattern[0] == '*'){
927 pattern++;
928 arglen--;
929 hostnamel->matchtype ^= MATCHBEGIN;
930 }
931 hostnamel->name = (unsigned char *) mystrdup( (char *)pattern);
932 if(!hostnamel->name) {
933 fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
934 return(NULL);
935 }
936 }
937 else {
938
939 if(!acl->dst) {
940 acl->dst = ipl = myalloc(sizeof(struct iplist));
941 }
942 else {
943 ipl->next = myalloc(sizeof(struct iplist));
944 ipl = ipl -> next;
945 }
946 if(!ipl) {
947 fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
948 return(NULL);
949 }
950 *ipl = tmpip;
951 }
952 }while((arg = (unsigned char *)strtok((char *)NULL, ",")));
953 }
954 if(argc > 3 && strcmp("*", (char *)argv[3])) {
955 arg = (unsigned char *)strtok((char *)argv[3], ",");
956 do {
957 if(!acl->ports) {
958 acl->ports = portl = myalloc(sizeof(struct portlist));
959 }
960 else {
961 portl->next = myalloc(sizeof(struct portlist));
962 portl = portl -> next;
963 }
964 if(!portl) {
965 fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
966 return(NULL);
967 }
968 memset(portl, 0, sizeof(struct portlist));
969 res = sscanf((char *)arg, "%hu-%hu", &portl->startport, &portl->endport);
970 if(res < 1) {
971 fprintf(stderr, "Invalid port or port range, line %d\n", linenum);
972 return(NULL);
973 }
974 if (res == 1) portl->endport = portl->startport;
975 } while((arg = (unsigned char *)strtok((char *)NULL, ",")));
976 }
977 if(argc > 4 && strcmp("*", (char *)argv[4])) {
978 arg = (unsigned char *)strtok((char *)argv[4], ",");
979 do {
980 if(!strcmp((char *)arg, "CONNECT")){
981 acl->operation |= CONNECT;
982 }
983 else if(!strcmp((char *)arg, "BIND")){
984 acl->operation |= BIND;
985 }
986 else if(!strcmp((char *)arg, "UDPASSOC")){
987 acl->operation |= UDPASSOC;
988 }
989 else if(!strcmp((char *)arg, "ICMPASSOC")){
990 acl->operation |= ICMPASSOC;
991 }
992 else if(!strcmp((char *)arg, "HTTP_GET")){
993 acl->operation |= HTTP_GET;
994 }
995 else if(!strcmp((char *)arg, "HTTP_PUT")){
996 acl->operation |= HTTP_PUT;
997 }
998 else if(!strcmp((char *)arg, "HTTP_POST")){
999 acl->operation |= HTTP_POST;
1000 }
1001 else if(!strcmp((char *)arg, "HTTP_HEAD")){
1002 acl->operation |= HTTP_HEAD;
1003 }
1004 else if(!strcmp((char *)arg, "HTTP_OTHER")){
1005 acl->operation |= HTTP_OTHER;
1006 }
1007 else if(!strcmp((char *)arg, "HTTP_CONNECT")){
1008 acl->operation |= HTTP_CONNECT;
1009 }
1010 else if(!strcmp((char *)arg, "HTTP")){
1011 acl->operation |= HTTP;
1012 }
1013 else if(!strcmp((char *)arg, "HTTPS")){
1014 acl->operation |= HTTPS;
1015 }
1016 else if(!strcmp((char *)arg, "FTP_GET")){
1017 acl->operation |= FTP_GET;
1018 }
1019 else if(!strcmp((char *)arg, "FTP_PUT")){
1020 acl->operation |= FTP_PUT;
1021 }
1022 else if(!strcmp((char *)arg, "FTP_LIST")){
1023 acl->operation |= FTP_LIST;
1024 }
1025 else if(!strcmp((char *)arg, "FTP_DATA")){
1026 acl->operation |= FTP_DATA;
1027 }
1028 else if(!strcmp((char *)arg, "FTP")){
1029 acl->operation |= FTP;
1030 }
1031 else if(!strcmp((char *)arg, "ADMIN")){
1032 acl->operation |= ADMIN;
1033 }
1034 else if(!strcmp((char *)arg, "DNSRESOLVE")){
1035 acl->operation |= DNSRESOLVE;
1036 }
1037 else {
1038 fprintf(stderr, "Unknown operation type: %s line %d\n", arg, linenum);
1039 return(NULL);
1040 }
1041 } while((arg = (unsigned char *)strtok((char *)NULL, ",")));
1042 }
1043 if(argc > 5){
1044 for(arg = argv[5]; *arg;){
1045 int val, val1;
1046
1047 if(!isnumber(*arg)){
1048 arg++;
1049 continue;
1050 }
1051 val1 = val = (*arg - '0');
1052 arg++;
1053 if(*arg == '-' && isnumber(*(arg+1)) && (*(arg+1) - '0') > val) {
1054 val1 = (*(arg+1) - '0');
1055 arg+=2;
1056 }
1057 for(; val<=val1; val++) acl->wdays |= (1 << (val % 7));
1058 }
1059
1060 }
1061 if(argc > 6){
1062 for(arg = argv[6]; strlen((char *)arg) >= 17 &&
1063 isdigit(arg[0]) &&
1064 isdigit(arg[1]) &&
1065 isdigit(arg[3]) &&
1066 isdigit(arg[4]) &&
1067 isdigit(arg[6]) &&
1068 isdigit(arg[7]) &&
1069 isdigit(arg[9]) &&
1070 isdigit(arg[10]) &&
1071 isdigit(arg[12]) &&
1072 isdigit(arg[13]) &&
1073 isdigit(arg[15]) &&
1074 isdigit(arg[16])
1075 ; arg+=18){
1076
1077 int t1, t2;
1078 struct period *sp;
1079
1080 t1 = (arg[0] - '0') * 10 + (arg[1] - '0');
1081 t1 = (t1 * 60) + (arg[3] - '0') * 10 + (arg[4] - '0');
1082 t1 = (t1 * 60) + (arg[6] - '0') * 10 + (arg[7] - '0');
1083 t2 = (arg[9] - '0') * 10 + (arg[10] - '0');
1084 t2 = (t2 * 60) + (arg[12] - '0') * 10 + (arg[13] - '0');
1085 t2 = (t2 * 60) + (arg[15] - '0') * 10 + (arg[16] - '0');
1086 if(t2 < t1) break;
1087 sp = myalloc(sizeof(struct period));
1088 if(sp){
1089 sp->fromtime = t1;
1090 sp->totime = t2;
1091 sp->next = acl->periods;
1092 acl->periods = sp;
1093 }
1094 if(arg[17]!=',') break;
1095 }
1096 }
1097 if (argc > 7){
1098 acl->weight = atoi((char *)argv[7]);
1099 }
1100
1101 return acl;
1102 }
1103
1104
1105 static int h_ace(int argc, unsigned char **argv){
1106 int res = 0;
1107 int offset = 0;
1108 struct ace *acl = NULL;
1109 struct bandlim * nbl;
1110 struct trafcount * tl;
1111 struct connlim * ncl;
1112
1113 if(!strcmp((char *)argv[0], "allow")){
1114 res = ALLOW;
1115 }
1116 else if(!strcmp((char *)argv[0], "deny")){
1117 res = DENY;
1118 }
1119 else if(!strcmp((char *)argv[0], "redirect")){
1120 res = REDIRECT;
1121 offset = 2;
1122 }
1123 else if(!strcmp((char *)argv[0], "bandlimin")||!strcmp((char *)argv[0], "bandlimout")){
1124 res = BANDLIM;
1125 offset = 1;
1126 }
1127 else if(!strcmp((char *)argv[0], "nobandlimin")||!strcmp((char *)argv[0], "nobandlimout")){
1128 res = NOBANDLIM;
1129 }
1130 else if(!strcmp((char *)argv[0], "countin")){
1131 res = COUNTIN;
1132 offset = 3;
1133 }
1134 else if(!strcmp((char *)argv[0], "nocountin")){
1135 res = NOCOUNTIN;
1136 }
1137 else if(!strcmp((char *)argv[0], "countout")){
1138 res = COUNTOUT;
1139 offset = 3;
1140 }
1141 else if(!strcmp((char *)argv[0], "nocountout")){
1142 res = NOCOUNTOUT;
1143 }
1144 else if(!strcmp((char *)argv[0], "countall")){
1145 res = COUNTALL;
1146 offset = 3;
1147 }
1148 else if(!strcmp((char *)argv[0], "nocountall")){
1149 res = NOCOUNTALL;
1150 }
1151 else if(!strcmp((char *)argv[0], "connlim")){
1152 res = CONNLIM;
1153 offset = 2;
1154 }
1155 else if(!strcmp((char *)argv[0], "noconnlim")){
1156 res = NOCONNLIM;
1157 }
1158 acl = make_ace(argc - (offset+1), argv + (offset + 1));
1159 if(!acl) {
1160 fprintf(stderr, "Unable to parse ACL entry, line %d\n", linenum);
1161 return(1);
1162 }
1163 acl->action = res;
1164 switch(acl->action){
1165 case REDIRECT:
1166 acl->chains = myalloc(sizeof(struct chain));
1167 if(!acl->chains) {
1168 freeacl(acl);
1169 return(21);
1170 }
1171 memset(acl->chains, 0, sizeof(struct chain));
1172 acl->chains->type = R_HTTP;
1173 if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) return 5;
1174 *SAPORT(&acl->chains->addr) = htons((unsigned short)atoi((char *)argv[2]));
1175 acl->chains->weight = 1000;
1176 case ALLOW:
1177 case DENY:
1178 if(!conf.acl){
1179 conf.acl = acl;
1180 }
1181 else {
1182 struct ace * acei;
1183
1184 for(acei = conf.acl; acei->next; acei = acei->next);
1185 acei->next = acl;
1186 }
1187 break;
1188 case CONNLIM:
1189 case NOCONNLIM:
1190 ncl = myalloc(sizeof(struct connlim));
1191 if(!ncl) {
1192 freeacl(acl);
1193 return(21);
1194 }
1195 memset(ncl, 0, sizeof(struct connlim));
1196 ncl->ace = acl;
1197 if(acl->action == CONNLIM) {
1198 sscanf((char *)argv[1], "%u", &ncl->rate);
1199 sscanf((char *)argv[2], "%u", &ncl->period);
1200 }
1201 pthread_mutex_lock(&connlim_mutex);
1202 if(!conf.connlimiter){
1203 conf.connlimiter = ncl;
1204 }
1205 else {
1206 struct connlim * cli;
1207
1208 for(cli = conf.connlimiter; cli->next; cli = cli->next);
1209 cli->next = ncl;
1210 }
1211 pthread_mutex_unlock(&connlim_mutex);
1212 break;
1213
1214 case BANDLIM:
1215 case NOBANDLIM:
1216
1217 nbl = myalloc(sizeof(struct bandlim));
1218 if(!nbl) {
1219 freeacl(acl);
1220 return(21);
1221 }
1222 memset(nbl, 0, sizeof(struct bandlim));
1223 nbl->ace = acl;
1224 if(acl->action == BANDLIM) {
1225 sscanf((char *)argv[1], "%u", &nbl->rate);
1226 if(nbl->rate < 300) {
1227 myfree(nbl);
1228 freeacl(acl);
1229 fprintf(stderr, "Wrong bandwidth specified, line %d\n", linenum);
1230 return(4);
1231 }
1232 }
1233 pthread_mutex_lock(&bandlim_mutex);
1234 if(!strcmp((char *)argv[0], "bandlimin") || !strcmp((char *)argv[0], "nobandlimin")){
1235 if(!conf.bandlimiter){
1236 conf.bandlimiter = nbl;
1237 }
1238 else {
1239 struct bandlim * bli;
1240
1241 for(bli = conf.bandlimiter; bli->next; bli = bli->next);
1242 bli->next = nbl;
1243 }
1244 }
1245 else {
1246 if(!conf.bandlimiterout){
1247 conf.bandlimiterout = nbl;
1248 }
1249 else {
1250 struct bandlim * bli;
1251
1252 for(bli = conf.bandlimiterout; bli->next; bli = bli->next);
1253 bli->next = nbl;
1254 }
1255 }
1256 conf.bandlimver++;
1257 pthread_mutex_unlock(&bandlim_mutex);
1258 break;
1259
1260 case COUNTIN:
1261 case NOCOUNTIN:
1262 case COUNTOUT:
1263 case NOCOUNTOUT:
1264 case COUNTALL:
1265 case NOCOUNTALL:
1266 if(!conf.trafcountfunc) conf.trafcountfunc = trafcountfunc;
1267 tl = myalloc(sizeof(struct trafcount));
1268 if(!tl) {
1269 freeacl(acl);
1270 return(21);
1271 }
1272 memset(tl, 0, sizeof(struct trafcount));
1273 tl->ace = acl;
1274
1275 if((acl->action == COUNTIN)||(acl->action == COUNTOUT)||(acl->action == COUNTALL)) {
1276 unsigned long lim;
1277
1278 tl->comment = ( char *)argv[1];
1279 while(isdigit(*tl->comment))tl->comment++;
1280 if(*tl->comment== '/')tl->comment++;
1281 tl->comment = mystrdup(tl->comment);
1282
1283 sscanf((char *)argv[1], "%u", &tl->number);
1284 sscanf((char *)argv[3], "%lu", &lim);
1285 tl->type = getrotate(*argv[2]);
1286 tl->traflim64 = ((uint64_t)lim)*(1024*1024);
1287 if(!tl->traflim64) {
1288 myfree(tl);
1289 freeacl(acl);
1290 fprintf(stderr, "Wrong traffic limit specified, line %d\n", linenum);
1291 return(6);
1292 }
1293 if(tl->number != 0 && conf.counterd >= 0) {
1294 lseek(conf.counterd,
1295 sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record),
1296 SEEK_SET);
1297 memset(&crecord, 0, sizeof(struct counter_record));
1298 read(conf.counterd, &crecord, sizeof(struct counter_record));
1299 tl->traf64 = crecord.traf64;
1300 tl->cleared = crecord.cleared;
1301 tl->updated = crecord.updated;
1302 if(tl->cleared < 0 || tl->cleared >= MAX_COUNTER_TIME || tl->updated < 0 || tl->updated >= MAX_COUNTER_TIME){
1303 fprintf(stderr, "Invalid, incompatible or corrupted counter file.\n");
1304 return(6);
1305 }
1306 }
1307 }
1308 pthread_mutex_lock(&tc_mutex);
1309 if(!conf.trafcounter){
1310 conf.trafcounter = tl;
1311 }
1312 else {
1313 struct trafcount * ntl;
1314
1315 for(ntl = conf.trafcounter; ntl->next; ntl = ntl->next);
1316 ntl->next = tl;
1317 }
1318 pthread_mutex_unlock(&tc_mutex);
1319
1320 }
1321 return 0;
1322 }
1323
1324 static int h_logdump(int argc, unsigned char **argv){
1325 conf.logdumpsrv = (unsigned) atoi((char *) *(argv + 1));
1326 if(argc > 2) conf.logdumpcli = (unsigned) atoi((char *) *(argv + 2));
1327 return 0;
1328 }
1329
1330
1331 static int h_filtermaxsize(int argc, unsigned char **argv){
1332 conf.filtermaxsize = atoi((char *) *(argv + 1));
1333 return 0;
1334 }
1335
1336 static int h_delimchar(int argc, unsigned char **argv){
1337 conf.delimchar = *argv[1];
1338 return 0;
1339 }
1340
1341
1342 #ifndef NORADIUS
1343 static int h_radius(int argc, unsigned char **argv){
1344 unsigned short port;
1345
1346 /*
1347 int oldrad;
1348 #ifdef NOIPV6
1349 struct sockaddr_in bindaddr;
1350 #else
1351 struct sockaddr_in6 bindaddr;
1352 #endif
1353
1354 oldrad = nradservers;
1355 nradservers = 0;
1356 for(; oldrad; oldrad--){
1357 if(radiuslist[oldrad].logsock >= 0) so._closesocket(radiuslist[oldrad].logsock);
1358 radiuslist[oldrad].logsock = -1;
1359 }
1360 */
1361 memset(radiuslist, 0, sizeof(radiuslist));
1362 if(strlen(argv[1]) > 63) argv[1][63] = 0;
1363 strcpy(radiussecret, argv[1]);
1364 for( nradservers=0; nradservers < MAXRADIUS && nradservers < argc -2; nradservers++){
1365 char *s = 0;
1366 if((s=strchr(argv[nradservers + 2], '/'))){
1367 *s = 0;
1368 s++;
1369 }
1370 if( !getip46(46, argv[nradservers + 2], (struct sockaddr *)&radiuslist[nradservers].authaddr)) return 1;
1371 if( s && !getip46(46, s+1, (struct sockaddr *)&radiuslist[nradservers].localaddr)) return 2;
1372 if(!*SAPORT(&radiuslist[nradservers].authaddr))*SAPORT(&radiuslist[nradservers].authaddr) = htons(1812);
1373 port = ntohs(*SAPORT(&radiuslist[nradservers].authaddr));
1374 radiuslist[nradservers].logaddr = radiuslist[nradservers].authaddr;
1375 *SAPORT(&radiuslist[nradservers].logaddr) = htons(port+1);
1376 /*
1377 bindaddr = radiuslist[nradservers].localaddr;
1378 if ((radiuslist[nradservers].logsock = so._socket(SASOCK(&radiuslist[nradservers].logaddr), SOCK_DGRAM, 0)) < 0) return 2;
1379 if (so._bind(radiuslist[nradservers].logsock, (struct sockaddr *)&bindaddr, SASIZE(&bindaddr))) return 3;
1380 */
1381 }
1382 return 0;
1383 }
1384 #endif
1385 static int h_authcache(int argc, unsigned char **argv){
1386 conf.authcachetype = 0;
1387 if(strstr((char *) *(argv + 1), "ip")) conf.authcachetype |= 1;
1388 if(strstr((char *) *(argv + 1), "user")) conf.authcachetype |= 2;
1389 if(strstr((char *) *(argv + 1), "pass")) conf.authcachetype |= 4;
1390 if(strstr((char *) *(argv + 1), "limit")) conf.authcachetype |= 8;
1391 if(strstr((char *) *(argv + 1), "acl")) conf.authcachetype |= 16;
1392 if(strstr((char *) *(argv + 1), "ext")) conf.authcachetype |= 32;
1393 if(argc > 2) conf.authcachetime = (unsigned) atoi((char *) *(argv + 2));
1394 if(!conf.authcachetype) conf.authcachetype = 6;
1395 if(!conf.authcachetime) conf.authcachetime = 600;
1396 return 0;
1397 }
1398
1399 static int h_plugin(int argc, unsigned char **argv){
1400 #ifdef NOPLUGINS
1401 return 999;
1402 #else
1403 #ifdef _WIN32
1404 HINSTANCE hi;
1405 FARPROC fp;
1406
1407 #ifdef _WINCE
1408 hi = LoadLibraryW((LPCWSTR)CEToUnicode(argv[1]));
1409 #else
1410 hi = LoadLibrary((char *)argv[1]);
1411 #endif
1412 if(!hi) {
1413 fprintf(stderr, "Failed to load %s, code %d\n", argv[1], (int)GetLastError());
1414 return 1;
1415 }
1416 #ifdef _WINCE
1417 fp = GetProcAddressW(hi, (LPCWSTR)CEToUnicode(argv[2]));
1418 #else
1419 fp = GetProcAddress(hi, (char *)argv[2]);
1420 #endif
1421 if(!fp) {
1422 printf("%s not found in %s, code: %d\n", argv[2], argv[1], (int)GetLastError());
1423 return 2;
1424 }
1425 return (*(PLUGINFUNC)fp)(&pluginlink, argc - 2, (char **)argv + 2);
1426 #else
1427 void *hi, *fp;
1428 hi = dlopen((char *)argv[1], RTLD_LAZY);
1429 if(!hi) return 1;
1430 fp = dlsym(hi, (char *)argv[2]);
1431 if(!fp) return 2;
1432 return (*(PLUGINFUNC)fp)(&pluginlink, argc - 2, (char **)argv + 2);
1433 #endif
1434 #endif
1435 }
1436
1437 #ifndef _WIN32
1438
1439 uid_t strtouid(unsigned char *str){
1440 uid_t res = 0;
1441
1442 if(!isnumber(*(char *)str)){
1443 struct passwd *pw;
1444 pw = getpwnam((char *)str);
1445 if(pw) res = pw->pw_uid;
1446 }
1447 else res = atoi((char *)str);
1448 return res;
1449 }
1450
1451
1452 static int h_setuid(int argc, unsigned char **argv){
1453 uid_t res = 0;
1454 res = strtouid(argv[1]);
1455 if(!res || setreuid(res,res)) {
1456 fprintf(stderr, "Unable to set uid %d", res);
1457 return(1);
1458 }
1459 return 0;
1460 }
1461
1462 gid_t strtogid(unsigned char *str){
1463 gid_t res = 0;
1464
1465 if(!isnumber(*(char *)str)){
1466 struct group *gr;
1467 gr = getgrnam((char *)str);
1468 if(gr) res = gr->gr_gid;
1469 }
1470 else res = atoi((char *)str);
1471 return res;
1472 }
1473
1474 static int h_setgid(int argc, unsigned char **argv){
1475 gid_t res = 0;
1476
1477 res = strtogid(argv[1]);
1478 if(!res || setregid(res,res)) {
1479 fprintf(stderr, "Unable to set gid %d", res);
1480 return(1);
1481 }
1482 return 0;
1483 }
1484
1485
1486 static int h_chroot(int argc, unsigned char **argv){
1487 uid_t uid = 0;
1488 gid_t gid = 0;
1489 if(argc > 2) {
1490 uid = strtouid(argv[2]);
1491 if(!uid){
1492 fprintf(stderr, "Unable to resolve uid %s", argv[2]);
1493 return(2);
1494 }
1495 }
1496 if(argc > 3) {
1497 gid = strtogid(argv[3]);
1498 if(!gid){
1499 fprintf(stderr, "Unable to resolve gid %s", argv[3]);
1500 return(3);
1501 }
1502 }
1503 if(!chrootp){
1504 char *p;
1505 if(chroot((char *)argv[1])) {
1506 fprintf(stderr, "Unable to chroot %s", argv[1]);
1507 return(1);
1508 }
1509 p = (char *)argv[1] + strlen((char *)argv[1]) ;
1510 while (p > (char *)argv[1] && p[-1] == '/'){
1511 p--;
1512 *p = 0;
1513 }
1514 chrootp = mystrdup((char *)argv[1]);
1515 if(!chrootp) return 21;
1516 }
1517 if (gid && setregid(gid,gid)) {
1518 fprintf(stderr, "Unable to set gid %d", (int)gid);
1519 return(4);
1520 }
1521 if (uid && setreuid(uid,uid)) {
1522 fprintf(stderr, "Unable to set uid %d", (int)uid);
1523 return(5);
1524 }
1525 chdir("/");
1526 return 0;
1527 }
1528 #endif
1529
1530
1531 struct commands specificcommands[]={
1532 #ifndef _WIN32
1533 {specificcommands+1, "setuid", h_setuid, 2, 2},
1534 {specificcommands+2, "setgid", h_setgid, 2, 2},
1535 {specificcommands+3, "chroot", h_chroot, 2, 4},
1536 #endif
1537 {NULL, "", h_noop, 1, 0}
1538 };
1539
1540 struct commands commandhandlers[]={
1541 {commandhandlers+1, "", h_noop, 1, 0},
1542 {commandhandlers+2, "proxy", h_proxy, 1, 0},
1543 {commandhandlers+3, "pop3p", h_proxy, 1, 0},
1544 {commandhandlers+4, "ftppr", h_proxy, 1, 0},
1545 {commandhandlers+5, "socks", h_proxy, 1, 0},
1546 {commandhandlers+6, "tcppm", h_proxy, 4, 0},
1547 {commandhandlers+7, "udppm", h_proxy, 4, 0},
1548 {commandhandlers+8, "admin", h_proxy, 1, 0},
1549 {commandhandlers+9, "dnspr", h_proxy, 1, 0},
1550 {commandhandlers+10, "internal", h_internal, 2, 2},
1551 {commandhandlers+11, "external", h_external, 2, 2},
1552 {commandhandlers+12, "log", h_log, 1, 0},
1553 {commandhandlers+13, "service", h_service, 1, 1},
1554 {commandhandlers+14, "daemon", h_daemon, 1, 1},
1555 {commandhandlers+15, "config", h_config, 2, 2},
1556 {commandhandlers+16, "include", h_include, 2, 2},
1557 {commandhandlers+17, "archiver", h_archiver, 3, 0},
1558 {commandhandlers+18, "counter", h_counter, 2, 4},
1559 {commandhandlers+19, "rotate", h_rotate, 2, 2},
1560 {commandhandlers+20, "logformat", h_logformat, 2, 2},
1561 {commandhandlers+21, "timeouts", h_timeouts, 2, 0},
1562 {commandhandlers+22, "auth", h_auth, 2, 0},
1563 {commandhandlers+23, "users", h_users, 1, 0},
1564 {commandhandlers+24, "maxconn", h_maxconn, 2, 2},
1565 {commandhandlers+25, "flush", h_flush, 1, 1},
1566 {commandhandlers+26, "nserver", h_nserver, 2, 2},
1567 {commandhandlers+27, "fakeresolve", h_fakeresolve, 1, 1},
1568 {commandhandlers+28, "nscache", h_nscache, 2, 2},
1569 {commandhandlers+29, "nscache6", h_nscache6, 2, 2},
1570 {commandhandlers+30, "nsrecord", h_nsrecord, 3, 3},
1571 {commandhandlers+31, "dialer", h_dialer, 2, 2},
1572 {commandhandlers+32, "system", h_system, 2, 2},
1573 {commandhandlers+33, "pidfile", h_pidfile, 2, 2},
1574 {commandhandlers+34, "monitor", h_monitor, 2, 2},
1575 {commandhandlers+35, "parent", h_parent, 5, 0},
1576 {commandhandlers+36, "allow", h_ace, 1, 0},
1577 {commandhandlers+37, "deny", h_ace, 1, 0},
1578 {commandhandlers+38, "redirect", h_ace, 3, 0},
1579 {commandhandlers+39, "bandlimin", h_ace, 2, 0},
1580 {commandhandlers+40, "bandlimout", h_ace, 2, 0},
1581 {commandhandlers+41, "nobandlimin", h_ace, 1, 0},
1582 {commandhandlers+42, "nobandlimout", h_ace, 1, 0},
1583 {commandhandlers+43, "countin", h_ace, 4, 0},
1584 {commandhandlers+44, "nocountin", h_ace, 1, 0},
1585 {commandhandlers+45, "countout", h_ace, 4, 0},
1586 {commandhandlers+46, "nocountout", h_ace, 1, 0},
1587 {commandhandlers+47, "countall", h_ace, 4, 0},
1588 {commandhandlers+48, "nocountall", h_ace, 1, 0},
1589 {commandhandlers+49, "connlim", h_ace, 4, 0},
1590 {commandhandlers+50, "noconnlim", h_ace, 1, 0},
1591 {commandhandlers+51, "plugin", h_plugin, 3, 0},
1592 {commandhandlers+52, "logdump", h_logdump, 2, 3},
1593 {commandhandlers+53, "filtermaxsize", h_filtermaxsize, 2, 2},
1594 {commandhandlers+54, "nolog", h_nolog, 1, 1},
1595 {commandhandlers+55, "weight", h_nolog, 2, 2},
1596 {commandhandlers+56, "authcache", h_authcache, 2, 3},
1597 {commandhandlers+57, "smtpp", h_proxy, 1, 0},
1598 {commandhandlers+58, "delimchar",h_delimchar, 2, 2},
1599 {commandhandlers+59, "authnserver", h_authnserver, 2, 2},
1600 {commandhandlers+60, "stacksize", h_stacksize, 2, 2},
1601 {commandhandlers+61, "force", h_force, 1, 1},
1602 {commandhandlers+62, "noforce", h_noforce, 1, 1},
1603 {commandhandlers+63, "parentretries", h_parentretries, 2, 2},
1604 #ifndef NORADIUS
1605 {commandhandlers+64, "radius", h_radius, 3, 0},
1606 #endif
1607 {specificcommands, "", h_noop, 1, 0}
1608 };
1609
1610 int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize){
1611 #define buf (*buff)
1612 int argc = 0;
1613 int space = 1;
1614 int comment = 0;
1615 unsigned char * incbegin = 0;
1616 int fd;
1617 int res, len;
1618 unsigned char *str1;
1619
1620 for(;;str++){
1621 if(*str == '\"'){
1622 str1 = str;
1623 do {
1624 *str1 = *(str1 + 1);
1625 }while(*(str1++));
1626 if(!comment || *str != '\"'){
1627 comment = !comment;
1628 }
1629 }
1630 switch(*str){
1631 case '\0':
1632 if(comment) return -1;
1633 argm[argc] = 0;
1634 return argc;
1635 case '$':
1636 if(comment){
1637 if(space){
1638 argm[argc++] = str;
1639 if(argc >= nitems) return argc;
1640 space = 0;
1641 }
1642 }
1643 else if(!included){
1644 incbegin = str;
1645 *str = 0;
1646 }
1647 break;
1648 case '\r':
1649 case '\n':
1650 case '\t':
1651 case ' ':
1652 if(!comment){
1653 *str = 0;
1654 space = 1;
1655 if(incbegin){
1656 argc--;
1657 if((fd = open((char *)incbegin+1, O_RDONLY)) <= 0){
1658 fprintf(stderr, "Failed to open %s\n", incbegin+1);
1659 break;
1660 }
1661 if((*bufsize - *inbuf) <STRINGBUF){
1662 *bufsize += STRINGBUF;
1663 if(!(buf = myrealloc(buf, *bufsize))){
1664 fprintf(stderr, "Failed to allocate memory for %s\n", incbegin+1);
1665 close(fd);
1666 break;
1667 }
1668 }
1669 len = 0;
1670 if(argm[argc]!=(incbegin+1)) {
1671 len = (int)strlen((char *)argm[argc]);
1672 memmove(buf+*inbuf, argm[argc], len);
1673 }
1674 if((res = read(fd, buf+*inbuf+len, STRINGBUF-(1+len))) <= 0) {
1675 perror((char *)incbegin+1);
1676 close(fd);
1677 break;
1678 }
1679 close(fd);
1680 buf[*inbuf+res+len] = 0;
1681 incbegin = buf + *inbuf;
1682 (*inbuf) += (res + len + 1);
1683 included++;
1684 argc+=parsestr(incbegin, argm + argc, nitems - argc, buff, inbuf, bufsize);
1685 included--;
1686 incbegin = NULL;
1687
1688 }
1689 break;
1690 }
1691 default:
1692 if(space) {
1693 if(comment && *str == '\"' && str[1] != '\"'){
1694 str++;
1695 comment = 0;
1696 }
1697 argm[argc++] = str;
1698 if(argc >= nitems) return argc;
1699 space = 0;
1700 }
1701 }
1702 }
1703 #undef buf
1704 }
1705
1706
1707 int readconfig(FILE * fp){
1708 unsigned char ** argv = NULL;
1709 unsigned char * buf = NULL;
1710 int bufsize = STRINGBUF*2;
1711 int inbuf = 0;
1712 int argc;
1713 struct commands * cm;
1714 int res = 0;
1715
1716 if( !(buf = myalloc(bufsize)) || ! (argv = myalloc((NPARAMS + 1) * sizeof(unsigned char *))) ) {
1717 fprintf(stderr, "No memory for configuration");
1718 return(10);
1719 }
1720 for (linenum = 1; fgets((char *)buf, STRINGBUF, fp); linenum++){
1721 if(!*buf || isspace(*buf) || (*buf) == '#')continue;
1722
1723 inbuf = (int)(strlen((char *)buf) + 1);
1724 argc = parsestr (buf, argv, NPARAMS-1, &buf, &inbuf, &bufsize);
1725 if(argc < 1) {
1726 fprintf(stderr, "Parse error line %d\n", linenum);
1727 return(11);
1728 }
1729 argv[argc] = NULL;
1730 if(!strcmp((char *)argv[0], "end") && argc == 1) {
1731 break;
1732 }
1733 else if(!strcmp((char *)argv[0], "writable") && argc == 1) {
1734 if(!writable){
1735 writable = freopen(curconf, "r+", fp);
1736 if(!writable){
1737 fprintf(stderr, "Unable to reopen config for writing: %s\n", curconf);
1738 return 1;
1739 }
1740 }
1741 continue;
1742 }
1743
1744 res = 1;
1745 for(cm = commandhandlers; cm; cm = cm->next){
1746 if(!strcmp((char *)argv[0], (char *)cm->command) && argc >= cm->minargs && (!cm->maxargs || argc <= cm->maxargs)){
1747 res = (*cm->handler)(argc, argv);
1748 if(res > 0){
1749 fprintf(stderr, "Command: '%s' failed with code %d, line %d\n", argv[0], res, linenum);
1750 return(linenum);
1751 }
1752 if(!res) break;
1753 }
1754 }
1755 if(res != 1)continue;
1756 fprintf(stderr, "Unknown command: '%s' line %d\n", argv[0], linenum);
1757 return(linenum);
1758 }
1759 myfree(buf);
1760 myfree(argv);
1761 return 0;
1762
1763 }
1764
1765
1766
1767 void freepwl(struct passwords *pwl){
1768 for(; pwl; pwl = (struct passwords *)itfree(pwl, pwl->next)){
1769 if(pwl->user)myfree(pwl->user);
1770 if(pwl->password)myfree(pwl->password);
1771 }
1772 }
1773
1774
1775 void freeconf(struct extparam *confp){
1776 struct bandlim * bl;
1777 struct bandlim * blout;
1778 struct connlim * cl;
1779 struct trafcount * tc;
1780 struct passwords *pw;
1781 struct ace *acl;
1782 struct filemon *fm;
1783 int counterd, archiverc;
1784 unsigned char *logname, *logtarget;
1785 unsigned char **archiver;
1786 unsigned char * logformat;
1787
1788 int i;
1789
1790
1791
1792
1793 pthread_mutex_lock(&tc_mutex);
1794 confp->trafcountfunc = NULL;
1795 tc = confp->trafcounter;
1796 confp->trafcounter = NULL;
1797 counterd = confp->counterd;
1798 confp->counterd = -1;
1799 confp->countertype = NONE;
1800 pthread_mutex_unlock(&tc_mutex);
1801
1802 pthread_mutex_lock(&bandlim_mutex);
1803 bl = confp->bandlimiter;
1804 blout = confp->bandlimiterout;
1805 confp->bandlimiter = NULL;
1806 confp->bandlimiterout = NULL;
1807 confp->bandlimfunc = NULL;
1808 confp->bandlimver++;
1809 pthread_mutex_unlock(&bandlim_mutex);
1810 pthread_mutex_lock(&connlim_mutex);
1811 cl = confp->connlimiter;
1812 confp->connlimiter = NULL;
1813 pthread_mutex_unlock(&connlim_mutex);
1814
1815 pthread_mutex_lock(&pwl_mutex);
1816 pw = confp->pwl;
1817 confp->pwl = NULL;
1818 pthread_mutex_unlock(&pwl_mutex);
1819
1820
1821 /*
1822 logtarget = confp->logtarget;
1823 confp->logtarget = NULL;
1824 logname = confp->logname;
1825 confp->logname = NULL;
1826 */
1827 confp->logfunc = lognone;
1828 logformat = confp->logformat;
1829 confp->logformat = NULL;
1830 confp->rotate = 0;
1831 confp->logtype = NONE;
1832 confp->logtime = confp->time = 0;
1833
1834 archiverc = confp->archiverc;
1835 confp->archiverc = 0;
1836 archiver = confp->archiver;
1837 confp->archiver = NULL;
1838 fm = confp->fmon;
1839 confp->fmon = NULL;
1840 confp->bandlimfunc = NULL;
1841 memset(&confp->intsa, 0, sizeof(confp->intsa));
1842 memset(&confp->extsa, 0, sizeof(confp->extsa));
1843 #ifndef NOIPV6
1844 memset(&confp->extsa6, 0, sizeof(confp->extsa6));
1845 *SAFAMILY(&confp->extsa6) = AF_INET6;
1846 #endif
1847 *SAFAMILY(&confp->intsa) = AF_INET;
1848 *SAFAMILY(&confp->extsa) = AF_INET;
1849 confp->maxchild = 100;
1850 resolvfunc = NULL;
1851 numservers = 0;
1852 acl = confp->acl;
1853 confp->acl = NULL;
1854
1855 usleep(SLEEPTIME);
1856
1857 {
1858 char * args[] = {"auth", "iponly", NULL};
1859 h_auth(2, (unsigned char **)args);
1860 }
1861 if(tc)dumpcounters(tc,counterd);
1862 for(; tc; tc = (struct trafcount *) itfree(tc, tc->next)){
1863 if(tc->comment)myfree(tc->comment);
1864 freeacl(tc->ace);
1865 }
1866
1867
1868 freeacl(acl);
1869 freepwl(pw);
1870 for(; bl; bl = (struct bandlim *) itfree(bl, bl->next)) freeacl(bl->ace);
1871 for(; blout; blout = (struct bandlim *) itfree(blout, blout->next))freeacl(blout->ace);
1872 for(; cl; cl = (struct connlim *) itfree(cl, cl->next)) freeacl(cl->ace);
1873
1874 if(counterd != -1) {
1875 close(counterd);
1876 }
1877 for(; fm; fm = (struct filemon *)itfree(fm, fm->next)){
1878 if(fm->path) myfree(fm->path);
1879 }
1880 /*
1881 if(logtarget) {
1882 myfree(logtarget);
1883 }
1884 if(logname) {
1885 myfree(logname);
1886 }
1887 */
1888 if(logformat) {
1889 myfree(logformat);
1890 }
1891 if(archiver) {
1892 for(i = 0; i < archiverc; i++) myfree(archiver[i]);
1893 myfree(archiver);
1894 }
1895 havelog = 0;
1896 }
1897
1898 int reload (void){
1899 FILE *fp;
1900 int error = -2;
1901
1902 conf.paused++;
1903 freeconf(&conf);
1904 conf.paused++;
1905
1906 fp = confopen();
1907 if(fp){
1908 error = readconfig(fp);
1909 conf.version++;
1910 if(error) {
1911 freeconf(&conf);
1912 }
1913 if(!writable)fclose(fp);
1914 }
1915 return error;
1916 }
1917