1 /*
2 * ffproxy (c) 2002, 2003 Niklas Olmes <niklas@noxa.de>
3 * http://faith.eu.org
4 *
5 * $Id: filter.c,v 2.1 2004/12/31 08:59:15 niklas Exp $
6 *
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 675
19 * Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <stdio.h>
23 #include "configure.h"
24 #ifdef HAVE_STDLIB_H
25 # include <stdlib.h>
26 #endif
27 #include <string.h>
28
29 #include "req.h"
30 #include "dbs.h"
31 #include "print.h"
32 #include "alloc.h"
33 #include "http.h"
34 #include "regex.h"
35 #include "filter.h"
36
37 static void rotate(int, char *[]);
38
39 extern char loop_header[];
40
41 int
filter_request(struct req * r)42 filter_request(struct req * r)
43 {
44 size_t i;
45 int j;
46
47 i = 0;
48 while (f_host[i] != NULL)
49 if (do_regex(r->host, f_host[i++]) == 0)
50 return 1;
51
52 i = 0;
53 while (f_url[i] != NULL)
54 if (do_regex(r->url, f_url[i++]) == 0)
55 return 1;
56
57 i = 0;
58 start_over:
59 while (r->header[i] != NULL && i < sizeof(r->header) - 2) {
60 DEBUG(("filter_request() => header entry %d (%s)", i, r->header[i]));
61
62 if (strncasecmp(r->header[i], loop_header, strlen(loop_header)) == 0) {
63 DEBUG(("filter_request() => LOOP DETECTED"));
64 r->loop = 1;
65 return -1;
66 }
67 if (http_parse(r, r->header[i]) == 0)
68 goto skip;
69
70 j = 0;
71 while (f_hdr_drop[j] != NULL)
72 if (do_regex(r->header[i], f_hdr_drop[j++]) == 0)
73 return 1;
74
75 j = 0;
76 while (f_hdr_entry[j] != NULL) {
77 if (strncasecmp(r->header[i], f_hdr_entry[j], strlen(f_hdr_entry[j])) == 0) {
78 rotate(i, r->header);
79 goto start_over;
80 }
81 j++;
82 }
83
84 j = 0;
85 while (f_hdr_match[j] != NULL) {
86 if (do_regex(r->header[i], f_hdr_match[j]) == 0) {
87 rotate(i, r->header);
88 goto start_over;
89 }
90 j++;
91 }
92
93 skip:
94 i++;
95 }
96
97 if (r->header[i] != NULL)
98 free(r->header[i]);
99
100 r->header[i] = (char *) my_alloc(strlen(loop_header) + 1);
101 (void) strcpy(r->header[i], loop_header);
102
103 DEBUG(("filter_request() => added loop header[%d] (%s)", i, r->header[i]));
104
105 i++;
106 j = 0;
107 while (f_hdr_add[j] != NULL && i < sizeof(r->header) - 1) {
108 r->header[i] = (char *) my_alloc(strlen(f_hdr_add[j]) + 1);
109 (void) strcpy(r->header[i], f_hdr_add[j]);
110
111 DEBUG(("filter_request() => added header[%d] (%s)", i, r->header[i]));
112 i++, j++;
113 }
114 r->header[i] = NULL;
115
116 DEBUG(("filter_request() => done, request ok"));
117
118 return 0;
119 }
120
121 static const char http_pkalive[] = "Proxy-Connection: keep-alive";
122 static const char http_kalive[] = "Connection: keep-alive";
123
124 int
filter_remote(struct req * r)125 filter_remote(struct req * r)
126 {
127 size_t i;
128 int j;
129
130 i = 0;
131 start_over:
132 while (r->header[i] != NULL) {
133 DEBUG(("filter_remote() => remote header entry %d (%s)", i, r->header[i]));
134
135 if (strncasecmp(r->header[i], loop_header, strlen(loop_header)) == 0) {
136 DEBUG(("filter_request() => LOOP DETECTED"));
137 r->loop = 1;
138 return -1;
139 }
140 if (http_parse(r, r->header[i]) == 0)
141 goto skip;
142
143 j = 0;
144 while (f_rhdr_drop[j] != NULL)
145 if (do_regex(r->header[i], f_rhdr_drop[j++]) == 0)
146 return 1;
147
148 j = 0;
149 while (f_rhdr_entry[j] != NULL) {
150 if (strncasecmp(r->header[i], f_rhdr_entry[j], strlen(f_rhdr_entry[j])) == 0) {
151 rotate(i, r->header);
152 goto start_over;
153 }
154 j++;
155 }
156
157 j = 0;
158 while (f_rhdr_match[j] != NULL) {
159 if (do_regex(r->header[i], f_rhdr_match[j]) == 0) {
160 rotate(i, r->header);
161 goto start_over;
162 }
163 j++;
164 }
165 skip:
166 i++;
167
168 }
169 if(r->kalive && i - 2 < sizeof(r->header)) {
170 r->header[i] = (char *) my_alloc(strlen(http_pkalive) + 1);
171 (void) strcpy(r->header[i], http_pkalive);
172 r->header[++i] = (char *) my_alloc(strlen(http_kalive) + 1);
173 (void) strcpy(r->header[i], http_kalive);
174 r->header[++i] = NULL;
175 } else if(r->kalive) {
176 r->kalive = 0;
177 }
178
179 DEBUG(("filter_remote() => done, request ok"));
180
181 return 0;
182 }
183
184
185 static void
rotate(int i,char * a[])186 rotate(int i, char *a[])
187 {
188 if (a[i] == NULL) {
189 DEBUG(("rotate() => entry to rotate, %d, is NULL", i));
190 } else {
191 DEBUG(("rotate() => freeing a[%d] == (%s)", i, a[i]));
192 free(a[i]);
193 a[i] = a[i + 1];
194 if (a[i + 1] != NULL) {
195 i++;
196 while (a[i] != NULL) {
197 a[i] = a[i + 1];
198 i++;
199 }
200 }
201 }
202
203 DEBUG(("rotate() => done"));
204 }
205