2 MiddleMan filtering proxy server
3 Copyright (C) 2002 Jason McLaughlin
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 load <filter> section of xml_list into a FILTER_LIST structure
27 FILTER_LIST *filter_load(FILTER_LIST * filter_list, XML_LIST * xml_list)
29 FILTER_LIST *tmp_list = filter_list;
30 struct FILTER_LIST_LIST *allow = NULL, *deny = NULL;
33 if (tmp_list == NULL) {
34 tmp_list = xmalloc(sizeof(FILTER_LIST));
35 tmp_list->dtemplate = NULL;
36 tmp_list->allow = NULL;
37 tmp_list->deny = NULL;
38 tmp_list->empty = NULL;
39 tmp_list->policy = POLICY_ALLOW;
41 tmp_list->enabled = TRUE;
43 tmp_list->empty = filter_ll_new(NULL);
45 filter_list = tmp_list;
47 pthread_rwlock_init(&tmp_list->lock, NULL);
49 allow = tmp_list->allow;
50 deny = tmp_list->deny;
53 while ((xml_list = xml_section(xml_list, "<filter>"))) {
54 XML_LIST_LOOP(xml_list, "<filter>") {
55 XML_LIST_CMP(xml_list, "<allow>") {
56 allow = filter_ll_new(allow);
57 allow->id = filter_list->id++;
59 if (tmp_list->allow == NULL)
60 tmp_list->allow = allow;
61 XML_LIST_LOOP(xml_list, "<allow>") {
62 XML_LIST_CMP(xml_list, "<enabled>") {
63 xml_list = xml_list->next;
64 if (xml_list->type == XML_VALUE) {
65 if (!strcasecmp(xml_list->item, "false"))
66 allow->enabled = FALSE;
68 allow->enabled = TRUE;
71 XML_LIST_CMP(xml_list, "<comment>") {
72 xml_list = xml_list->next;
73 if (xml_list->type == XML_VALUE)
74 filter_ll_insert(allow, xml_list->item, NULL, NULL, NULL);
76 XML_LIST_CMP(xml_list, "<host>") {
77 xml_list = xml_list->next;
78 if (xml_list->type == XML_VALUE)
79 filter_ll_insert(allow, NULL, xml_list->item, NULL, NULL);
81 XML_LIST_CMP(xml_list, "<file>") {
82 xml_list = xml_list->next;
83 if (xml_list->type == XML_VALUE)
84 filter_ll_insert(allow, NULL, NULL, xml_list->item, NULL);
86 XML_LIST_CMP(xml_list, "<template>") {
87 xml_list = xml_list->next;
88 if (xml_list->type == XML_VALUE)
89 filter_ll_insert(allow, NULL, NULL, NULL, xml_list->item);
94 XML_LIST_CMP(xml_list, "<deny>") {
95 deny = filter_ll_new(deny);
96 deny->id = filter_list->id++;
98 if (tmp_list->deny == NULL)
99 tmp_list->deny = deny;
100 XML_LIST_LOOP(xml_list, "<deny>") {
101 XML_LIST_CMP(xml_list, "<enabled>") {
102 xml_list = xml_list->next;
103 if (xml_list->type == XML_VALUE) {
104 if (!strcasecmp(xml_list->item, "false"))
105 deny->enabled = FALSE;
107 deny->enabled = TRUE;
110 XML_LIST_CMP(xml_list, "<comment>") {
111 xml_list = xml_list->next;
112 if (xml_list->type == XML_VALUE)
113 filter_ll_insert(deny, xml_list->item, NULL, NULL, NULL);
115 XML_LIST_CMP(xml_list, "<host>") {
116 xml_list = xml_list->next;
117 if (xml_list->type == XML_VALUE)
118 filter_ll_insert(deny, NULL, xml_list->item, NULL, NULL);
120 XML_LIST_CMP(xml_list, "<file>") {
121 xml_list = xml_list->next;
122 if (xml_list->type == XML_VALUE)
123 filter_ll_insert(deny, NULL, NULL, xml_list->item, NULL);
125 XML_LIST_CMP(xml_list, "<template>") {
126 xml_list = xml_list->next;
127 if (xml_list->type == XML_VALUE)
128 filter_ll_insert(deny, NULL, NULL, NULL, xml_list->item);
132 XML_LIST_CMP(xml_list, "<enabled>") {
133 xml_list = xml_list->next;
134 if (xml_list->type == XML_VALUE) {
135 if (!strcasecmp(xml_list->item, "false"))
136 filter_list->enabled = FALSE;
138 filter_list->enabled = TRUE;
141 XML_LIST_CMP(xml_list, "<default>") {
142 xml_list = xml_list->next;
143 if (xml_list->type == XML_VALUE) {
144 FREE_AND_NULL(tmp_list->dtemplate);
145 tmp_list->dtemplate = xstrdup(xml_list->item);
148 XML_LIST_CMP(xml_list, "<policy>") {
149 xml_list = xml_list->next;
150 if (xml_list->type == XML_VALUE) {
151 if (!strcasecmp(xml_list->item, "allow"))
152 tmp_list->policy = POLICY_ALLOW;
153 else if (!strcasecmp(xml_list->item, "deny"))
154 tmp_list->policy = POLICY_DENY;
165 XML_LIST *filter_xml(FILTER_LIST * filter_list, XML_LIST * xml_list)
169 struct FILTER_LIST_LIST *fl = NULL;
171 if (filter_list == NULL)
174 pthread_rwlock_rdlock(&filter_list->lock);
176 xml_list = xml_list_add(xml_list, "<filter>", XML_TAG);
178 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG);
179 xml_list = xml_list_add(xml_list, (filter_list->enabled == TRUE) ? "true" : "false", XML_VALUE);
180 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG);
182 xml_list = xml_list_add(xml_list, "<policy>", XML_TAG);
183 xml_list = xml_list_add(xml_list, (filter_list->policy == POLICY_ALLOW) ? "allow" : "deny", XML_VALUE);
184 xml_list = xml_list_add(xml_list, "</policy>", XML_TAG);
187 if (filter_list->dtemplate != NULL) {
188 xml_list = xml_list_add(xml_list, "<default>", XML_TAG);
189 ptr = string_to_xml(filter_list->dtemplate);
190 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
192 xml_list = xml_list_add(xml_list, "</default>", XML_TAG);
196 for (i = 0; i < 2; i++) {
199 fl = filter_list->allow;
202 fl = filter_list->deny;
206 for (; fl; fl = fl->next) {
207 xml_list = xml_list_add(xml_list, (i == 0) ? "<allow>" : "<deny>", XML_TAG);
209 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG);
210 xml_list = xml_list_add(xml_list, (fl->enabled == TRUE) ? "true" : "false", XML_VALUE);
211 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG);
213 if (fl->comment != NULL) {
214 xml_list = xml_list_add(xml_list, "<comment>", XML_TAG);
215 ptr = string_to_xml(fl->comment);
216 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
218 xml_list = xml_list_add(xml_list, "</comment>", XML_TAG);
220 if (fl->template != NULL) {
221 xml_list = xml_list_add(xml_list, "<template>", XML_TAG);
222 ptr = string_to_xml(fl->template);
223 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
225 xml_list = xml_list_add(xml_list, "</template>", XML_TAG);
228 if (fl->host != NULL) {
229 xml_list = xml_list_add(xml_list, "<host>", XML_TAG);
230 ptr = string_to_xml(fl->host);
231 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
233 xml_list = xml_list_add(xml_list, "</host>", XML_TAG);
236 if (fl->file != NULL) {
237 xml_list = xml_list_add(xml_list, "<file>", XML_TAG);
238 ptr = string_to_xml(fl->file);
239 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
241 xml_list = xml_list_add(xml_list, "</file>", XML_TAG);
244 xml_list = xml_list_add(xml_list, (i == 0) ? "</allow>" : "</deny>", XML_TAG);
248 xml_list = xml_list_add(xml_list, "</filter>", XML_TAG);
250 pthread_rwlock_unlock(&filter_list->lock);
257 free memory used by FILTER_LIST linked list
259 void filter_free(FILTER_LIST * filter_list)
261 filter_ll_free(filter_list->allow);
262 filter_ll_free(filter_list->deny);
264 FREE_AND_NULL(filter_list->dtemplate);
265 pthread_rwlock_destroy(&filter_list->lock);
270 void filter_ll_free(struct FILTER_LIST_LIST *fl)
272 struct FILTER_LIST_LIST *tmp;
281 FREE_AND_NULL(fl->comment);
282 FREE_AND_NULL(fl->host);
283 FREE_AND_NULL(fl->file);
284 FREE_AND_NULL(fl->template);
292 determine whether or not the host and/or file is allowed to be retrieved
293 based on the rules given in the filter_list linked list
295 struct FILTER_LIST_LIST *filter_check(FILTER_LIST * filter_list, CONNECTION * connection)
297 int action = FALSE, result = TRUE, ret, i;
298 struct FILTER_LIST_LIST *current, *match = NULL;
300 pthread_rwlock_rdlock(&filter_list->lock);
302 if (filter_list->enabled == FALSE || connection->bypass & FEATURE_FILTER)
305 for (i = 0; i < 2; i++) {
307 if (filter_list->policy == POLICY_ALLOW) {
308 current = filter_list->deny;
312 current = filter_list->allow;
316 } else if (result == action) {
317 if (filter_list->policy == POLICY_ALLOW) {
318 current = filter_list->allow;
321 current = filter_list->deny;
327 for (; current != NULL; current = current->next) {
328 if (current->enabled == FALSE)
331 if (current->he != NULL) {
332 ret = reg_exec(current->he, connection->header->host);
337 if (current->fe != NULL) {
338 ret = reg_exec(current->fe, connection->header->file);
349 return (!result) ? (match != NULL) ? match : filter_list->empty : NULL;
352 void filter_ll_insert(struct FILTER_LIST_LIST *x, char *a, char *b, char *c, char *d)
355 FREE_AND_NULL(x->comment);
358 x->comment = xstrdup(a);
363 FREE_AND_NULL(x->host);
366 x->he = reg_compile(b, REGFLAGS);
367 x->host = xstrdup(b);
375 FREE_AND_NULL(x->file);
378 x->fe = reg_compile(c, REGFLAGS);
379 x->file = xstrdup(c);
385 FREE_AND_NULL(x->template);
388 x->template = xstrdup(d);
392 struct FILTER_LIST_LIST *filter_ll_delete(struct FILTER_LIST_LIST *x)
394 struct FILTER_LIST_LIST *start = x;
396 while (start->prev != NULL)
400 x->next->prev = x->prev;
402 x->prev->next = x->next;
410 FREE_AND_NULL(x->comment);
411 FREE_AND_NULL(x->host);
412 FREE_AND_NULL(x->file);
413 FREE_AND_NULL(x->template);
420 struct FILTER_LIST_LIST *filter_ll_new(struct FILTER_LIST_LIST *x)
423 x = xmalloc(sizeof(struct FILTER_LIST_LIST));
426 while (x->next != NULL)
428 x->next = xmalloc(sizeof(struct FILTER_LIST_LIST));