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 parse <access> section from XML file
27 ACCESS_LIST *access_load(ACCESS_LIST * access_list, XML_LIST * xml_list)
29 ACCESS_LIST *tmp_list = access_list;
30 struct ACCESS_LIST_LIST *allow = NULL, *deny = NULL;
32 if (tmp_list == NULL) {
33 tmp_list = xmalloc(sizeof(ACCESS_LIST));
34 tmp_list->allow = NULL;
35 tmp_list->deny = NULL;
36 tmp_list->policy = POLICY_DENY;
39 access_list = tmp_list;
41 pthread_rwlock_init(&tmp_list->lock, NULL);
43 allow = tmp_list->allow;
44 deny = tmp_list->deny;
47 while ((xml_list = xml_section(xml_list, "<access>"))) {
48 XML_LIST_LOOP(xml_list, "<access>") {
49 XML_LIST_CMP(xml_list, "<allow>") {
50 allow = access_ll_new(allow);
51 allow->id = access_list->id++;
53 if (tmp_list->allow == NULL)
54 tmp_list->allow = allow;
55 XML_LIST_LOOP(xml_list, "<allow>") {
56 XML_LIST_CMP(xml_list, "<enabled>") {
57 xml_list = xml_list->next;
58 if (xml_list->type == XML_VALUE) {
59 if (!strcasecmp(xml_list->item, "false"))
60 allow->enabled = FALSE;
62 allow->enabled = TRUE;
65 XML_LIST_CMP(xml_list, "<comment>") {
66 xml_list = xml_list->next;
67 if (xml_list->type == XML_VALUE)
68 access_ll_insert(allow, xml_list->item, NULL, NULL, NULL, NULL, NULL);
70 XML_LIST_CMP(xml_list, "<ip>") {
71 xml_list = xml_list->next;
72 if (xml_list->type == XML_VALUE)
73 access_ll_insert(allow, NULL, xml_list->item, NULL, NULL, NULL, NULL);
75 XML_LIST_CMP(xml_list, "<access>") {
76 xml_list = xml_list->next;
77 if (xml_list->type == XML_VALUE)
78 access_ll_insert(allow, NULL, NULL, xml_list->item, NULL, NULL, NULL);
80 XML_LIST_CMP(xml_list, "<bypass>") {
81 xml_list = xml_list->next;
82 if (xml_list->type == XML_VALUE)
83 access_ll_insert(allow, NULL, NULL, NULL, xml_list->item, NULL, NULL);
85 XML_LIST_CMP(xml_list, "<username>") {
86 xml_list = xml_list->next;
87 if (xml_list->type == XML_VALUE)
88 access_ll_insert(allow, NULL, NULL, NULL, NULL, xml_list->item, NULL);
90 XML_LIST_CMP(xml_list, "<password>") {
91 xml_list = xml_list->next;
92 if (xml_list->type == XML_VALUE)
93 access_ll_insert(allow, NULL, NULL, NULL, NULL, NULL, xml_list->item);
97 XML_LIST_CMP(xml_list, "<deny>") {
98 deny = access_ll_new(deny);
99 deny->id = access_list->id++;
101 if (tmp_list->deny == NULL)
102 tmp_list->deny = deny;
103 XML_LIST_LOOP(xml_list, "<deny>") {
104 XML_LIST_CMP(xml_list, "<enabled>") {
105 xml_list = xml_list->next;
106 if (xml_list->type == XML_VALUE) {
107 if (!strcasecmp(xml_list->item, "false"))
108 deny->enabled = FALSE;
110 deny->enabled = TRUE;
113 XML_LIST_CMP(xml_list, "<comment>") {
114 xml_list = xml_list->next;
115 if (xml_list->type == XML_VALUE)
116 access_ll_insert(deny, xml_list->item, NULL, NULL, NULL, NULL, NULL);
118 XML_LIST_CMP(xml_list, "<ip>") {
119 xml_list = xml_list->next;
120 if (xml_list->type == XML_VALUE)
121 access_ll_insert(deny, NULL, xml_list->item, NULL, NULL, NULL, NULL);
123 XML_LIST_CMP(xml_list, "<access>") {
124 xml_list = xml_list->next;
125 if (xml_list->type == XML_VALUE)
126 access_ll_insert(deny, NULL, NULL, xml_list->item, NULL, NULL, NULL);
128 XML_LIST_CMP(xml_list, "<bypass>") {
129 xml_list = xml_list->next;
130 if (xml_list->type == XML_VALUE)
131 access_ll_insert(deny, NULL, NULL, NULL, xml_list->item, NULL, NULL);
133 XML_LIST_CMP(xml_list, "<username>") {
134 xml_list = xml_list->next;
135 if (xml_list->type == XML_VALUE)
136 access_ll_insert(deny, NULL, NULL, NULL, NULL, xml_list->item, NULL);
138 XML_LIST_CMP(xml_list, "<password>") {
139 xml_list = xml_list->next;
140 if (xml_list->type == XML_VALUE)
141 access_ll_insert(deny, NULL, NULL, NULL, NULL, NULL, xml_list->item);
145 XML_LIST_CMP(xml_list, "<policy>") {
146 xml_list = xml_list->next;
147 if (xml_list->type == XML_VALUE) {
148 if (!strcasecmp(xml_list->item, "allow"))
149 tmp_list->policy = POLICY_ALLOW;
150 else if (!strcasecmp(xml_list->item, "deny"))
151 tmp_list->policy = POLICY_DENY;
160 XML_LIST *access_xml(ACCESS_LIST * access_list, XML_LIST * xml_list)
164 struct ACCESS_LIST_LIST *al = NULL;
166 if (access_list == NULL)
169 pthread_rwlock_rdlock(&access_list->lock);
171 xml_list = xml_list_add(xml_list, "<access>", XML_TAG);
173 xml_list = xml_list_add(xml_list, "<policy>", XML_TAG);
174 xml_list = xml_list_add(xml_list, (access_list->policy == POLICY_ALLOW) ? "allow" : "deny", XML_VALUE);
175 xml_list = xml_list_add(xml_list, "</policy>", XML_TAG);
177 for (i = 0; i < 2; i++) {
180 al = access_list->allow;
183 al = access_list->deny;
187 for (; al; al = al->next) {
188 xml_list = xml_list_add(xml_list, (i == 0) ? "<allow>" : "<deny>", XML_TAG);
190 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG);
191 xml_list = xml_list_add(xml_list, (al->enabled == TRUE) ? "true" : "false", XML_VALUE);
192 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG);
194 if (al->comment != NULL) {
195 xml_list = xml_list_add(xml_list, "<comment>", XML_TAG);
196 ptr = string_to_xml(al->comment);
197 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
199 xml_list = xml_list_add(xml_list, "</comment>", XML_TAG);
201 if (al->ip != NULL) {
202 xml_list = xml_list_add(xml_list, "<ip>", XML_TAG);
203 ptr = string_to_xml(al->ip);
204 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
206 xml_list = xml_list_add(xml_list, "</ip>", XML_TAG);
208 if (al->username != NULL) {
209 xml_list = xml_list_add(xml_list, "<username>", XML_TAG);
210 ptr = string_to_xml(al->username);
211 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
213 xml_list = xml_list_add(xml_list, "</username>", XML_TAG);
215 if (al->password != NULL) {
216 xml_list = xml_list_add(xml_list, "<password>", XML_TAG);
217 ptr = string_to_xml(al->password);
218 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
220 xml_list = xml_list_add(xml_list, "</password>", XML_TAG);
222 if (al->bypass != 0) {
223 xml_list = xml_list_add(xml_list, "<bypass>", XML_TAG);
224 snprintf(buf, sizeof(buf), "%s,%s,%s,%s,%s,%s,%s,%s,%s", (al->bypass & FEATURE_FILTER) ? "filter" : "", (al->bypass & FEATURE_HEADER) ? "header" : "", (al->bypass & FEATURE_MIME) ? "mime" : "", (al->bypass & FEATURE_REDIRECT) ? "redirect" : "", (al->bypass & FEATURE_COOKIES) ? "cookies" : "", (al->bypass & FEATURE_REWRITE) ? "rewrite" : "", (al->bypass & FEATURE_EXTERNAL) ? "external" : "", (al->bypass & FEATURE_FORWARD) ? "forward" : "", (al->bypass & FEATURE_KEYWORDS) ? "keywords" : "");
225 xml_list = xml_list_add(xml_list, buf, XML_VALUE);
226 xml_list = xml_list_add(xml_list, "</bypass>", XML_TAG);
229 xml_list = xml_list_add(xml_list, "<access>", XML_TAG);
230 snprintf(buf, sizeof(buf), "%s,%s,%s,%s,%s,%s", (al->access & ACCESS_CONFIG) ? "config" : "", (al->access & ACCESS_PROXY) ? "proxy" : "", (al->access & ACCESS_CONNECT) ? "connect" : "", (al->access & ACCESS_HTTP) ? "http" : "", (al->access & ACCESS_TRANSPARENT) ? "transparent" : "", (al->access & ACCESS_BYPASS) ? "bypass" : "");
231 xml_list = xml_list_add(xml_list, buf, XML_VALUE);
232 xml_list = xml_list_add(xml_list, "</access>", XML_TAG);
234 xml_list = xml_list_add(xml_list, (i == 0) ? "</allow>" : "</deny>", XML_TAG);
238 xml_list = xml_list_add(xml_list, "</access>", XML_TAG);
240 pthread_rwlock_unlock(&access_list->lock);
246 free memory used by ACCESS_LIST linked list
248 void access_free(ACCESS_LIST * access_list)
253 access_ll_free(access_list->allow);
254 access_ll_free(access_list->deny);
256 pthread_rwlock_destroy(&access_list->lock);
261 void access_ll_free(struct ACCESS_LIST_LIST *al)
263 struct ACCESS_LIST_LIST *tmp;
270 FREE_AND_NULL(al->comment);
271 FREE_AND_NULL(al->ip);
272 FREE_AND_NULL(al->username);
273 FREE_AND_NULL(al->password);
281 check whether or not an ip address is allowed access based on the rules supplied
282 in the access_list linked list
284 int access_check(ACCESS_LIST * access_list, CONNECTION * connection, char *username, char *password)
286 int action = FALSE, result = TRUE, i, ret;
287 struct ACCESS_LIST_LIST *current = NULL;
292 pthread_rwlock_rdlock(&access_list->lock);
294 for (i = 0; i < 2; i++) {
296 if (access_list->policy == POLICY_ALLOW) {
297 current = access_list->deny;
301 current = access_list->allow;
305 } else if (result == action) {
306 if (access_list->policy == POLICY_ALLOW) {
307 current = access_list->allow;
310 current = access_list->deny;
316 for (; current != NULL; current = current->next) {
317 if (current->enabled == FALSE)
320 if (current->ie != NULL) {
321 ret = reg_exec(current->ie, connection->ip);
326 if (current->username != NULL) {
327 if (username != NULL) {
328 if (strcmp(current->username, username))
330 } else connection->authenticate = TRUE;
331 } else if (username == NULL)
332 connection->authenticate = FALSE;
334 if (current->password != NULL && password != NULL && strcmp(current->password, password))
337 connection->access = current->access;
338 connection->obypass = current->bypass;
345 if (result && current == NULL) {
346 /* policy is allow, and no deny rules matched; allow full access */
347 connection->access = ~0;
350 pthread_rwlock_unlock(&access_list->lock);
355 void access_ll_insert(struct ACCESS_LIST_LIST *x, char *a, char *b, char *c, char *d, char *e, char *f)
361 FREE_AND_NULL(x->comment);
364 x->comment = xstrdup(a);
369 FREE_AND_NULL(x->ip);
373 x->ie = reg_compile(b, REGFLAGS);
381 args = string_break(c, ',');
382 for (i = 0; args[i]; i++) {
383 if (!strcasecmp(args[i], "config"))
384 x->access |= ACCESS_CONFIG;
385 else if (!strcasecmp(args[i], "proxy"))
386 x->access |= ACCESS_PROXY;
387 else if (!strcasecmp(args[i], "connect"))
388 x->access |= ACCESS_CONNECT;
389 else if (!strcasecmp(args[i], "http"))
390 x->access |= ACCESS_HTTP;
391 else if (!strcasecmp(args[i], "transparent"))
392 x->access |= ACCESS_TRANSPARENT;
393 else if (!strcasecmp(args[i], "bypass"))
394 x->access |= ACCESS_BYPASS;
404 args = string_break(d, ',');
405 for (i = 0; args[i]; i++) {
406 if (!strcasecmp(args[i], "filter"))
407 x->bypass |= FEATURE_FILTER;
408 else if (!strcasecmp(args[i], "header"))
409 x->bypass |= FEATURE_HEADER;
410 else if (!strcasecmp(args[i], "mime"))
411 x->bypass |= FEATURE_MIME;
412 else if (!strcasecmp(args[i], "redirect"))
413 x->bypass |= FEATURE_REDIRECT;
414 else if (!strcasecmp(args[i], "cookies"))
415 x->bypass |= FEATURE_COOKIES;
416 else if (!strcasecmp(args[i], "rewrite"))
417 x->bypass |= FEATURE_REWRITE;
418 else if (!strcasecmp(args[i], "external"))
419 x->bypass |= FEATURE_EXTERNAL;
420 else if (!strcasecmp(args[i], "forward"))
421 x->bypass |= FEATURE_FORWARD;
422 else if (!strcasecmp(args[i], "keywords"))
423 x->bypass |= FEATURE_KEYWORDS;
430 FREE_AND_NULL(x->username);
433 x->username = xstrdup(e);
436 FREE_AND_NULL(x->password);
439 x->password = xstrdup(f);
443 struct ACCESS_LIST_LIST *access_ll_new(struct ACCESS_LIST_LIST *x)
446 x = xmalloc(sizeof(struct ACCESS_LIST_LIST));
449 while (x->next != NULL)
451 x->next = xmalloc(sizeof(struct ACCESS_LIST_LIST));
469 struct ACCESS_LIST_LIST *access_ll_delete(struct ACCESS_LIST_LIST *x)
471 struct ACCESS_LIST_LIST *start = x;
473 while (start->prev != NULL)
477 x->next->prev = x->prev;
479 x->prev->next = x->next;
485 FREE_AND_NULL(x->comment);
486 FREE_AND_NULL(x->ip);
487 FREE_AND_NULL(x->username);
488 FREE_AND_NULL(x->password);