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