2008-05-24 16:05:49 +08:00
|
|
|
/* tinyproxy - A fast light-weight HTTP proxy
|
|
|
|
* Copyright (C) 1999 George Talusan <gstalusan@uwaterloo.ca>
|
|
|
|
* Copyright (C) 2002 James E. Flemer <jflemer@acm.jhu.edu>
|
|
|
|
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
|
2000-02-17 01:32:49 +08:00
|
|
|
*
|
2008-05-24 16:05:49 +08:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
2000-02-17 01:32:49 +08:00
|
|
|
*
|
2008-05-24 16:05:49 +08:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2000-02-17 01:32:49 +08:00
|
|
|
*
|
2008-05-24 16:05:49 +08:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* A substring of the domain to be filtered goes into the file
|
|
|
|
* pointed at by DEFAULT_FILTER.
|
2000-02-17 01:32:49 +08:00
|
|
|
*/
|
|
|
|
|
2009-08-07 06:12:53 +08:00
|
|
|
#include "main.h"
|
2000-09-12 07:43:59 +08:00
|
|
|
|
2000-02-17 01:32:49 +08:00
|
|
|
#include "filter.h"
|
2002-05-24 02:20:27 +08:00
|
|
|
#include "heap.h"
|
2002-06-07 04:30:04 +08:00
|
|
|
#include "log.h"
|
2002-05-27 09:56:22 +08:00
|
|
|
#include "reqs.h"
|
|
|
|
|
|
|
|
#define FILTER_BUFFER_LEN (512)
|
2000-02-17 01:32:49 +08:00
|
|
|
|
|
|
|
static int err;
|
|
|
|
|
2009-09-15 03:41:25 +08:00
|
|
|
struct filter_list {
|
|
|
|
struct filter_list *next;
|
|
|
|
char *pat;
|
|
|
|
regex_t *cpat;
|
2000-02-17 01:32:49 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct filter_list *fl = NULL;
|
|
|
|
static int already_init = 0;
|
2002-06-08 02:36:22 +08:00
|
|
|
static filter_policy_t default_policy = FILTER_DEFAULT_ALLOW;
|
2000-02-17 01:32:49 +08:00
|
|
|
|
2002-05-27 09:56:22 +08:00
|
|
|
/*
|
|
|
|
* Initializes a linked list of strings containing hosts/urls to be filtered
|
|
|
|
*/
|
2009-09-15 03:41:25 +08:00
|
|
|
void filter_init (void)
|
2000-02-17 01:32:49 +08:00
|
|
|
{
|
2009-09-15 03:41:25 +08:00
|
|
|
FILE *fd;
|
|
|
|
struct filter_list *p;
|
|
|
|
char buf[FILTER_BUFFER_LEN];
|
|
|
|
char *s;
|
|
|
|
int cflags;
|
|
|
|
|
2009-09-15 07:13:11 +08:00
|
|
|
if (fl || already_init) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fd = fopen (config.filter, "r");
|
|
|
|
if (!fd) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = NULL;
|
|
|
|
|
|
|
|
cflags = REG_NEWLINE | REG_NOSUB;
|
|
|
|
if (config.filter_extended)
|
|
|
|
cflags |= REG_EXTENDED;
|
|
|
|
if (!config.filter_casesensitive)
|
|
|
|
cflags |= REG_ICASE;
|
|
|
|
|
|
|
|
while (fgets (buf, FILTER_BUFFER_LEN, fd)) {
|
|
|
|
/*
|
|
|
|
* Remove any trailing white space and
|
|
|
|
* comments.
|
|
|
|
*/
|
|
|
|
s = buf;
|
|
|
|
while (*s) {
|
|
|
|
if (isspace ((unsigned char) *s))
|
|
|
|
break;
|
|
|
|
if (*s == '#') {
|
2009-09-15 03:41:25 +08:00
|
|
|
/*
|
2009-09-15 07:13:11 +08:00
|
|
|
* If the '#' char is preceeded by
|
|
|
|
* an escape, it's not a comment
|
|
|
|
* string.
|
2009-09-15 03:41:25 +08:00
|
|
|
*/
|
2009-09-15 08:22:04 +08:00
|
|
|
if (s == buf || *(s - 1) != '\\')
|
2009-09-15 07:13:11 +08:00
|
|
|
break;
|
2009-09-15 03:41:25 +08:00
|
|
|
}
|
2009-09-15 07:13:11 +08:00
|
|
|
++s;
|
|
|
|
}
|
|
|
|
*s = '\0';
|
|
|
|
|
|
|
|
/* skip leading whitespace */
|
|
|
|
s = buf;
|
|
|
|
while (*s && isspace ((unsigned char) *s))
|
|
|
|
s++;
|
|
|
|
|
|
|
|
/* skip blank lines and comments */
|
|
|
|
if (*s == '\0')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!p) /* head of list */
|
|
|
|
fl = p =
|
|
|
|
(struct filter_list *)
|
2009-09-15 08:22:04 +08:00
|
|
|
safecalloc (1, sizeof (struct filter_list));
|
2009-09-15 07:13:11 +08:00
|
|
|
else { /* next entry */
|
|
|
|
p->next =
|
|
|
|
(struct filter_list *)
|
2009-09-15 08:22:04 +08:00
|
|
|
safecalloc (1, sizeof (struct filter_list));
|
2009-09-15 07:13:11 +08:00
|
|
|
p = p->next;
|
|
|
|
}
|
2009-09-15 03:41:25 +08:00
|
|
|
|
2009-09-15 07:13:11 +08:00
|
|
|
p->pat = safestrdup (s);
|
2009-09-15 08:22:04 +08:00
|
|
|
p->cpat = (regex_t *) safemalloc (sizeof (regex_t));
|
2009-09-15 07:13:11 +08:00
|
|
|
err = regcomp (p->cpat, p->pat, cflags);
|
|
|
|
if (err != 0) {
|
|
|
|
fprintf (stderr,
|
|
|
|
"Bad regex in %s: %s\n",
|
|
|
|
config.filter, p->pat);
|
|
|
|
exit (EX_DATAERR);
|
2008-12-08 21:39:44 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-15 07:13:11 +08:00
|
|
|
if (ferror (fd)) {
|
|
|
|
perror ("fgets");
|
|
|
|
exit (EX_DATAERR);
|
|
|
|
}
|
|
|
|
fclose (fd);
|
|
|
|
|
|
|
|
already_init = 1;
|
2000-02-17 01:32:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* unlink the list */
|
2009-09-15 03:41:25 +08:00
|
|
|
void filter_destroy (void)
|
2000-02-17 01:32:49 +08:00
|
|
|
{
|
2009-09-15 03:41:25 +08:00
|
|
|
struct filter_list *p, *q;
|
|
|
|
|
|
|
|
if (already_init) {
|
|
|
|
for (p = q = fl; p; p = q) {
|
|
|
|
regfree (p->cpat);
|
|
|
|
safefree (p->cpat);
|
|
|
|
safefree (p->pat);
|
|
|
|
q = p->next;
|
|
|
|
safefree (p);
|
|
|
|
}
|
|
|
|
fl = NULL;
|
|
|
|
already_init = 0;
|
2008-12-08 21:39:44 +08:00
|
|
|
}
|
2000-02-17 01:32:49 +08:00
|
|
|
}
|
|
|
|
|
2009-10-25 20:54:46 +08:00
|
|
|
/**
|
|
|
|
* reload the filter file if filtering is enabled
|
|
|
|
*/
|
|
|
|
void filter_reload (void)
|
|
|
|
{
|
|
|
|
if (config.filter) {
|
|
|
|
log_message (LOG_NOTICE, "Re-reading filter file.");
|
|
|
|
filter_destroy ();
|
|
|
|
filter_init ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-08 02:36:22 +08:00
|
|
|
/* Return 0 to allow, non-zero to block */
|
2009-09-15 03:41:25 +08:00
|
|
|
int filter_domain (const char *host)
|
2000-02-17 01:32:49 +08:00
|
|
|
{
|
2009-09-15 03:41:25 +08:00
|
|
|
struct filter_list *p;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (!fl || !already_init)
|
|
|
|
goto COMMON_EXIT;
|
|
|
|
|
|
|
|
for (p = fl; p; p = p->next) {
|
|
|
|
result =
|
|
|
|
regexec (p->cpat, host, (size_t) 0, (regmatch_t *) 0, 0);
|
|
|
|
|
|
|
|
if (result == 0) {
|
|
|
|
if (default_policy == FILTER_DEFAULT_ALLOW)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
2008-12-08 21:39:44 +08:00
|
|
|
}
|
2008-12-01 23:01:11 +08:00
|
|
|
|
|
|
|
COMMON_EXIT:
|
2009-09-15 03:41:25 +08:00
|
|
|
if (default_policy == FILTER_DEFAULT_ALLOW)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
2000-02-17 01:32:49 +08:00
|
|
|
}
|
2002-05-27 09:56:22 +08:00
|
|
|
|
2002-06-08 02:36:22 +08:00
|
|
|
/* returns 0 to allow, non-zero to block */
|
2009-09-15 03:41:25 +08:00
|
|
|
int filter_url (const char *url)
|
2002-05-27 09:56:22 +08:00
|
|
|
{
|
2009-09-15 03:41:25 +08:00
|
|
|
struct filter_list *p;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (!fl || !already_init)
|
|
|
|
goto COMMON_EXIT;
|
|
|
|
|
|
|
|
for (p = fl; p; p = p->next) {
|
|
|
|
result =
|
|
|
|
regexec (p->cpat, url, (size_t) 0, (regmatch_t *) 0, 0);
|
|
|
|
|
|
|
|
if (result == 0) {
|
|
|
|
if (default_policy == FILTER_DEFAULT_ALLOW)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
2008-12-08 21:39:44 +08:00
|
|
|
}
|
2008-12-01 23:01:11 +08:00
|
|
|
|
|
|
|
COMMON_EXIT:
|
2009-09-15 03:41:25 +08:00
|
|
|
if (default_policy == FILTER_DEFAULT_ALLOW)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 1;
|
2002-06-08 02:36:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the default filtering policy
|
|
|
|
*/
|
2009-09-15 03:41:25 +08:00
|
|
|
void filter_set_default_policy (filter_policy_t policy)
|
2002-06-08 02:36:22 +08:00
|
|
|
{
|
2009-09-15 03:41:25 +08:00
|
|
|
default_policy = policy;
|
2002-05-27 09:56:22 +08:00
|
|
|
}
|