1 :
2 : #include "httpd.h"
3 : #include "httpd_policy.h"
4 :
5 : #define EX_UTILS_NO_FUNCS 1
6 : #include "ex_utils.h"
7 :
8 : #include "mk.h"
9 :
10 : #include "match_req.h"
11 :
12 : static int httpd__match_request_tst_op_d1(Conf_parse *conf, Conf_token *token,
13 : int *matches, int prev_match,
14 : void *passed_data)
15 52024 : {
16 52024 : struct Httpd__policy_req_tst_data *data = passed_data;
17 :
18 52024 : return (httpd_match_request_tst_d1(data->con, data->req, conf, token,
19 : matches, prev_match,
20 : httpd__match_request_tst_op_d1, data));
21 : }
22 :
23 : int httpd_match_request_sc_tst_d1(struct Con *con, Httpd_req_data *req,
24 : Conf_parse *conf, Conf_token *token,
25 : int *matches, int prev_match)
26 563952 : {
27 : struct Httpd__policy_req_tst_data data[1];
28 :
29 563952 : data->con = con;
30 563952 : data->req = req;
31 :
32 563952 : return (httpd_match_request_tst_d1(con, req, conf, token,
33 : matches, prev_match,
34 : httpd__match_request_tst_op_d1, data));
35 : }
36 :
37 : /* match tokens against a passed in header */
38 : static int httpd_match__req_hdr(Httpd_req_data *req,
39 : Conf_parse *conf, Conf_token *token,
40 : const Vstr_base *s1, size_t pos, size_t len,
41 : int flags)
42 19608 : {
43 19608 : if (!conf_token_list_num(token, token->depth_num))
44 1568 : return (!!pos); /* does the header exist */
45 :
46 18040 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
47 :
48 : /* FIXME: add [] tests for search etc.? */
49 :
50 18040 : switch (flags)
51 : {
52 : case HTTPD_MATCH__TYPE_REQ_HDR_IM:
53 : case HTTPD_MATCH__TYPE_REQ_HDR_INM: /* disallow weak etag's? */
54 : {
55 192 : const Vstr_sect_node *val = conf_token_value(token);
56 :
57 192 : return (val && httpd_match_etags(req, conf->data, val->pos, val->len,
58 : s1, pos, len, TRUE));
59 : }
60 : case HTTPD_MATCH__TYPE_REQ_HDR_EQ:
61 352 : return (conf_token_cmp_val_eq(conf, token, s1, pos, len));
62 : case HTTPD_MATCH__TYPE_REQ_HDR_CASE_EQ:
63 14520 : return (conf_token_cmp_case_val_eq(conf, token, s1, pos, len));
64 : case HTTPD_MATCH__TYPE_REQ_HDR_AE:
65 2976 : http_parse_accept_encoding(req, TRUE);
66 :
67 : if (0) { }
68 2976 : else if (conf_token_cmp_val_cstr_eq(conf, token, "identity"))
69 0 : return (!!req->content_enc_identity);
70 2976 : else if (conf_token_cmp_val_cstr_eq(conf, token, "gzip"))
71 1504 : return (!!req->content_enc_gzip);
72 1472 : else if (conf_token_cmp_val_cstr_eq(conf, token, "bzip2"))
73 1472 : return (!!req->content_enc_bzip2);
74 :
75 0 : return (FALSE);
76 : }
77 :
78 0 : ASSERT_NOT_REACHED();
79 :
80 0 : return (FALSE);
81 : }
82 :
83 : int httpd_match_request_tst_d1(struct Con *con, Httpd_req_data *req,
84 : Conf_parse *conf, Conf_token *token,
85 : int *matches, int prev_match,
86 : int (*tst_func)(Conf_parse *, Conf_token *,
87 : int *, int, void *),
88 : void *data)
89 703736 : {
90 703736 : Vstr_base *http_data = con->evnt->io_r;
91 703736 : Vstr_base *http_multi_data = req->http_hdrs->multi->comb;
92 703736 : int clist = FALSE;
93 :
94 351868 : ASSERT(con && req);
95 351868 : ASSERT(matches);
96 :
97 703736 : CONF_SC_TOGGLE_CLIST_VAR(clist);
98 :
99 703736 : if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
100 : {
101 169484 : unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
102 169484 : unsigned int nxt = 0;
103 169484 : Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
104 :
105 169484 : switch (type)
106 : {
107 : case HTTPD_POLICY_REQ_PATH_BEG:
108 : case HTTPD_POLICY_REQ_PATH_END:
109 : case HTTPD_POLICY_REQ_PATH_EQ:
110 :
111 : case HTTPD_POLICY_REQ_NAME_BEG:
112 : case HTTPD_POLICY_REQ_NAME_END:
113 : case HTTPD_POLICY_REQ_NAME_EQ:
114 :
115 : case HTTPD_POLICY_REQ_BWEN_BEG:
116 : case HTTPD_POLICY_REQ_BWEN_END:
117 : case HTTPD_POLICY_REQ_BWEN_EQ:
118 :
119 : case HTTPD_POLICY_REQ_BWES_BEG:
120 : case HTTPD_POLICY_REQ_BWES_END:
121 : case HTTPD_POLICY_REQ_BWES_EQ:
122 :
123 : case HTTPD_POLICY_REQ_EXTN_BEG:
124 : case HTTPD_POLICY_REQ_EXTN_END:
125 : case HTTPD_POLICY_REQ_EXTN_EQ:
126 :
127 : case HTTPD_POLICY_REQ_EXTS_BEG:
128 : case HTTPD_POLICY_REQ_EXTS_END:
129 : case HTTPD_POLICY_REQ_EXTS_EQ:
130 : {
131 167828 : size_t pos = 1;
132 167828 : size_t len = req->fname->len;
133 167828 : unsigned int lim = httpd_policy_path_req2lim(type);
134 :
135 167828 : vstr_ref_add(ref);
136 167828 : *matches = httpd_policy_path_lim_eq(req->fname, &pos, &len, lim,
137 : req->vhost_prefix_len, ref);
138 : }
139 167828 : break;
140 :
141 : case HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ:
142 : {
143 828 : struct sockaddr *sa = CON_CEVNT_SA(con);
144 828 : *matches = httpd_policy_ipv4_cidr_eq(con, req, ref->ptr, sa);
145 : }
146 828 : break;
147 :
148 : case HTTPD_POLICY_SERVER_IPV4_CIDR_EQ:
149 : {
150 828 : struct sockaddr *sa = CON_SEVNT_SA(con);
151 828 : *matches = httpd_policy_ipv4_cidr_eq(con, req, ref->ptr, sa);
152 : }
153 828 : break;
154 :
155 : default:
156 0 : vstr_ref_del(ref);
157 0 : return (FALSE);
158 : }
159 :
160 169484 : vstr_ref_del(ref);
161 169484 : if (nxt)
162 169484 : return (conf_parse_num_token(conf, token, nxt));
163 : }
164 :
165 534252 : else if (OPT_SERV_SYM_EQ("connection-policy-eq") ||
166 : OPT_SERV_SYM_EQ("connection-policy=="))
167 0 : OPT_SERV_X_EQ(con->policy->s->policy_name);
168 646104 : else if (OPT_SERV_SYM_EQ("policy-eq") || OPT_SERV_SYM_EQ("policy=="))
169 223704 : OPT_SERV_X_EQ(req->policy->s->policy_name);
170 310548 : else if (OPT_SERV_SYM_EQ("connection-tag-eq") ||
171 : OPT_SERV_SYM_EQ("connection-tag=="))
172 0 : OPT_SERV_X_EQ(con->tag);
173 435408 : else if (OPT_SERV_SYM_EQ("tag-eq") || OPT_SERV_SYM_EQ("tag=="))
174 249720 : OPT_SERV_X_EQ(req->tag);
175 60828 : else if (OPT_SERV_SYM_EQ("client-ipv4-cidr-eq") ||
176 : OPT_SERV_SYM_EQ("client-ipv4-cidr==")) /* NOTE: need ipv6 */
177 4 : return (httpd_policy_ipv4_make(con, req, conf, token,
178 : HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ,
179 : CON_CEVNT_SA(con), matches));
180 60824 : else if (OPT_SERV_SYM_EQ("server-ipv4-cidr-eq") ||
181 : OPT_SERV_SYM_EQ("server-ipv4-cidr==")) /* NOTE: need ipv6 */
182 260 : return (httpd_policy_ipv4_make(con, req, conf, token,
183 : HTTPD_POLICY_SERVER_IPV4_CIDR_EQ,
184 : CON_SEVNT_SA(con), matches));
185 60980 : else if (OPT_SERV_SYM_EQ("server-ipv4-port-eq") ||
186 : OPT_SERV_SYM_EQ("server-ipv4-port=="))
187 : {
188 832 : struct sockaddr *sa = CON_SEVNT_SA(con);
189 832 : unsigned int tst_port = 0;
190 :
191 832 : OPT_SERV_X_SINGLE_UINT(tst_port);
192 :
193 832 : if (sa->sa_family != AF_INET)
194 0 : *matches = FALSE;
195 : else
196 : {
197 832 : struct sockaddr_in *sin = CON_SEVNT_SA_IN4(con);
198 832 : *matches = tst_port == ntohs(sin->sin_port);
199 : }
200 : }
201 60148 : else if (OPT_SERV_SYM_EQ("server-ipv6-port-eq") ||
202 : OPT_SERV_SYM_EQ("server-ipv6-port=="))
203 : {
204 832 : struct sockaddr *sa = CON_SEVNT_SA(con);
205 832 : unsigned int tst_port = 0;
206 :
207 832 : OPT_SERV_X_SINGLE_UINT(tst_port);
208 :
209 832 : if (sa->sa_family != AF_INET6)
210 832 : *matches = FALSE;
211 : else
212 : {
213 0 : struct sockaddr_in6 *sin6 = CON_SEVNT_SA_IN6(con);
214 0 : *matches = tst_port == ntohs(sin6->sin6_port);
215 : }
216 : }
217 60788 : else if (OPT_SERV_SYM_EQ("protect-vary") || OPT_SERV_SYM_EQ("save-vary"))
218 : {
219 1888 : unsigned int depth = token->depth_num;
220 1888 : int con_vary_star = con->vary_star;
221 1888 : int req_vary_star = req->vary_star;
222 1888 : int req_vary_a = req->vary_a;
223 1888 : int req_vary_ac = req->vary_ac;
224 1888 : int req_vary_ae = req->vary_ae;
225 1888 : int req_vary_al = req->vary_al;
226 1888 : int req_vary_rf = req->vary_rf;
227 1888 : int req_vary_ua = req->vary_ua;
228 1888 : int req_vary_ims = req->vary_ims;
229 1888 : int req_vary_ius = req->vary_ius;
230 1888 : int req_vary_ir = req->vary_ir;
231 1888 : int req_vary_im = req->vary_im;
232 1888 : int req_vary_inm = req->vary_inm;
233 1888 : int req_vary_xm = req->vary_xm;
234 :
235 944 : ASSERT(*matches);
236 4720 : while (*matches && conf_token_list_num(token, depth))
237 : {
238 1888 : CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
239 :
240 1888 : if (!httpd_match_request_tst_d1(con, req, conf, token,
241 : matches, prev_match, tst_func, data))
242 0 : return (FALSE);
243 : }
244 :
245 1888 : con->vary_star = con_vary_star;
246 1888 : req->vary_star = req_vary_star;
247 1888 : req->vary_a = req_vary_a;
248 1888 : req->vary_ac = req_vary_ac;
249 1888 : req->vary_ae = req_vary_ae;
250 1888 : req->vary_al = req_vary_al;
251 1888 : req->vary_rf = req_vary_rf;
252 1888 : req->vary_ua = req_vary_ua;
253 1888 : req->vary_ims = req_vary_ims;
254 1888 : req->vary_ius = req_vary_ius;
255 1888 : req->vary_ir = req_vary_ir;
256 1888 : req->vary_im = req_vary_im;
257 1888 : req->vary_inm = req_vary_inm;
258 1888 : req->vary_xm = req_vary_xm;
259 : }
260 57012 : else if (OPT_SERV_SYM_EQ("Accept-Encoding:"))
261 : { /* in theory could call http_parse_accept_encoding() and make sure
262 : * they are allowing gzip ... but non-zero len is probably fine for now */
263 4480 : Vstr_sect_node *h_ae = req->http_hdrs->multi->hdr_accept_encoding;
264 :
265 4480 : req->vary_ae = TRUE;
266 4480 : *matches = httpd_match__req_hdr(req, conf, token,
267 : http_multi_data, h_ae->pos, h_ae->len,
268 : HTTPD_MATCH__TYPE_REQ_HDR_AE);
269 : }
270 52532 : else if (OPT_SERV_SYM_EQ("If-Modified-Since:"))
271 : {
272 96 : Vstr_sect_node *h_ims = req->http_hdrs->hdr_if_modified_since;
273 :
274 96 : req->vary_ims = TRUE;
275 96 : *matches = httpd_match__req_hdr(req, conf, token,
276 : http_data, h_ims->pos, h_ims->len,
277 : HTTPD_MATCH__TYPE_REQ_HDR_EQ);
278 : }
279 52436 : else if (OPT_SERV_SYM_EQ("If-Unmodified-Since:"))
280 : {
281 96 : Vstr_sect_node *h_ius = req->http_hdrs->hdr_if_unmodified_since;
282 :
283 96 : req->vary_ius = TRUE;
284 96 : *matches = httpd_match__req_hdr(req, conf, token,
285 : http_data, h_ius->pos, h_ius->len,
286 : HTTPD_MATCH__TYPE_REQ_HDR_EQ);
287 : }
288 52340 : else if (OPT_SERV_SYM_EQ("If-Range:"))
289 : {
290 96 : Vstr_sect_node *h_ir = req->http_hdrs->hdr_if_range;
291 :
292 96 : req->vary_ir = TRUE;
293 96 : *matches = httpd_match__req_hdr(req, conf, token,
294 : http_data, h_ir->pos, h_ir->len,
295 : HTTPD_MATCH__TYPE_REQ_HDR_EQ);
296 : }
297 52244 : else if (OPT_SERV_SYM_EQ("If-Match:"))
298 : {
299 96 : Vstr_sect_node *h_im = req->http_hdrs->multi->hdr_if_match;
300 :
301 96 : req->vary_im = TRUE;
302 96 : *matches = httpd_match__req_hdr(req, conf, token,
303 : http_multi_data, h_im->pos, h_im->len,
304 : HTTPD_MATCH__TYPE_REQ_HDR_IM);
305 : }
306 52148 : else if (OPT_SERV_SYM_EQ("If-None-Match:"))
307 : {
308 96 : Vstr_sect_node *h_inm = req->http_hdrs->multi->hdr_if_none_match;
309 :
310 96 : req->vary_inm = TRUE;
311 96 : *matches = httpd_match__req_hdr(req, conf, token,
312 : http_multi_data, h_inm->pos, h_inm->len,
313 : HTTPD_MATCH__TYPE_REQ_HDR_INM);
314 : }
315 52052 : else if (OPT_SERV_SYM_EQ("X-Moz:"))
316 : { /* in theory could call http_parse_accept_encoding() and make sure
317 : * they are allowing gzip ... but non-zero len is probably fine for now */
318 64 : Vstr_sect_node *h_xm = req->http_hdrs->hdr_x_moz;
319 :
320 64 : req->vary_xm = TRUE;
321 64 : *matches = httpd_match__req_hdr(req, conf, token,
322 : http_data, h_xm->pos, h_xm->len,
323 : HTTPD_MATCH__TYPE_REQ_HDR_EQ);
324 : }
325 59216 : else if (OPT_SERV_SYM_EQ("Host:") ||
326 : /* compat */
327 : OPT_SERV_SYM_EQ("hostname-eq") || OPT_SERV_SYM_EQ("hostname=="))
328 : { /* doesn't do escaping because DNS is ASCII */
329 14456 : Vstr_sect_node *h_h = req->http_hdrs->hdr_host;
330 14456 : Vstr_base *d_h = req->policy->default_hostname;
331 :
332 14456 : if (h_h->len)
333 9800 : *matches = httpd_match__req_hdr(req, conf, token,
334 : http_data, h_h->pos, h_h->len,
335 : HTTPD_MATCH__TYPE_REQ_HDR_CASE_EQ);
336 : else
337 4656 : *matches = httpd_match__req_hdr(req, conf, token,
338 : d_h, 1, d_h->len,
339 : HTTPD_MATCH__TYPE_REQ_HDR_CASE_EQ);
340 : }
341 38732 : else if (OPT_SERV_SYM_EQ("port-eq") || OPT_SERV_SYM_EQ("port=="))
342 : {
343 2400 : Vstr_sect_node *h_h = req->http_hdrs->hdr_host;
344 2400 : unsigned int tmp = 0;
345 :
346 2400 : OPT_SERV_X_SINGLE_UINT(tmp);
347 :
348 2400 : if (h_h->len)
349 0 : *matches = tmp == req->http_host_port;
350 : else
351 : { /* FIXME: ipv6 */
352 2400 : struct sockaddr_in *sinv4 = EVNT_ACPT_SA_IN4(con->evnt);
353 :
354 1200 : ASSERT(sinv4->sin_family == AF_INET);
355 2400 : *matches = tmp == ntohs(sinv4->sin_port);
356 : }
357 : }
358 35196 : else if (OPT_SERV_SYM_EQ("User-Agent:") ||
359 : /* compat */
360 : OPT_SERV_SYM_EQ("user-agent-eq") || OPT_SERV_SYM_EQ("UA-eq") ||
361 : OPT_SERV_SYM_EQ("user-agent==") || OPT_SERV_SYM_EQ("UA=="))
362 : { /* doesn't do escaping because URLs are ASCII */
363 64 : Vstr_sect_node *h_ua = req->http_hdrs->hdr_ua;
364 :
365 64 : req->vary_ua = TRUE;
366 64 : *matches = httpd_match__req_hdr(req, conf, token,
367 : http_data, h_ua->pos, h_ua->len,
368 : HTTPD_MATCH__TYPE_REQ_HDR_EQ);
369 : }
370 35196 : else if (OPT_SERV_SYM_EQ("user-agent-search-eq") || /* required compat */
371 : OPT_SERV_SYM_EQ("user-agent-search==") ||
372 : OPT_SERV_SYM_EQ("user-agent-srch-eq") ||
373 : OPT_SERV_SYM_EQ("user-agent-srch==") ||
374 : OPT_SERV_SYM_EQ("UA-srch-eq") ||
375 : OPT_SERV_SYM_EQ("UA-srch=="))
376 : { /* doesn't do escaping because URLs are ASCII */
377 128 : Vstr_sect_node *h_ua = req->http_hdrs->hdr_ua;
378 :
379 128 : req->vary_ua = TRUE;
380 128 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
381 128 : *matches = !!conf_token_srch_val(conf, token, http_data,
382 : h_ua->pos, h_ua->len);
383 : }
384 35004 : else if (OPT_SERV_SYM_EQ("Referer:") || OPT_SERV_SYM_EQ("Referrer:") ||
385 : /* compat */
386 : OPT_SERV_SYM_EQ("referrer-eq") || OPT_SERV_SYM_EQ("referer-eq") ||
387 : OPT_SERV_SYM_EQ("referrer==") || OPT_SERV_SYM_EQ("referer=="))
388 : { /* doesn't do escaping because URLs are ASCII */
389 64 : Vstr_sect_node *h_ref = req->http_hdrs->hdr_referer;
390 :
391 64 : req->vary_rf = TRUE;
392 64 : *matches = httpd_match__req_hdr(req, conf, token,
393 : http_data, h_ref->pos, h_ref->len,
394 : HTTPD_MATCH__TYPE_REQ_HDR_CASE_EQ);
395 : }
396 35068 : else if (OPT_SERV_SYM_EQ("referrer-beg") || OPT_SERV_SYM_EQ("referer-beg"))
397 : /* required compat */
398 : { /* doesn't do escaping because URLs are ASCII */
399 192 : Vstr_sect_node *h_ref = req->http_hdrs->hdr_referer;
400 :
401 192 : req->vary_rf = TRUE;
402 192 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
403 192 : *matches = conf_token_cmp_case_val_beg_eq(conf, token, http_data,
404 : h_ref->pos, h_ref->len);
405 : }
406 34940 : else if (OPT_SERV_SYM_EQ("referrer-search-eq") || /* required compat */
407 : OPT_SERV_SYM_EQ("referrer-search==") ||
408 : OPT_SERV_SYM_EQ("referrer-srch-eq") ||
409 : OPT_SERV_SYM_EQ("referrer-srch==") ||
410 : OPT_SERV_SYM_EQ("referer-search-eq") ||
411 : OPT_SERV_SYM_EQ("referer-search==") ||
412 : OPT_SERV_SYM_EQ("referer-srch-eq") ||
413 : OPT_SERV_SYM_EQ("referer-srch=="))
414 : { /* doesn't do escaping because URLs are ASCII */
415 256 : Vstr_sect_node *h_ref = req->http_hdrs->hdr_referer;
416 :
417 256 : req->vary_rf = TRUE;
418 256 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
419 256 : *matches = !!conf_token_srch_case_val(conf, token,
420 : http_data, h_ref->pos, h_ref->len);
421 : }
422 34428 : else if (OPT_SERV_SYM_EQ("http-0.9-eq") || OPT_SERV_SYM_EQ("http-0.9==") ||
423 : OPT_SERV_SYM_EQ("http-vers-eq-0.9") ||
424 : OPT_SERV_SYM_EQ("http-vers==0.9") ||
425 : OPT_SERV_SYM_EQ("http-version-eq-0.9") ||
426 : OPT_SERV_SYM_EQ("http-version==0.9"))
427 0 : *matches = req->ver_0_9;
428 34428 : else if (OPT_SERV_SYM_EQ("http-1.0-eq") || OPT_SERV_SYM_EQ("http-1.0==") ||
429 : OPT_SERV_SYM_EQ("http-vers-eq-1.0") ||
430 : OPT_SERV_SYM_EQ("http-vers==1.0") ||
431 : OPT_SERV_SYM_EQ("http-version-eq-1.0") ||
432 : OPT_SERV_SYM_EQ("http-version==1.0"))
433 0 : *matches = !req->ver_0_9 && !req->ver_1_1;
434 34428 : else if (OPT_SERV_SYM_EQ("http-1.1-eq") || OPT_SERV_SYM_EQ("http-1.1==") ||
435 : OPT_SERV_SYM_EQ("http-vers-eq-1.1") ||
436 : OPT_SERV_SYM_EQ("http-vers==1.1") ||
437 : OPT_SERV_SYM_EQ("http-version-eq-1.1") ||
438 : OPT_SERV_SYM_EQ("http-version==1.1"))
439 : {
440 0 : *matches = req->ver_1_1;
441 0 : ASSERT(!req->ver_0_9 || !*matches);
442 : }
443 34428 : else if (OPT_SERV_SYM_EQ("http-vers>=1.0") ||
444 : OPT_SERV_SYM_EQ("http-version>=1.0"))
445 0 : *matches = !req->ver_0_9;
446 34428 : else if (OPT_SERV_SYM_EQ("http-vers>1.0") ||
447 : OPT_SERV_SYM_EQ("http-version>1.0") ||
448 : OPT_SERV_SYM_EQ("http-vers>=1.1") ||
449 : OPT_SERV_SYM_EQ("http-version>=1.1"))
450 : {
451 0 : *matches = HTTPD_VER_GE_1_1(req);
452 0 : ASSERT(!req->ver_0_9 || !*matches);
453 : }
454 34428 : else if (OPT_SERV_SYM_EQ("http-vers>1.1") ||
455 : OPT_SERV_SYM_EQ("http-vers>=1.2"))
456 : {
457 0 : *matches = req->ver_1_x;
458 0 : ASSERT(!req->ver_0_9 || !*matches);
459 : }
460 34556 : else if (OPT_SERV_SYM_EQ("method-eq") || OPT_SERV_SYM_EQ("method=="))
461 : { /* doesn't do escaping because methods are ASCII */
462 128 : Vstr_sect_node *meth = VSTR_SECTS_NUM(req->sects, 1);
463 :
464 128 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
465 128 : *matches = conf_token_cmp_val_eq(conf, token,
466 : http_data, meth->pos, meth->len);
467 : }
468 34332 : else if (OPT_SERV_SYM_EQ("tm-dow-eq") || OPT_SERV_SYM_EQ("tm-dow=="))
469 : { /* so we can do msff :) */
470 32 : Opt_serv_opts *opts = req->policy->s->beg;
471 32 : Httpd_opts *hopts = (Httpd_opts *)opts;
472 32 : const struct tm *tm = date_gmtime(hopts->date, req->now);
473 32 : int tmp = 0;
474 :
475 32 : if (!tm) return (FALSE);
476 :
477 32 : req->vary_star = TRUE;
478 32 : OPT_SERV_X_SINGLE_UINT(tmp);
479 32 : *matches = tmp == tm->tm_wday;
480 : }
481 34284 : else if (OPT_SERV_SYM_EQ("content-lang-eq") ||
482 : OPT_SERV_SYM_EQ("content-language-eq") ||
483 : OPT_SERV_SYM_EQ("content-lang==") ||
484 : OPT_SERV_SYM_EQ("content-language=="))
485 : {
486 32 : req->vary_al = TRUE;
487 32 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
488 32 : if (!req->content_language_vs1)
489 32 : *matches = conf_token_cmp_val_eq(conf, token, conf->tmp, 1, 0);
490 : else
491 0 : *matches = conf_token_cmp_val_eq(conf, token,
492 : HTTP__XTRA_HDR_PARAMS(req,
493 : content_language));
494 : }
495 34252 : else if (OPT_SERV_SYM_EQ("content-lang-ext-eq") ||
496 : OPT_SERV_SYM_EQ("content-language-extension-eq") ||
497 : OPT_SERV_SYM_EQ("content-lang-ext==") ||
498 : OPT_SERV_SYM_EQ("content-language-extension=="))
499 : {
500 32 : req->vary_al = TRUE;
501 32 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
502 32 : if (!req->ext_vary_al_vs1)
503 32 : *matches = conf_token_cmp_val_eq(conf, token, conf->tmp, 1, 0);
504 : else
505 0 : *matches = conf_token_cmp_val_eq(conf, token,
506 : HTTP__XTRA_HDR_PARAMS(req, ext_vary_al));
507 : }
508 34220 : else if (OPT_SERV_SYM_EQ("content-type-eq") ||
509 : OPT_SERV_SYM_EQ("content-type=="))
510 : {
511 32 : req->vary_a = TRUE;
512 32 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
513 32 : if (!req->content_type_vs1)
514 32 : *matches = conf_token_cmp_val_eq(conf, token, conf->tmp, 1, 0);
515 : else
516 0 : *matches = conf_token_cmp_val_eq(conf, token,
517 : HTTP__XTRA_HDR_PARAMS(req,
518 : content_type));
519 : }
520 34188 : else if (OPT_SERV_SYM_EQ("content-type-ext-eq") ||
521 : OPT_SERV_SYM_EQ("content-type-extension-eq") ||
522 : OPT_SERV_SYM_EQ("content-type-ext==") ||
523 : OPT_SERV_SYM_EQ("content-type-extension=="))
524 : {
525 32 : req->vary_a = TRUE;
526 32 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
527 32 : if (!req->ext_vary_a_vs1)
528 32 : *matches = conf_token_cmp_val_eq(conf, token, conf->tmp, 1, 0);
529 : else
530 0 : *matches = conf_token_cmp_val_eq(conf, token,
531 : HTTP__XTRA_HDR_PARAMS(req, ext_vary_a));
532 : }
533 : else
534 : { /* spend time doing path/name/extn/bnwe */
535 34140 : Vstr_ref *ref = NULL;
536 34140 : unsigned int type = 0;
537 34140 : unsigned int lim = 0;
538 34140 : size_t pos = 1;
539 34140 : size_t len = req->fname->len;
540 :
541 : if (0) { }
542 34140 : else if (OPT_SERV_SYM_EQ("path-beg"))
543 44 : type = HTTPD_POLICY_REQ_PATH_BEG;
544 34096 : else if (OPT_SERV_SYM_EQ("path-end"))
545 1720 : type = HTTPD_POLICY_REQ_PATH_END;
546 32492 : else if (OPT_SERV_SYM_EQ("path-eq") || OPT_SERV_SYM_EQ("path=="))
547 116 : type = HTTPD_POLICY_REQ_PATH_EQ;
548 32260 : else if (OPT_SERV_SYM_EQ("basename-beg"))
549 4 : type = HTTPD_POLICY_REQ_NAME_BEG;
550 32256 : else if (OPT_SERV_SYM_EQ("basename-end"))
551 4 : type = HTTPD_POLICY_REQ_NAME_END;
552 32256 : else if (OPT_SERV_SYM_EQ("basename-eq") || OPT_SERV_SYM_EQ("basename=="))
553 4 : type = HTTPD_POLICY_REQ_NAME_EQ;
554 32248 : else if (OPT_SERV_SYM_EQ("extension-beg"))
555 4 : type = HTTPD_POLICY_REQ_EXTN_BEG;
556 32244 : else if (OPT_SERV_SYM_EQ("extension-end"))
557 4 : type = HTTPD_POLICY_REQ_EXTN_END;
558 32244 : else if (OPT_SERV_SYM_EQ("extension-eq") || OPT_SERV_SYM_EQ("extension=="))
559 4 : type = HTTPD_POLICY_REQ_EXTN_EQ;
560 32236 : else if (OPT_SERV_SYM_EQ("extensions-beg"))
561 4 : type = HTTPD_POLICY_REQ_EXTS_BEG;
562 32232 : else if (OPT_SERV_SYM_EQ("extensions-end"))
563 4 : type = HTTPD_POLICY_REQ_EXTS_END;
564 32232 : else if (OPT_SERV_SYM_EQ("extensions-eq") ||
565 : OPT_SERV_SYM_EQ("extensions=="))
566 4 : type = HTTPD_POLICY_REQ_EXTS_EQ;
567 32224 : else if (OPT_SERV_SYM_EQ("basename-without-extension-beg"))
568 4 : type = HTTPD_POLICY_REQ_BWEN_BEG;
569 32220 : else if (OPT_SERV_SYM_EQ("basename-without-extension-end"))
570 4 : type = HTTPD_POLICY_REQ_BWEN_END;
571 32220 : else if (OPT_SERV_SYM_EQ("basename-without-extension-eq") ||
572 : OPT_SERV_SYM_EQ("basename-without-extension=="))
573 4 : type = HTTPD_POLICY_REQ_BWEN_EQ;
574 32212 : else if (OPT_SERV_SYM_EQ("basename-without-extensions-beg"))
575 4 : type = HTTPD_POLICY_REQ_BWES_BEG;
576 32208 : else if (OPT_SERV_SYM_EQ("basename-without-extensions-end"))
577 4 : type = HTTPD_POLICY_REQ_BWES_END;
578 32208 : else if (OPT_SERV_SYM_EQ("basename-without-extensions-eq") ||
579 : OPT_SERV_SYM_EQ("basename-without-extensions=="))
580 4 : type = HTTPD_POLICY_REQ_BWES_EQ;
581 : else
582 32200 : return (opt_serv_sc_tst(conf, token, matches, prev_match,
583 : tst_func, data));
584 :
585 970 : ASSERT(type);
586 :
587 1940 : if (!httpd_policy_path_make(con, req, conf, token, type, &ref))
588 : {
589 0 : vstr_ref_del(ref);
590 0 : return (FALSE);
591 : }
592 :
593 1940 : lim = httpd_policy_path_req2lim(type);
594 1940 : *matches = httpd_policy_path_lim_eq(req->fname, &pos, &len, lim,
595 : req->vhost_prefix_len, ref);
596 : }
597 :
598 501788 : return (TRUE);
599 : }
600 :
601 : int httpd__policy_request_d1(struct Con *con, Httpd_req_data *req,
602 : Conf_parse *conf, Conf_token *token,
603 : int *stop)
604 14688 : {
605 14688 : int clist = FALSE;
606 :
607 14688 : CONF_SC_TOGGLE_CLIST_VAR(clist);
608 :
609 14688 : if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
610 : {
611 2780 : unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
612 2780 : unsigned int nxt = 0;
613 2780 : Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
614 :
615 2780 : switch (type)
616 : {
617 : case HTTPD_POLICY_CON_POLICY:
618 592 : httpd_policy_change_con(con, ref->ptr);
619 592 : break;
620 :
621 : case HTTPD_POLICY_REQ_POLICY:
622 2188 : httpd_policy_change_req(con, req, ref->ptr);
623 2188 : break;
624 :
625 : default:
626 0 : vstr_ref_del(ref);
627 0 : return (FALSE);
628 : }
629 :
630 2780 : vstr_ref_del(ref);
631 2780 : if (nxt)
632 2780 : return (conf_parse_num_token(conf, token, nxt));
633 : }
634 :
635 11908 : else if (OPT_SERV_SYM_EQ("<close>"))
636 : {
637 32 : evnt_close(con->evnt);
638 32 : return (TRUE);
639 : }
640 11876 : else if (OPT_SERV_SYM_EQ("<stop>"))
641 : {
642 64 : *stop = TRUE;
643 64 : return (TRUE);
644 : }
645 11812 : else if (OPT_SERV_SYM_EQ("connection-policy"))
646 : {
647 48 : const Httpd_policy_opts *policy = NULL;
648 :
649 48 : if (!(policy = httpd__policy_build(con, conf, token,
650 : HTTPD_POLICY_CON_POLICY)))
651 32 : return (FALSE);
652 16 : httpd_policy_change_con(con, policy);
653 : }
654 11764 : else if (OPT_SERV_SYM_EQ("policy"))
655 : {
656 52 : const Httpd_policy_opts *policy = NULL;
657 :
658 52 : if (!(policy = httpd__policy_build(con, conf, token,
659 : HTTPD_POLICY_REQ_POLICY)))
660 32 : return (FALSE);
661 20 : httpd_policy_change_req(con, req, policy);
662 : }
663 11712 : else if (OPT_SERV_SYM_EQ("connection-tag"))
664 64 : OPT_SERV_X_VSTR(req->policy->s->beg, con->tag);
665 11648 : else if (OPT_SERV_SYM_EQ("tag"))
666 3392 : OPT_SERV_X_VSTR(req->policy->s->beg, req->tag);
667 8256 : else if (OPT_SERV_SYM_EQ("org.and.httpd-conf-req-1.0") ||
668 : OPT_SERV_SYM_EQ("org.and.jhttpd-conf-req-1.0"))
669 : {
670 8256 : Httpd_opts *opts = (Httpd_opts *)con->policy->s->beg;
671 8256 : return (httpd_conf_req_d0(con, req, /* server beg time is "close enough" */
672 : opts->beg_time, conf, token));
673 : }
674 : else
675 0 : return (FALSE);
676 :
677 3492 : return (TRUE);
678 : }
679 :
680 : static int httpd__policy_request_d0(struct Con *con, struct Httpd_req_data *req,
681 : Conf_parse *conf, Conf_token *token,
682 : int *stop)
683 537968 : {
684 : static int prev_match = TRUE;
685 537968 : unsigned int depth = token->depth_num;
686 537968 : int matches = TRUE;
687 :
688 537968 : if (token->type != CONF_TOKEN_TYPE_SLIST)
689 0 : return (FALSE);
690 :
691 842248 : while (conf_token_list_num(token, depth))
692 : {
693 563216 : CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
694 :
695 563216 : if (!httpd_match_request_sc_tst_d1(con, req, conf, token,
696 : &matches, prev_match))
697 0 : return (FALSE);
698 :
699 563216 : if (!matches)
700 : {
701 527920 : prev_match = FALSE;
702 527920 : return (TRUE);
703 : }
704 : }
705 10048 : --depth;
706 :
707 10048 : prev_match = TRUE;
708 :
709 30720 : while (conf_token_list_num(token, depth))
710 : {
711 14016 : CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
712 :
713 14016 : if (!httpd__policy_request_d1(con, req, conf, token, stop))
714 3296 : return (FALSE);
715 10720 : if (*stop || con->evnt->flag_q_closed) /* don't do anything else */
716 96 : return (TRUE);
717 : }
718 :
719 6656 : return (TRUE);
720 : }
721 :
722 : int httpd_policy_request(struct Con *con, struct Httpd_req_data *req,
723 : Conf_parse *conf, const Conf_token *beg_token)
724 31841 : {
725 : Conf_token token[1];
726 31841 : Vstr_ref *ref = NULL;
727 31841 : unsigned int num = 0;
728 :
729 31841 : if (!beg_token->num) /* not been parsed */
730 13561 : return (TRUE);
731 :
732 18280 : *token = *beg_token;
733 18280 : if (!httpd__match_iter_beg(conf, token, &ref, &num))
734 0 : return (TRUE);
735 :
736 : do
737 : {
738 537968 : int stop = FALSE;
739 :
740 537968 : conf_parse_num_token(conf, token, token->num);
741 268984 : assert(token->type == (CONF_TOKEN_TYPE_USER_BEG+HTTPD_CONF_MAIN_MATCH_REQ));
742 :
743 1704736 : while (token->type != CONF_TOKEN_TYPE_SLIST)
744 897784 : conf_parse_token(conf, token);
745 :
746 537968 : if (!httpd__policy_request_d0(con, req, conf, token, &stop))
747 3296 : goto conf_fail;
748 534672 : if (stop || con->evnt->flag_q_closed) /* don't do anything else */
749 : break;
750 534576 : } while (httpd__match_iter_nxt(conf, token, &ref, &num));
751 :
752 14984 : vstr_ref_del(ref);
753 14984 : vstr_del(conf->tmp, 1, conf->tmp->len);
754 14984 : return (TRUE);
755 :
756 3296 : conf_fail:
757 3296 : vstr_ref_del(ref);
758 3296 : vstr_del(conf->tmp, 1, conf->tmp->len);
759 3296 : if (!req->user_return_error_code)
760 : {
761 64 : conf_parse_backtrace(conf->tmp, "<policy-request>", conf, token);
762 64 : HTTPD_ERR(req, 503);
763 : }
764 3296 : return (FALSE);
765 : }
766 :
|