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
24 FORWARD_LIST *forward_load(FORWARD_LIST * forward_list, XML_LIST * xml_list)
26 FORWARD_LIST *tmp_list = forward_list;
27 struct FORWARD_LIST_LIST *forward = NULL;
29 if (tmp_list == NULL) {
30 tmp_list = xmalloc(sizeof(FORWARD_LIST));
31 tmp_list->forward_list = NULL;
33 tmp_list->enabled = TRUE;
35 forward_list = tmp_list;
37 pthread_rwlock_init(&tmp_list->lock, NULL);
39 forward = tmp_list->forward_list;
41 while ((xml_list = xml_section(xml_list, "<forward>"))) {
42 XML_LIST_LOOP(xml_list, "<forward>") {
43 XML_LIST_CMP(xml_list, "<item>") {
44 forward = forward_list_new(forward);
45 forward->id = tmp_list->id++;
47 if (tmp_list->forward_list == NULL)
48 tmp_list->forward_list = forward;
50 XML_LIST_LOOP(xml_list, "<item>") {
51 XML_LIST_CMP(xml_list, "<enabled>") {
52 xml_list = xml_list->next;
53 if (xml_list->type == XML_VALUE) {
54 if (!strcasecmp(xml_list->item, "false"))
55 forward->enabled = FALSE;
57 forward->enabled = TRUE;
60 XML_LIST_CMP(xml_list, "<comment>") {
61 xml_list = xml_list->next;
62 if (xml_list->type == XML_VALUE)
63 forward_list_insert(forward, xml_list->item, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
65 XML_LIST_CMP(xml_list, "<host>") {
66 xml_list = xml_list->next;
67 if (xml_list->type == XML_VALUE)
68 forward_list_insert(forward, NULL, xml_list->item, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
70 XML_LIST_CMP(xml_list, "<file>") {
71 xml_list = xml_list->next;
72 if (xml_list->type == XML_VALUE)
73 forward_list_insert(forward, NULL, NULL, xml_list->item, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
75 XML_LIST_CMP(xml_list, "<proxy>") {
76 xml_list = xml_list->next;
77 if (xml_list->type == XML_VALUE)
78 forward_list_insert(forward, NULL, NULL, NULL, xml_list->item, NULL, NULL, NULL, NULL, NULL, NULL);
80 XML_LIST_CMP(xml_list, "<port>") {
81 xml_list = xml_list->next;
82 if (xml_list->type == XML_VALUE)
83 forward_list_insert(forward, NULL, NULL, NULL, NULL, xml_list->item, NULL, NULL, NULL, NULL, NULL);
85 XML_LIST_CMP(xml_list, "<type>") {
86 xml_list = xml_list->next;
87 if (xml_list->type == XML_VALUE)
88 forward_list_insert(forward, NULL, NULL, NULL, NULL, NULL, xml_list->item, NULL, NULL, NULL, NULL);
90 XML_LIST_CMP(xml_list, "<which>") {
91 xml_list = xml_list->next;
92 if (xml_list->type == XML_VALUE)
93 forward_list_insert(forward, NULL, NULL, NULL, NULL, NULL, NULL, xml_list->item, NULL, NULL, NULL);
95 XML_LIST_CMP(xml_list, "<username>") {
96 xml_list = xml_list->next;
97 if (xml_list->type == XML_VALUE)
98 forward_list_insert(forward, NULL, NULL, NULL, NULL, NULL, NULL, NULL, xml_list->item, NULL, NULL);
100 XML_LIST_CMP(xml_list, "<password>") {
101 xml_list = xml_list->next;
102 if (xml_list->type == XML_VALUE)
103 forward_list_insert(forward, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, xml_list->item, NULL);
105 XML_LIST_CMP(xml_list, "<domain>") {
106 xml_list = xml_list->next;
107 if (xml_list->type == XML_VALUE)
108 forward_list_insert(forward, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, xml_list->item);
111 XML_LIST_CMP(xml_list, "<enabled>") {
112 xml_list = xml_list->next;
113 if (xml_list->type == XML_VALUE) {
114 if (!strcasecmp(xml_list->item, "false"))
115 tmp_list->enabled = FALSE;
117 tmp_list->enabled = TRUE;
127 XML_LIST *forward_xml(FORWARD_LIST * forward_list, XML_LIST * xml_list)
130 struct FORWARD_LIST_LIST *fl;
132 pthread_rwlock_rdlock(&forward_list->lock);
134 xml_list = xml_list_add(xml_list, "<forward>", XML_TAG);
136 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG);
137 xml_list = xml_list_add(xml_list, (forward_list->enabled == TRUE) ? "true" : "false", XML_VALUE);
138 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG);
140 for (fl = forward_list->forward_list; fl; fl = fl->next) {
141 xml_list = xml_list_add(xml_list, "<item>", XML_TAG);
143 xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG);
144 xml_list = xml_list_add(xml_list, (fl->enabled == TRUE) ? "true" : "false", XML_VALUE);
145 xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG);
147 if (fl->comment != NULL) {
148 xml_list = xml_list_add(xml_list, "<comment>", XML_TAG);
149 ptr = string_to_xml(fl->comment);
150 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
152 xml_list = xml_list_add(xml_list, "</comment>", XML_TAG);
154 if (fl->host != NULL) {
155 xml_list = xml_list_add(xml_list, "<host>", XML_TAG);
156 ptr = string_to_xml(fl->host);
157 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
159 xml_list = xml_list_add(xml_list, "</host>", XML_TAG);
161 if (fl->file != NULL) {
162 xml_list = xml_list_add(xml_list, "<file>", XML_TAG);
163 ptr = string_to_xml(fl->file);
164 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
166 xml_list = xml_list_add(xml_list, "</file>", XML_TAG);
168 if (fl->proxy != NULL) {
169 xml_list = xml_list_add(xml_list, "<proxy>", XML_TAG);
170 ptr = string_to_xml(fl->proxy);
171 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
173 xml_list = xml_list_add(xml_list, "</proxy>", XML_TAG);
176 if (fl->port != -1) {
177 xml_list_add(xml_list, "<port>", XML_TAG);
178 snprintf(buf, sizeof(buf), "%d", fl->port);
179 xml_list = xml_list_add(xml_list, buf, XML_VALUE);
180 xml_list_add(xml_list, "</port>", XML_TAG);
182 if (fl->username != NULL) {
183 xml_list = xml_list_add(xml_list, "<username>", XML_TAG);
184 ptr = string_to_xml(fl->username);
185 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
187 xml_list = xml_list_add(xml_list, "</username>", XML_TAG);
189 if (fl->password != NULL) {
190 xml_list = xml_list_add(xml_list, "<password>", XML_TAG);
191 ptr = string_to_xml(fl->password);
192 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
194 xml_list = xml_list_add(xml_list, "</password>", XML_TAG);
196 if (fl->domain != NULL) {
197 xml_list = xml_list_add(xml_list, "<domain>", XML_TAG);
198 ptr = string_to_xml(fl->domain);
199 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
201 xml_list = xml_list_add(xml_list, "</domain>", XML_TAG);
205 xml_list = xml_list_add(xml_list, "<type>", XML_TAG);
206 xml_list = xml_list_add(xml_list, (fl->type == PROXY_NORMAL) ? "HTTP" : "SOCKS4", XML_VALUE);
207 xml_list = xml_list_add(xml_list, "</type>", XML_TAG);
209 xml_list = xml_list_add(xml_list, "<which>", XML_TAG);
210 snprintf(buf, sizeof(buf), "%s,%s", (fl->which & FORWARD_HTTP) ? "HTTP" : "", (fl->which & FORWARD_CONNECT) ? "CONNECT" : "");
211 xml_list = xml_list_add(xml_list, buf, XML_VALUE);
212 xml_list = xml_list_add(xml_list, "</which>", XML_TAG);
214 xml_list = xml_list_add(xml_list, "</item>", XML_TAG);
217 xml_list = xml_list_add(xml_list, "</forward>", XML_TAG);
219 pthread_rwlock_unlock(&forward_list->lock);
224 struct FORWARD_LIST_LIST *forward_list_new(struct FORWARD_LIST_LIST *x)
227 x = xmalloc(sizeof(struct FORWARD_LIST_LIST));
230 while (x->next != NULL)
232 x->next = xmalloc(sizeof(struct FORWARD_LIST_LIST));
242 x->type = PROXY_NORMAL;
255 void forward_list_insert(struct FORWARD_LIST_LIST *x, char *a, char *b, char *c, char *d, char *e, char *f, char *g, char *h, char *i, char *j)
261 FREE_AND_NULL(x->comment);
264 x->comment = xstrdup(a);
269 FREE_AND_NULL(x->host);
272 x->he = reg_compile(b, REGFLAGS);
273 x->host = xstrdup(b);
280 FREE_AND_NULL(x->file);
283 x->fe = reg_compile(c, REGFLAGS);
284 x->file = xstrdup(c);
289 FREE_AND_NULL(x->proxy);
292 x->proxy = xstrdup(d);
301 x->type = PROXY_NORMAL;
304 if (!strcasecmp(f, "HTTP"))
305 x->type = PROXY_NORMAL;
306 else if (!strcasecmp(f, "SOCKS4"))
307 x->type = PROXY_SOCKS4;
314 args = string_break(g, ',');
315 for (z = 0; args[z]; z++) {
316 if (!strcasecmp(args[z], "HTTP"))
317 x->which |= FORWARD_HTTP;
318 else if (!strcasecmp(args[z], "CONNECT"))
319 x->which |= FORWARD_CONNECT;
327 FREE_AND_NULL(x->username);
330 x->username = xstrdup(h);
334 FREE_AND_NULL(x->password);
337 x->password = xstrdup(i);
341 FREE_AND_NULL(x->domain);
344 x->domain = xstrdup(j);
348 struct FORWARD_LIST_LIST *forward_list_delete(struct FORWARD_LIST_LIST *x)
350 struct FORWARD_LIST_LIST *start = x;
352 while (start->prev != NULL)
356 x->next->prev = x->prev;
358 x->prev->next = x->next;
366 FREE_AND_NULL(x->comment);
367 FREE_AND_NULL(x->host);
368 FREE_AND_NULL(x->file);
369 FREE_AND_NULL(x->proxy);
370 FREE_AND_NULL(x->username);
371 FREE_AND_NULL(x->password);
372 FREE_AND_NULL(x->domain);
377 void forward_list_free(struct FORWARD_LIST_LIST *fl)
379 struct FORWARD_LIST_LIST *tmp;
388 FREE_AND_NULL(fl->comment);
389 FREE_AND_NULL(fl->host);
390 FREE_AND_NULL(fl->file);
391 FREE_AND_NULL(fl->proxy);
392 FREE_AND_NULL(fl->username);
393 FREE_AND_NULL(fl->password);
394 FREE_AND_NULL(fl->domain);
402 void forward_free(FORWARD_LIST * forward_list)
404 if (forward_list == NULL)
407 forward_list_free(forward_list->forward_list);
412 int forward_do(FORWARD_LIST * forward_list, CONNECTION * connection)
415 struct FORWARD_LIST_LIST *forward;
417 if (!forward_list || connection->bypass & FEATURE_FORWARD)
420 pthread_rwlock_rdlock(&forward_list->lock);
422 if (forward_list->enabled == FALSE) {
423 pthread_rwlock_unlock(&forward_list->lock);
428 for (forward = forward_list->forward_list; forward; forward = forward->next) {
429 if (forward->enabled == FALSE)
432 if (((connection->header->type == HTTP_PROXY || connection->header->type == HTTP_REQUEST) && !(forward->which & FORWARD_HTTP)) || ((connection->header->type == HTTP_CONNECT) && !(forward->which & FORWARD_CONNECT)))
435 if (forward->he != NULL) {
436 ret = reg_exec(forward->he, connection->header->host);
441 if (forward->fe != NULL) {
442 ret = reg_exec(forward->fe, connection->header->file);
447 /* allow entries with no proxy host to match, but don't do anything */
448 if (forward->proxy == NULL)
451 connection->proxy_type = forward->type;
452 connection->proxy_host = xstrdup(forward->proxy);
453 if (forward->username != NULL) connection->proxy_username = xstrdup(forward->username);
454 if (forward->password != NULL) connection->proxy_password = xstrdup(forward->password);
455 if (forward->domain != NULL) connection->proxy_domain = xstrdup(forward->domain);
456 connection->proxy_port = (forward->port != -1) ? forward->port : (forward->type == PROXY_SOCKS4) ? 443 : 3128;
458 pthread_rwlock_unlock(&forward_list->lock);
463 pthread_rwlock_unlock(&forward_list->lock);