1 const char loaders_rcs[] = "$Id: loaders.c,v 1.4 2001/05/22 18:56:28 oes Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/loaders.c,v $
6 * Purpose : Functions to load and unload the various
7 * configuration files. Also contains code to manage
8 * the list of active loaders, and to automatically
9 * unload files that are no longer in use.
11 * Copyright : Written by and Copyright (C) 2001 the SourceForge
12 * IJBSWA team. http://ijbswa.sourceforge.net
14 * Based on the Internet Junkbuster originally written
15 * by and Copyright (C) 1997 Anonymous Coders and
16 * Junkbusters Corporation. http://www.junkbusters.com
18 * This program is free software; you can redistribute it
19 * and/or modify it under the terms of the GNU General
20 * Public License as published by the Free Software
21 * Foundation; either version 2 of the License, or (at
22 * your option) any later version.
24 * This program is distributed in the hope that it will
25 * be useful, but WITHOUT ANY WARRANTY; without even the
26 * implied warranty of MERCHANTABILITY or FITNESS FOR A
27 * PARTICULAR PURPOSE. See the GNU General Public
28 * License for more details.
30 * The GNU General Public License should be included with
31 * this file. If not, you can view it at
32 * http://www.gnu.org/copyleft/gpl.html
33 * or write to the Free Software Foundation, Inc., 59
34 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 * Revision 1.4 2001/05/22 18:56:28 oes
41 * Revision 1.3 2001/05/20 01:21:20 jongfoster
42 * Version 2.9.4 checkin.
43 * - Merged popupfile and cookiefile, and added control over PCRS
44 * filtering, in new "permissionsfile".
45 * - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
46 * file error you now get a message box (in the Win32 GUI) rather
47 * than the program exiting with no explanation.
48 * - Made killpopup use the PCRS MIME-type checking and HTTP-header
50 * - Removed tabs from "config"
51 * - Moved duplicated url parsing code in "loaders.c" to a new funcition.
52 * - Bumped up version number.
54 * Revision 1.2 2001/05/17 23:01:01 oes
55 * - Cleaned CRLF's from the sources and related files
57 * Revision 1.1.1.1 2001/05/15 13:58:59 oes
58 * Initial import of version 2.9.3 source tree
61 *********************************************************************/
68 #include <sys/types.h>
90 #ifndef SPLIT_PROXY_ARGS
93 #endif /* ndef SPLIT_PROXY_ARGS */
95 const char loaders_h_rcs[] = LOADERS_H_VERSION;
97 /* Fix a problem with Solaris. There should be no effect on other
99 * Solaris's isspace() is a macro which uses it's argument directly
100 * as an array index. Therefore we need to make sure that high-bit
101 * characters generate +ve values, and ideally we also want to make
102 * the argument match the declared parameter type of "int".
104 #define ijb_isspace(__X) isspace((int)(unsigned char)(__X))
108 static int (*loaders[NLOADERS])(struct client_state *);
112 * Currently active files.
113 * These are also entered in the main linked list of files.
115 static struct file_list *current_blockfile = NULL;
116 static struct file_list *current_permissions_file = NULL;
117 static struct file_list *current_forwardfile = NULL;
120 static struct file_list *current_aclfile = NULL;
121 #endif /* def ACL_FILES */
123 #ifdef USE_IMAGE_LIST
124 static struct file_list *current_imagefile = NULL;
125 #endif /* def USE_IMAGE_LIST */
128 static struct file_list *current_trustfile = NULL;
129 #endif /* def TRUST_FILES */
132 static struct file_list *current_re_filterfile = NULL;
133 #endif /* def PCRS */
136 static int create_url_spec(struct url_spec * url, char * buf);
139 /*********************************************************************
143 * Description : Basically a mark and sweep garbage collector, it is run
144 * (by the parent thread) every once in a while to reclaim memory.
146 * It uses a mark and sweep strategy:
147 * 1) mark all files as inactive
149 * 2) check with each client:
150 * if it is active, mark its files as active
151 * if it is inactive, free its resources
153 * 3) free the resources of all of the files that
154 * are still marked as inactive (and are obsolete).
156 * N.B. files that are not obsolete don't have an unloader defined.
162 *********************************************************************/
165 struct file_list *fl, *nfl;
166 struct client_state *csp, *ncsp;
168 /* clear all of the file's active flags */
169 for ( fl = files->next; NULL != fl; fl = fl->next )
174 for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
178 /* mark this client's files as active */
180 if (ncsp->blist) /* block files */
182 ncsp->blist->active = 1;
185 if (ncsp->permissions_list) /* permissions files */
187 ncsp->permissions_list->active = 1;
190 if (ncsp->flist) /* forward files */
192 ncsp->flist->active = 1;
196 if (ncsp->alist) /* acl files */
198 ncsp->alist->active = 1;
200 #endif /* def ACL_FILES */
202 #ifdef USE_IMAGE_LIST
203 if (ncsp->ilist) /* image files */
205 ncsp->ilist->active = 1;
207 #endif /* def USE_IMAGE_LIST */
210 if (ncsp->rlist) /* perl re files */
212 ncsp->rlist->active = 1;
214 #endif /* def PCRS */
217 if (ncsp->tlist) /* trust files */
219 ncsp->tlist->active = 1;
221 #endif /* def TRUST_FILES */
226 /* this client one is not active, release its resources */
227 csp->next = ncsp->next;
229 freez(ncsp->ip_addr_str);
230 freez(ncsp->referrer);
231 freez(ncsp->x_forwarded);
232 freez(ncsp->ip_addr_str);
233 freez(ncsp->iob->buf);
235 free_http_request(ncsp->http);
237 destroy_list(ncsp->headers);
238 destroy_list(ncsp->cookie_list);
246 #endif /* def STATISTICS */
252 for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
254 if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
256 fl->next = nfl->next;
258 (nfl->unloader)(nfl->f);
260 #ifndef SPLIT_PROXY_ARGS
261 freez(nfl->proxy_args);
262 #endif /* ndef SPLIT_PROXY_ARGS */
264 freez(nfl->filename);
273 /*********************************************************************
275 * Function : create_url_spec
277 * Description : Creates a "url_spec" structure from a string.
278 * When finished, free with unload_url().
281 * 1 : url = Target url_spec to be filled in. Must be
282 * zeroed out before the call (e.g. using zalloc).
283 * 2 : buf = Source pattern, null terminated. NOTE: The
284 * contents of this buffer are destroyed by this
285 * function. If this function succeeds, the
286 * buffer is copied to url->spec. If this
287 * function fails, the contents of the buffer
290 * Returns : 0 => Ok, everything else is an error.
292 *********************************************************************/
293 static int create_url_spec(struct url_spec * url, char * buf)
296 struct url_spec tmp_url[1];
298 /* paranoia - should never happen. */
299 if ((url == NULL) || (buf == NULL))
304 /* save a copy of the orignal specification */
305 if ((url->spec = strdup(buf)) == NULL)
310 if ((p = strchr(buf, '/')))
312 if (NULL == (url->path = strdup(p)))
317 url->pathlen = strlen(url->path);
331 if (NULL == (url->preg = zalloc(sizeof(*url->preg))))
338 sprintf(rebuf, "^(%s)", url->path);
340 errcode = regcomp(url->preg, rebuf,
341 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
346 url->preg, buf, sizeof(buf));
350 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
361 if ((p = strchr(buf, ':')) == NULL)
371 if ((url->domain = strdup(buf)) == NULL)
377 #endif /* def REGEX */
381 /* split domain into components */
383 *tmp_url = dsplit(url->domain);
384 url->dbuf = tmp_url->dbuf;
385 url->dcnt = tmp_url->dcnt;
386 url->dvec = tmp_url->dvec;
392 /*********************************************************************
394 * Function : unload_url
396 * Description : Called from the "unloaders". Freez the url
397 * structure elements.
400 * 1 : url = pointer to a url_spec structure.
404 *********************************************************************/
405 static void unload_url(struct url_spec *url)
407 if (url == NULL) return;
426 /*********************************************************************
428 * Function : unload_aclfile
430 * Description : Unloads an aclfile.
433 * 1 : f = the data structure associated with the aclfile.
437 *********************************************************************/
438 static void unload_aclfile(void *f)
440 struct access_control_list *b = (struct access_control_list *)f;
441 if (b == NULL) return;
443 unload_aclfile(b->next);
448 #endif /* def ACL_FILES */
450 /*********************************************************************
452 * Function : unload_blockfile
454 * Description : Unloads a blockfile.
457 * 1 : f = the data structure associated with the blockfile.
461 *********************************************************************/
462 static void unload_blockfile(void *f)
464 struct block_spec *b = (struct block_spec *)f;
465 if (b == NULL) return;
467 unload_blockfile(b->next);
476 #ifdef USE_IMAGE_LIST
477 /*********************************************************************
479 * Function : unload_imagefile
481 * Description : Unloads an imagefile.
484 * 1 : f = the data structure associated with the imagefile.
488 *********************************************************************/
489 static void unload_imagefile(void *f)
491 struct block_spec *b = (struct block_spec *)f;
492 if (b == NULL) return;
494 unload_imagefile(b->next);
501 #endif /* def USE_IMAGE_LIST */
504 /*********************************************************************
506 * Function : unload_permissions_file
508 * Description : Unloads a permissions file.
511 * 1 : file_data = the data structure associated with the
516 *********************************************************************/
517 static void unload_permissions_file(void *file_data)
519 struct permissions_spec * next;
520 struct permissions_spec * cur = (struct permissions_spec *)file_data;
524 unload_url(cur->url);
533 /*********************************************************************
535 * Function : unload_trustfile
537 * Description : Unloads a trustfile.
540 * 1 : f = the data structure associated with the trustfile.
544 *********************************************************************/
545 static void unload_trustfile(void *f)
547 struct block_spec *b = (struct block_spec *)f;
548 if (b == NULL) return;
550 unload_trustfile(b->next);
557 #endif /* def TRUST_FILES */
560 /*********************************************************************
562 * Function : unload_forwardfile
564 * Description : Unloads a forwardfile.
567 * 1 : f = the data structure associated with the forwardfile.
571 *********************************************************************/
572 static void unload_forwardfile(void *f)
574 struct forward_spec *b = (struct forward_spec *)f;
575 if (b == NULL) return;
577 unload_forwardfile(b->next);
581 freez(b->gw->gateway_host);
582 freez(b->gw->forward_host);
590 /*********************************************************************
592 * Function : unload_re_filterfile
594 * Description : Unload the re_filter list.
597 * 1 : f = the data structure associated with the filterfile.
601 *********************************************************************/
602 static void unload_re_filterfile(void *f)
605 struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
607 if (b == NULL) return;
609 destroy_list(b->patterns);
611 joblist = b->joblist;
612 while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}
617 #endif /* def PCRS */
620 /*********************************************************************
622 * Function : check_file_changed
624 * Description : Helper function to check if a file needs reloading.
625 * If "current" is still current, return it. Otherwise
626 * allocates a new (zeroed) "struct file_list", fills
627 * in the disk file name and timestamp, and returns it.
630 * 1 : current = The file_list currently being used - will
631 * be checked to see if it is out of date.
632 * May be NULL (which is treated as out of
634 * 2 : filename = Name of file to check.
635 * 3 : newfl = New file list. [Output only]
636 * This will be set to NULL, OR a struct
637 * file_list newly allocated on the
638 * heap, with the filename and lastmodified
639 * fields filled, standard header giving file
640 * name in proxy_args, and all others zeroed.
641 * (proxy_args is only filled in if !defined
642 * SPLIT_PROXY_ARGS and !suppress_blocklists).
644 * Returns : If file unchanged: 0 (and sets newfl == NULL)
645 * If file changed: 1 and sets newfl != NULL
646 * On error: 1 and sets newfl == NULL
648 *********************************************************************/
649 static int check_file_changed(const struct file_list * current,
650 const char * filename,
651 struct file_list ** newfl)
653 struct file_list *fs;
654 struct stat statbuf[1];
658 if (stat(filename, statbuf) < 0)
660 /* Error, probably file not found. */
665 && (current->lastmodified == statbuf->st_mtime)
666 && (0 == strcmp(current->filename, filename)))
671 fs = (struct file_list *)zalloc(sizeof(struct file_list));
675 /* Out of memory error */
679 fs->filename = strdup(filename);
680 fs->lastmodified = statbuf->st_mtime;
682 if (fs->filename == NULL)
684 /* Out of memory error */
689 #ifndef SPLIT_PROXY_ARGS
690 if (!suppress_blocklists)
692 char * p = html_encode(filename);
695 fs->proxy_args = strsav(fs->proxy_args, "<h2>The file `");
696 fs->proxy_args = strsav(fs->proxy_args, p);
697 fs->proxy_args = strsav(fs->proxy_args,
698 "' contains the following patterns</h2>\n");
701 fs->proxy_args = strsav(fs->proxy_args, "<pre>");
703 #endif /* ndef SPLIT_PROXY_ARGS */
710 /*********************************************************************
712 * Function : read_config_line
714 * Description : Read a single non-empty line from a file and return
715 * it. Trims comments, leading and trailing whitespace
716 * and respects escaping of newline and comment char.
717 * Also writes the file to fs->proxy_args.
720 * 1 : buf = Buffer to use.
721 * 2 : buflen = Size of buffer in bytes.
722 * 3 : fp = File to read from
723 * 4 : fs = File will be written to fs->proxy_args. May
724 * be NULL to disable this feature.
726 * Returns : NULL on EOF or error
727 * Otherwise, returns buf.
729 *********************************************************************/
730 char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs)
733 char linebuf[BUFSIZ];
738 while (fgets(linebuf, sizeof(linebuf), fp))
740 #ifndef SPLIT_PROXY_ARGS
741 if (fs && !suppress_blocklists)
743 char *html_line = html_encode(linebuf);
744 if (html_line != NULL)
746 fs->proxy_args = strsav(fs->proxy_args, html_line);
749 fs->proxy_args = strsav(fs->proxy_args, "<br>");
751 #endif /* ndef SPLIT_PROXY_ARGS */
753 /* Trim off newline */
754 if ((p = strpbrk(linebuf, "\r\n")) != NULL)
759 /* Line continuation? Trim escape and set flag. */
760 if ((p != linebuf) && (*--p == '\\'))
766 /* If there's a comment char.. */
767 if ((p = strpbrk(linebuf, "#")) != NULL)
769 /* ..and it's escaped, left-shift the line over the escape. */
770 if ((p != linebuf) && (*(p-1) == '\\'))
773 while ((*q++ = *p++) != '\0') /* nop */;
775 /* Else, chop off the rest of the line */
782 /* Trim leading whitespace */
784 while (*p && ijb_isspace(*p))
791 /* There is something other than whitespace on the line. */
793 /* Move the data to the start of buf */
796 /* strcpy that can cope with overlap. */
798 while ((*q++ = *p++) != '\0')
804 /* Trim trailing whitespace */
805 p = linebuf + strlen(linebuf) - 1;
808 * Note: the (p >= linebuf) below is paranoia, it's not really needed.
809 * When p == linebuf then ijb_isspace(*p) will be false and we'll drop
812 while ((p >= linebuf) && ijb_isspace(*p))
818 /* More paranoia. This if statement is always true. */
821 strncat(buf, linebuf, buflen - strlen(buf));
841 /*********************************************************************
843 * Function : load_aclfile
845 * Description : Read and parse an aclfile and add to files list.
848 * 1 : csp = Current client state (buffers, headers, etc...)
850 * Returns : 0 => Ok, everything else is an error.
852 *********************************************************************/
853 int load_aclfile(struct client_state *csp)
856 char buf[BUFSIZ], *v[3], *p;
858 struct access_control_list *a, *bl;
859 struct file_list *fs;
861 if (!check_file_changed(current_aclfile, aclfile, &fs))
863 /* No need to load */
866 csp->alist = current_aclfile;
872 goto load_aclfile_error;
875 fs->f = bl = (struct access_control_list *)zalloc(sizeof(*bl));
880 goto load_aclfile_error;
883 fp = fopen(aclfile, "r");
887 goto load_aclfile_error;
890 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
892 i = ssplit(buf, " \t", v, SZ(v), 1, 1);
894 /* allocate a new node */
895 a = (struct access_control_list *) zalloc(sizeof(*a));
903 goto load_aclfile_error;
906 /* add it to the list */
913 if (acl_addr(v[2], a->dst) < 0)
915 goto load_aclfile_error;
920 if (acl_addr(v[1], a->src) < 0)
922 goto load_aclfile_error;
926 if (strcmpic(p, "permit") == 0)
928 a->action = ACL_PERMIT;
932 if (strcmpic(p, "deny") == 0)
934 a->action = ACL_DENY;
940 goto load_aclfile_error;
946 #ifndef SPLIT_PROXY_ARGS
947 if (!suppress_blocklists)
949 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
951 #endif /* ndef SPLIT_PROXY_ARGS */
955 current_aclfile->unloader = unload_aclfile;
958 fs->next = files->next;
960 current_aclfile = fs;
970 log_error(LOG_LEVEL_ERROR, "can't load access control list %s: %E", aclfile);
974 #endif /* def ACL_FILES */
977 /*********************************************************************
979 * Function : load_blockfile
981 * Description : Read and parse a blockfile and add to files list.
984 * 1 : csp = Current client state (buffers, headers, etc...)
986 * Returns : 0 => Ok, everything else is an error.
988 *********************************************************************/
989 int load_blockfile(struct client_state *csp)
993 struct block_spec *b, *bl;
994 char buf[BUFSIZ], *p, *q;
996 struct file_list *fs;
998 if (!check_file_changed(current_blockfile, blockfile, &fs))
1000 /* No need to load */
1003 csp->blist = current_blockfile;
1009 goto load_blockfile_error;
1012 fs->f = bl = (struct block_spec *) zalloc(sizeof(*bl));
1015 goto load_blockfile_error;
1018 if ((fp = fopen(blockfile, "r")) == NULL)
1020 goto load_blockfile_error;
1023 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1032 while ((*p++ = *q++))
1038 /* skip lines containing only ~ */
1044 /* allocate a new node */
1045 if ((b = zalloc(sizeof(*b))) == NULL)
1048 goto load_blockfile_error;
1051 /* add it to the list */
1057 /* Save the URL pattern */
1058 if (create_url_spec(b->url, buf))
1061 goto load_blockfile_error;
1067 #ifndef SPLIT_PROXY_ARGS
1068 if (!suppress_blocklists)
1070 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1072 #endif /* ndef SPLIT_PROXY_ARGS */
1074 /* the old one is now obsolete */
1075 if (current_blockfile)
1077 current_blockfile->unloader = unload_blockfile;
1080 fs->next = files->next;
1082 current_blockfile = fs;
1091 load_blockfile_error:
1092 log_error(LOG_LEVEL_ERROR, "can't load blockfile '%s': %E", blockfile);
1098 #ifdef USE_IMAGE_LIST
1099 /*********************************************************************
1101 * Function : load_imagefile
1103 * Description : Read and parse an imagefile and add to files list.
1106 * 1 : csp = Current client state (buffers, headers, etc...)
1108 * Returns : 0 => Ok, everything else is an error.
1110 *********************************************************************/
1111 int load_imagefile(struct client_state *csp)
1115 struct block_spec *b, *bl;
1116 char buf[BUFSIZ], *p, *q;
1118 struct file_list *fs;
1120 if (!check_file_changed(current_imagefile, imagefile, &fs))
1122 /* No need to load */
1125 csp->ilist = current_imagefile;
1131 goto load_imagefile_error;
1134 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1137 goto load_imagefile_error;
1140 if ((fp = fopen(imagefile, "r")) == NULL)
1142 goto load_imagefile_error;
1145 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1154 while ((*p++ = *q++))
1160 /* skip lines containing only ~ */
1166 /* allocate a new node */
1167 if ((b = zalloc(sizeof(*b))) == NULL)
1170 goto load_imagefile_error;
1173 /* add it to the list */
1179 /* Save the URL pattern */
1180 if (create_url_spec(b->url, buf))
1183 goto load_imagefile_error;
1189 #ifndef SPLIT_PROXY_ARGS
1190 if (!suppress_blocklists)
1192 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1194 #endif /* ndef SPLIT_PROXY_ARGS */
1196 /* the old one is now obsolete */
1197 if (current_imagefile)
1199 current_imagefile->unloader = unload_imagefile;
1202 fs->next = files->next;
1204 current_imagefile = fs;
1213 load_imagefile_error:
1214 log_error(LOG_LEVEL_ERROR, "can't load imagefile '%s': %E", imagefile);
1218 #endif /* def USE_IMAGE_LIST */
1221 /*********************************************************************
1223 * Function : load_permissions_file
1225 * Description : Read and parse a permissions file and add to files
1229 * 1 : csp = Current client state (buffers, headers, etc...)
1231 * Returns : 0 => Ok, everything else is an error.
1233 *********************************************************************/
1234 int load_permissions_file(struct client_state *csp)
1238 struct permissions_spec *b, *bl;
1239 char buf[BUFSIZ], *p, *q;
1241 struct file_list *fs;
1244 if (!check_file_changed(current_permissions_file, permissions_file, &fs))
1246 /* No need to load */
1249 csp->permissions_list = current_permissions_file;
1255 goto load_permissions_error;
1258 fs->f = bl = (struct permissions_spec *)zalloc(sizeof(*bl));
1261 goto load_permissions_error;
1264 if ((fp = fopen(permissions_file, "r")) == NULL)
1266 goto load_permissions_error;
1271 * default_permissions is set in this file.
1273 * Reset it to default first.
1275 default_permissions = PERMIT_RE_FILTER;
1277 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1281 permissions = PERMIT_COOKIE_SET | PERMIT_COOKIE_READ | PERMIT_POPUPS;
1284 * FIXME: for() loop is a kludge. Want to loop around until we
1285 * find a non-control character. Assume there will be at most 4
1288 for (i = 0; i < 4; i++)
1294 * Allow cookies to be read by the server, but do
1295 * not allow them to be set.
1297 permissions = (permissions & ~PERMIT_COOKIE_SET);
1303 * Allow server to set cookies but do not let the
1306 permissions = (permissions & ~PERMIT_COOKIE_READ);
1314 permissions = (permissions & ~PERMIT_POPUPS);
1320 * Permit filtering using PCRS
1322 permissions = (permissions | PERMIT_RE_FILTER);
1328 * All of the above (maximum filtering).
1330 permissions = PERMIT_RE_FILTER;
1336 * FIXME: Should break out of the loop here.
1343 * Elide any of the "special" chars from the
1344 * front of the pattern
1349 while ((*q++ = *p++) != '\0')
1355 /* a lines containing only "special" chars sets default */
1358 default_permissions = permissions;
1362 /* allocate a new node */
1363 if (((b = zalloc(sizeof(*b))) == NULL)
1367 goto load_permissions_error;
1370 /* add it to the list */
1375 b->permissions = permissions;
1377 /* Save the URL pattern */
1378 if (create_url_spec(b->url, buf))
1381 goto load_permissions_error;
1387 #ifndef SPLIT_PROXY_ARGS
1388 if (!suppress_blocklists)
1390 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1392 #endif /* ndef SPLIT_PROXY_ARGS */
1394 /* the old one is now obsolete */
1395 if (current_permissions_file)
1397 current_permissions_file->unloader = unload_permissions_file;
1400 fs->next = files->next;
1402 current_permissions_file = fs;
1406 csp->permissions_list = fs;
1411 load_permissions_error:
1412 log_error(LOG_LEVEL_ERROR, "can't load permissions file '%s': %E", permissions_file);
1419 /*********************************************************************
1421 * Function : load_trustfile
1423 * Description : Read and parse a trustfile and add to files list.
1426 * 1 : csp = Current client state (buffers, headers, etc...)
1428 * Returns : 0 => Ok, everything else is an error.
1430 *********************************************************************/
1431 int load_trustfile(struct client_state *csp)
1435 struct block_spec *b, *bl;
1436 struct url_spec **tl;
1438 char buf[BUFSIZ], *p, *q;
1439 int reject, trusted;
1440 struct file_list *fs;
1442 if (!check_file_changed(current_trustfile, trustfile, &fs))
1444 /* No need to load */
1447 csp->tlist = current_trustfile;
1453 goto load_trustfile_error;
1456 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1459 goto load_trustfile_error;
1462 if ((fp = fopen(trustfile, "r")) == NULL)
1464 goto load_trustfile_error;
1469 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1485 while ((*p++ = *q++))
1491 /* skip blank lines */
1497 /* allocate a new node */
1498 if ((b = zalloc(sizeof(*b))) == NULL)
1501 goto load_trustfile_error;
1504 /* add it to the list */
1510 /* Save the URL pattern */
1511 if (create_url_spec(b->url, buf))
1514 goto load_trustfile_error;
1518 * save a pointer to URL's spec in the list of trusted URL's, too
1530 #ifndef SPLIT_PROXY_ARGS
1531 if (!suppress_blocklists)
1533 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1535 #endif /* ndef SPLIT_PROXY_ARGS */
1537 /* the old one is now obsolete */
1538 if (current_trustfile)
1540 current_trustfile->unloader = unload_trustfile;
1543 fs->next = files->next;
1545 current_trustfile = fs;
1554 load_trustfile_error:
1555 log_error(LOG_LEVEL_ERROR, "can't load trustfile '%s': %E", trustfile);
1559 #endif /* def TRUST_FILES */
1562 /*********************************************************************
1564 * Function : load_forwardfile
1566 * Description : Read and parse a forwardfile and add to files list.
1569 * 1 : csp = Current client state (buffers, headers, etc...)
1571 * Returns : 0 => Ok, everything else is an error.
1573 *********************************************************************/
1574 int load_forwardfile(struct client_state *csp)
1578 struct forward_spec *b, *bl;
1579 char buf[BUFSIZ], *p, *q, *tmp;
1581 int port, n, reject;
1582 struct file_list *fs;
1583 const struct gateway *gw;
1584 struct url_spec url[1];
1586 if (!check_file_changed(current_forwardfile, forwardfile, &fs))
1588 /* No need to load */
1591 csp->flist = current_forwardfile;
1597 goto load_forwardfile_error;
1600 fs->f = bl = (struct forward_spec *)zalloc(sizeof(*bl));
1602 if ((fs == NULL) || (bl == NULL))
1604 goto load_forwardfile_error;
1607 if ((fp = fopen(forwardfile, "r")) == NULL)
1609 goto load_forwardfile_error;
1614 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1620 n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
1624 log_error(LOG_LEVEL_ERROR, "error in forwardfile: %s", buf);
1628 strcpy(buf, vec[0]);
1637 while ((*p++ = *q++))
1643 /* skip lines containing only ~ */
1649 /* allocate a new node */
1650 if (((b = zalloc(sizeof(*b))) == NULL)
1652 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1657 goto load_forwardfile_error;
1660 /* add it to the list */
1664 /* save a copy of the orignal specification */
1665 if ((b->url->spec = strdup(buf)) == NULL)
1668 goto load_forwardfile_error;
1673 if ((p = strchr(buf, '/')))
1675 b->url->path = strdup(p);
1676 b->url->pathlen = strlen(b->url->path);
1681 b->url->path = NULL;
1682 b->url->pathlen = 0;
1690 sprintf(rebuf, "^(%s)", b->url->path);
1692 errcode = regcomp(b->url->preg, rebuf,
1693 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1697 size_t errlen = regerror(errcode, b->url->preg, buf, sizeof(buf));
1701 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1704 goto load_forwardfile_error;
1709 freez(b->url->preg);
1712 if ((p = strchr(buf, ':')) == NULL)
1722 b->url->port = port;
1724 if ((b->url->domain = strdup(buf)) == NULL)
1727 goto load_forwardfile_error;
1730 /* split domain into components */
1731 *url = dsplit(b->url->domain);
1732 b->url->dbuf = url->dbuf;
1733 b->url->dcnt = url->dcnt;
1734 b->url->dvec = url->dvec;
1736 /* now parse the gateway specs */
1740 for (gw = gateways; gw->name; gw++)
1742 if (strcmp(gw->name, p) == 0)
1748 if (gw->name == NULL)
1750 goto load_forwardfile_error;
1753 /* save this as the gateway type */
1756 /* now parse the gateway host[:port] spec */
1759 if (strcmp(p, ".") != 0)
1761 b->gw->gateway_host = strdup(p);
1763 if ((p = strchr(b->gw->gateway_host, ':')))
1766 b->gw->gateway_port = atoi(p);
1769 if (b->gw->gateway_port <= 0)
1771 goto load_forwardfile_error;
1775 /* now parse the forwarding spec */
1778 if (strcmp(p, ".") != 0)
1780 b->gw->forward_host = strdup(p);
1782 if ((p = strchr(b->gw->forward_host, ':')))
1785 b->gw->forward_port = atoi(p);
1788 if (b->gw->forward_port <= 0)
1790 b->gw->forward_port = 8000;
1799 #ifndef SPLIT_PROXY_ARGS
1800 if (!suppress_blocklists)
1802 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1804 #endif /* ndef SPLIT_PROXY_ARGS */
1806 /* the old one is now obsolete */
1807 if (current_forwardfile)
1809 current_forwardfile->unloader = unload_forwardfile;
1812 fs->next = files->next;
1814 current_forwardfile = fs;
1823 load_forwardfile_error:
1824 log_error(LOG_LEVEL_ERROR, "can't load forwardfile '%s': %E", forwardfile);
1831 /*********************************************************************
1833 * Function : load_re_filterfile
1835 * Description : Load the re_filterfile. Each non-comment, non-empty
1836 * line is instantly added to the joblist, which is
1837 * a chained list of pcrs_job structs.
1840 * 1 : csp = Current client state (buffers, headers, etc...)
1842 * Returns : 0 => Ok, everything else is an error.
1844 *********************************************************************/
1845 int load_re_filterfile(struct client_state *csp)
1849 struct re_filterfile_spec *bl;
1850 struct file_list *fs;
1856 if (!check_file_changed(current_re_filterfile, re_filterfile, &fs))
1858 /* No need to load */
1861 csp->rlist = current_re_filterfile;
1867 goto load_re_filterfile_error;
1870 fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
1873 goto load_re_filterfile_error;
1876 /* Open the file or fail */
1877 if ((fp = fopen(re_filterfile, "r")) == NULL)
1879 goto load_re_filterfile_error;
1882 /* Read line by line */
1883 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1885 enlist( bl->patterns, buf );
1887 /* We have a meaningful line -> make it a job */
1888 if ((dummy = pcrs_make_job(buf, &error)) == NULL)
1890 log_error(LOG_LEVEL_RE_FILTER,
1891 "Adding re_filter job %s failed with error %d.", buf, error);
1896 dummy->next = bl->joblist;
1897 bl->joblist = dummy;
1898 log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job %s succeeded.", buf);
1904 #ifndef SPLIT_PROXY_ARGS
1905 if (!suppress_blocklists)
1907 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1909 #endif /* ndef SPLIT_PROXY_ARGS */
1911 /* the old one is now obsolete */
1912 if ( NULL != current_re_filterfile )
1914 current_re_filterfile->unloader = unload_re_filterfile;
1917 fs->next = files->next;
1919 current_re_filterfile = fs;
1928 load_re_filterfile_error:
1929 log_error(LOG_LEVEL_ERROR, "can't load re_filterfile '%s': %E", re_filterfile);
1933 #endif /* def PCRS */
1936 /*********************************************************************
1938 * Function : add_loader
1940 * Description : Called from `load_config'. Called once for each input
1941 * file found in config.
1944 * 1 : loader = pointer to a function that can parse and load
1945 * the appropriate config file.
1949 *********************************************************************/
1950 void add_loader(int (*loader)(struct client_state *))
1954 for (i=0; i < NLOADERS; i++)
1956 if (loaders[i] == NULL)
1958 loaders[i] = loader;
1966 /*********************************************************************
1968 * Function : run_loader
1970 * Description : Called from `load_config' and `listen_loop'. This
1971 * function keeps the "csp" current with any file mods
1972 * since the last loop. If a file is unchanged, the
1973 * loader functions do NOT reload the file.
1976 * 1 : csp = Current client state (buffers, headers, etc...)
1978 * Returns : 0 => Ok, everything else is an error.
1980 *********************************************************************/
1981 int run_loader(struct client_state *csp)
1986 for (i=0; i < NLOADERS; i++)
1988 if (loaders[i] == NULL)
1992 ret |= (loaders[i])(csp);
1999 /*********************************************************************
2001 * Function : remove_all_loaders
2003 * Description : Remove all loaders from the list.
2009 *********************************************************************/
2010 void remove_all_loaders(void)
2012 memset( loaders, 0, sizeof( loaders ) );