1 : #ifndef HTTPD_POLICY_H
2 : #define HTTPD_POLICY_H
3 :
4 : #include "opt_policy.h"
5 :
6 : #define HTTPD_POLICY__PATH_LIM_FULL 0
7 : #define HTTPD_POLICY__PATH_LIM_BEG 1
8 : #define HTTPD_POLICY__PATH_LIM_END 2
9 : #define HTTPD_POLICY__PATH_LIM_EQ 3
10 : #define HTTPD_POLICY__PATH_LIM_MASK 3
11 : #define HTTPD_POLICY_PATH_LIM_NONE 0
12 : #define HTTPD_POLICY_PATH_LIM_PATH_FULL (0x4 | HTTPD_POLICY__PATH_LIM_FULL)
13 : #define HTTPD_POLICY_PATH_LIM_PATH_BEG (0x4 | HTTPD_POLICY__PATH_LIM_BEG)
14 : #define HTTPD_POLICY_PATH_LIM_PATH_END (0x4 | HTTPD_POLICY__PATH_LIM_END)
15 : #define HTTPD_POLICY_PATH_LIM_PATH_EQ (0x4 | HTTPD_POLICY__PATH_LIM_EQ)
16 : #define HTTPD_POLICY_PATH_LIM_NAME_FULL (0x8 | HTTPD_POLICY__PATH_LIM_FULL)
17 : #define HTTPD_POLICY_PATH_LIM_NAME_BEG (0x8 | HTTPD_POLICY__PATH_LIM_BEG)
18 : #define HTTPD_POLICY_PATH_LIM_NAME_END (0x8 | HTTPD_POLICY__PATH_LIM_END)
19 : #define HTTPD_POLICY_PATH_LIM_NAME_EQ (0x8 | HTTPD_POLICY__PATH_LIM_EQ)
20 : #define HTTPD_POLICY_PATH_LIM_EXTN_FULL (0xc | HTTPD_POLICY__PATH_LIM_FULL)
21 : #define HTTPD_POLICY_PATH_LIM_EXTN_BEG (0xc | HTTPD_POLICY__PATH_LIM_BEG)
22 : #define HTTPD_POLICY_PATH_LIM_EXTN_END (0xc | HTTPD_POLICY__PATH_LIM_END)
23 : #define HTTPD_POLICY_PATH_LIM_EXTN_EQ (0xc | HTTPD_POLICY__PATH_LIM_EQ)
24 : #define HTTPD_POLICY_PATH_LIM_EXTS_FULL (0x14 | HTTPD_POLICY__PATH_LIM_FULL)
25 : #define HTTPD_POLICY_PATH_LIM_EXTS_BEG (0x14 | HTTPD_POLICY__PATH_LIM_BEG)
26 : #define HTTPD_POLICY_PATH_LIM_EXTS_END (0x14 | HTTPD_POLICY__PATH_LIM_END)
27 : #define HTTPD_POLICY_PATH_LIM_EXTS_EQ (0x14 | HTTPD_POLICY__PATH_LIM_EQ)
28 : #define HTTPD_POLICY_PATH_LIM_BWEN_FULL (0x18 | HTTPD_POLICY__PATH_LIM_FULL)
29 : #define HTTPD_POLICY_PATH_LIM_BWEN_BEG (0x18 | HTTPD_POLICY__PATH_LIM_BEG)
30 : #define HTTPD_POLICY_PATH_LIM_BWEN_END (0x18 | HTTPD_POLICY__PATH_LIM_END)
31 : #define HTTPD_POLICY_PATH_LIM_BWEN_EQ (0x18 | HTTPD_POLICY__PATH_LIM_EQ)
32 : #define HTTPD_POLICY_PATH_LIM_BWES_FULL (0x1c | HTTPD_POLICY__PATH_LIM_FULL)
33 : #define HTTPD_POLICY_PATH_LIM_BWES_BEG (0x1c | HTTPD_POLICY__PATH_LIM_BEG)
34 : #define HTTPD_POLICY_PATH_LIM_BWES_END (0x1c | HTTPD_POLICY__PATH_LIM_END)
35 : #define HTTPD_POLICY_PATH_LIM_BWES_EQ (0x1c | HTTPD_POLICY__PATH_LIM_EQ)
36 :
37 : /* choosing (1024) as a offset ... kinda hackyish */
38 : #define HTTPD_POLICY_REQ_PATH_BEG (1024 + 0)
39 : #define HTTPD_POLICY_REQ_PATH_END (1024 + 1)
40 : #define HTTPD_POLICY_REQ_PATH_EQ (1024 + 2)
41 : #define HTTPD_POLICY_REQ_NAME_BEG (1024 + 3)
42 : #define HTTPD_POLICY_REQ_NAME_END (1024 + 4)
43 : #define HTTPD_POLICY_REQ_NAME_EQ (1024 + 5)
44 : #define HTTPD_POLICY_REQ_BWEN_BEG (1024 + 6)
45 : #define HTTPD_POLICY_REQ_BWEN_END (1024 + 7)
46 : #define HTTPD_POLICY_REQ_BWEN_EQ (1024 + 8)
47 : #define HTTPD_POLICY_REQ_BWES_BEG (1024 + 9)
48 : #define HTTPD_POLICY_REQ_BWES_END (1024 + 10)
49 : #define HTTPD_POLICY_REQ_BWES_EQ (1024 + 11)
50 : #define HTTPD_POLICY_REQ_EXTN_BEG (1024 + 12)
51 : #define HTTPD_POLICY_REQ_EXTN_END (1024 + 13)
52 : #define HTTPD_POLICY_REQ_EXTN_EQ (1024 + 14)
53 : #define HTTPD_POLICY_REQ_EXTS_BEG (1024 + 15)
54 : #define HTTPD_POLICY_REQ_EXTS_END (1024 + 16)
55 : #define HTTPD_POLICY_REQ_EXTS_EQ (1024 + 17)
56 :
57 : typedef struct Httpd_policy_path
58 : {
59 : Vstr_base *s1;
60 : void (*ref_func)(Vstr_ref *);
61 : } Httpd_policy_path;
62 :
63 : extern void httpd_policy_change_con(struct Con *, const Httpd_policy_opts *);
64 : extern void httpd_policy_change_req(struct Con *, Httpd_req_data *,
65 : const Httpd_policy_opts *);
66 :
67 : extern int httpd_policy_build_path(struct Con *, Httpd_req_data *,
68 : const Conf_parse *, Conf_token *,
69 : int *, int *);
70 : extern int httpd_policy_path_make(struct Con *con, Httpd_req_data *req,
71 : Conf_parse *, Conf_token *, unsigned int,
72 : Vstr_ref **);
73 :
74 : extern int httpd_policy_path_eq(const Vstr_base *,
75 : const Vstr_base *, size_t *, size_t *);
76 : extern int httpd_policy_path_beg_eq(const Vstr_base *,
77 : const Vstr_base *, size_t *, size_t *);
78 : extern int httpd_policy_path_end_eq(const Vstr_base *,
79 : const Vstr_base *, size_t *, size_t *);
80 :
81 : extern void httpd_policy_path_mod_name(const Vstr_base *, size_t *, size_t *);
82 : extern void httpd_policy_path_mod_dirn(const Vstr_base *, size_t *, size_t *);
83 : extern void httpd_policy_path_mod_extn(const Vstr_base *, size_t *, size_t *);
84 : extern void httpd_policy_path_mod_exts(const Vstr_base *, size_t *, size_t *);
85 : extern void httpd_policy_path_mod_bwen(const Vstr_base *, size_t *, size_t *);
86 : extern void httpd_policy_path_mod_bwes(const Vstr_base *, size_t *, size_t *);
87 :
88 : extern int httpd_policy_path_lim_eq(const Vstr_base *, size_t *, size_t *,
89 : unsigned int, size_t, Vstr_ref *);
90 :
91 : extern int httpd_policy_uri_eq(const Vstr_base *,
92 : const Vstr_base *, size_t *, size_t *);
93 : extern int httpd_policy_uri_beg_eq(const Vstr_base *,
94 : const Vstr_base *, size_t *, size_t *);
95 : extern int httpd_policy_uri_end_eq(const Vstr_base *,
96 : const Vstr_base *, size_t *, size_t *);
97 :
98 : extern void httpd_policy_uri_mod_name(const Vstr_base *, size_t *, size_t *);
99 : extern void httpd_policy_uri_mod_dirn(const Vstr_base *, size_t *, size_t *);
100 : extern void httpd_policy_uri_mod_extn(const Vstr_base *, size_t *, size_t *);
101 : extern void httpd_policy_uri_mod_exts(const Vstr_base *, size_t *, size_t *);
102 : extern void httpd_policy_uri_mod_bwen(const Vstr_base *, size_t *, size_t *);
103 : extern void httpd_policy_uri_mod_bwes(const Vstr_base *, size_t *, size_t *);
104 :
105 : extern int httpd_policy_uri_lim_eq(const Vstr_base *, size_t *, size_t *,
106 : unsigned int, int, Vstr_ref *);
107 :
108 : extern int httpd_policy_path_req2lim(unsigned int);
109 :
110 : extern int httpd_policy_ipv4_make(struct Con *, Httpd_req_data *,
111 : Conf_parse *, Conf_token *,
112 : unsigned int, struct sockaddr *, int *);
113 : extern int httpd_policy_ipv4_cidr_eq(struct Con *, Httpd_req_data *,
114 : Opt_policy_ipv4 *, struct sockaddr *);
115 :
116 : extern void httpd_policy_exit(Httpd_policy_opts *);
117 : extern int httpd_policy_init(Httpd_opts *, Httpd_policy_opts *);
118 : extern Opt_serv_policy_opts *httpd_policy_make(Opt_serv_opts *);
119 : extern int httpd_policy_copy(Opt_serv_policy_opts *,
120 : const Opt_serv_policy_opts *);
121 :
122 : #if !defined(HTTPD_POLICY_COMPILE_INLINE)
123 : # if ! COMPILE_DEBUG
124 : # define HTTPD_POLICY_COMPILE_INLINE 1
125 : # else
126 : # define HTTPD_POLICY_COMPILE_INLINE 0
127 : # endif
128 : #endif
129 :
130 : #if defined(VSTR_AUTOCONF_HAVE_INLINE) && HTTPD_POLICY_COMPILE_INLINE
131 :
132 : #if COMPILE_DEBUG
133 : # define HTTPD_POLICY__ASSERT ASSERT
134 : #else
135 : # define HTTPD_POLICY__ASSERT(x)
136 : #endif
137 :
138 : #ifndef HTTPD_POLICY__EI
139 : # define HTTPD_POLICY__EI extern inline
140 : #endif
141 :
142 : #define HTTPD_POLICY__TRUE 1
143 : #define HTTPD_POLICY__FALSE 0
144 :
145 : HTTPD_POLICY__EI void httpd_policy_change_con(struct Con *con,
146 : const Httpd_policy_opts *policy)
147 45862 : { /* BEG: should be in opt_policy_change_con() */
148 45862 : con->evnt->flag_insta_close = policy->s->use_insta_close;
149 :
150 45862 : evnt_limit_alt(con->evnt, 0, &policy->s->io_nslimit);
151 45862 : evnt_limit_chg(con->evnt, 1, policy->s->ref_io_limit);
152 : /* END: should be in opt_policy_change_con() */
153 :
154 45862 : con->use_sendfile = policy->use_sendfile;
155 45862 : con->use_posix_fadvise = policy->use_posix_fadvise;
156 45862 : con->policy = policy;
157 45862 : }
158 :
159 : HTTPD_POLICY__EI void httpd_policy_change_req(struct Con *con,
160 : Httpd_req_data *req,
161 : const Httpd_policy_opts *policy)
162 61562 : {
163 61562 : con->evnt->flag_insta_close = policy->s->use_insta_close;
164 :
165 61562 : req->parse_accept = policy->use_err_406;
166 61562 : req->parse_accept_language = policy->use_err_406;
167 61562 : req->allow_accept_encoding = policy->use_enc_content_replacement;
168 61562 : if (req->vhost_prefix_len && !policy->use_vhosts_name)
169 : { /* NOTE: doesn't do chk_host properly */
170 0 : vstr_del(req->fname, 1, req->vhost_prefix_len);
171 0 : req->vhost_prefix_len = 0;
172 : }
173 61562 : if (!req->chked_encoded_path)
174 : {
175 59354 : req->chk_encoded_slash = policy->chk_encoded_slash;
176 59354 : req->chk_encoded_dot = policy->chk_encoded_dot;
177 : }
178 61562 : req->policy = policy;
179 61562 : }
180 :
181 : HTTPD_POLICY__EI int httpd_policy_path_eq(const Vstr_base *s1,
182 : const Vstr_base *s2,
183 : size_t *p2, size_t *l2)
184 42312 : {
185 42312 : return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
186 : }
187 :
188 : /* if the s1 is equal to the begining of s2 */
189 : HTTPD_POLICY__EI int httpd_policy_path_beg_eq(const Vstr_base *s1,
190 : const Vstr_base *s2,
191 : size_t *p2, size_t *l2)
192 95272 : {
193 95272 : if (*l2 > s1->len)
194 13216 : *l2 = s1->len;
195 95272 : return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
196 : }
197 :
198 : /* if the s1 is equal to the end of s2 */
199 : HTTPD_POLICY__EI int httpd_policy_path_end_eq(const Vstr_base *s1,
200 : const Vstr_base *s2,
201 : size_t *p2, size_t *l2)
202 37176 : {
203 37176 : if (*l2 > s1->len)
204 : {
205 33944 : *p2 += (*l2 - s1->len);
206 33944 : *l2 = s1->len;
207 : }
208 37176 : return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
209 : }
210 :
211 : HTTPD_POLICY__EI void httpd_policy_path_mod_name(const Vstr_base *s1,
212 : size_t *pos, size_t *len)
213 3360 : {
214 3360 : size_t srch = vstr_srch_chr_rev(s1, *pos, *len, '/');
215 :
216 3360 : if (!srch)
217 992 : return;
218 :
219 2368 : *len -= vstr_sc_posdiff(*pos, srch);
220 2368 : *pos += vstr_sc_posdiff(*pos, srch);
221 : }
222 :
223 : HTTPD_POLICY__EI void httpd_policy_path_mod_dirn(const Vstr_base *s1,
224 : size_t *pos, size_t *len)
225 160 : {
226 160 : size_t srch = vstr_srch_chr_rev(s1, *pos, *len, '/');
227 :
228 160 : if (srch)
229 160 : *len = vstr_sc_posdiff(*pos, srch);
230 : else
231 0 : *len = 0;
232 160 : }
233 :
234 : HTTPD_POLICY__EI void httpd_policy_path_mod_extn(const Vstr_base *s1,
235 : size_t *pos, size_t *len)
236 768 : {
237 768 : size_t srch = 0;
238 :
239 768 : httpd_policy_path_mod_name(s1, pos, len);
240 :
241 768 : if ((srch = vstr_srch_chr_rev(s1, *pos, *len, '.')))
242 : { /* include '.' */
243 672 : *len -= srch - *pos;
244 672 : *pos = srch;
245 : }
246 : else
247 : { /* at point just after basename */
248 96 : *pos = vstr_sc_poslast(*pos, *len);
249 96 : *len = 0;
250 : }
251 768 : }
252 :
253 : HTTPD_POLICY__EI void httpd_policy_path_mod_exts(const Vstr_base *s1,
254 : size_t *pos, size_t *len)
255 768 : {
256 768 : size_t srch = 0;
257 :
258 768 : httpd_policy_path_mod_name(s1, pos, len);
259 :
260 768 : if ((srch = vstr_srch_chr_fwd(s1, *pos, *len, '.')))
261 : { /* include '.' */
262 672 : *len -= srch - *pos;
263 672 : *pos = srch;
264 : }
265 : else
266 : { /* at point just after basename */
267 96 : *pos = vstr_sc_poslast(*pos, *len);
268 96 : *len = 0;
269 : }
270 768 : }
271 :
272 : HTTPD_POLICY__EI void httpd_policy_path_mod_bwen(const Vstr_base *s1,
273 : size_t *pos, size_t *len)
274 256 : {
275 256 : size_t srch = 0;
276 :
277 256 : httpd_policy_path_mod_name(s1, pos, len);
278 :
279 256 : if ((srch = vstr_srch_chr_rev(s1, *pos, *len, '.')))
280 160 : *len = vstr_sc_posdiff(*pos, srch) - 1; /* don't include '.' */
281 256 : }
282 :
283 : HTTPD_POLICY__EI void httpd_policy_path_mod_bwes(const Vstr_base *s1,
284 : size_t *pos, size_t *len)
285 256 : {
286 256 : size_t srch = 0;
287 :
288 256 : httpd_policy_path_mod_name(s1, pos, len);
289 :
290 256 : if ((srch = vstr_srch_chr_fwd(s1, *pos, *len, '.')))
291 160 : *len = vstr_sc_posdiff(*pos, srch) - 1; /* don't include '.' */
292 256 : }
293 :
294 : HTTPD_POLICY__EI int httpd_policy_path_lim_eq(const Vstr_base *s1,
295 : size_t *pos, size_t *len,
296 : unsigned int lim,
297 : size_t vhost_prefix_len,
298 : Vstr_ref *ref)
299 176872 : {
300 176872 : const Httpd_policy_path *srch = NULL;
301 :
302 176872 : if (lim == HTTPD_POLICY_PATH_LIM_NONE)
303 96 : return (HTTPD_POLICY__TRUE);
304 :
305 176776 : *len -= vhost_prefix_len;
306 176776 : *pos += vhost_prefix_len;
307 :
308 176776 : switch (lim)
309 : {
310 0 : default: HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
311 :
312 : case HTTPD_POLICY_PATH_LIM_PATH_FULL:
313 : case HTTPD_POLICY_PATH_LIM_PATH_BEG:
314 : case HTTPD_POLICY_PATH_LIM_PATH_END:
315 : case HTTPD_POLICY_PATH_LIM_PATH_EQ:
316 87620 : break;
317 :
318 : case HTTPD_POLICY_PATH_LIM_NAME_FULL:
319 : case HTTPD_POLICY_PATH_LIM_NAME_BEG:
320 : case HTTPD_POLICY_PATH_LIM_NAME_END:
321 : case HTTPD_POLICY_PATH_LIM_NAME_EQ:
322 1152 : httpd_policy_path_mod_name(s1, pos, len);
323 1152 : break;
324 :
325 : case HTTPD_POLICY_PATH_LIM_EXTN_FULL:
326 : case HTTPD_POLICY_PATH_LIM_EXTN_BEG:
327 : case HTTPD_POLICY_PATH_LIM_EXTN_END:
328 : case HTTPD_POLICY_PATH_LIM_EXTN_EQ:
329 96 : httpd_policy_path_mod_extn(s1, pos, len);
330 96 : break;
331 :
332 : case HTTPD_POLICY_PATH_LIM_EXTS_FULL:
333 : case HTTPD_POLICY_PATH_LIM_EXTS_BEG:
334 : case HTTPD_POLICY_PATH_LIM_EXTS_END:
335 : case HTTPD_POLICY_PATH_LIM_EXTS_EQ:
336 96 : httpd_policy_path_mod_exts(s1, pos, len);
337 96 : break;
338 :
339 : case HTTPD_POLICY_PATH_LIM_BWEN_FULL:
340 : case HTTPD_POLICY_PATH_LIM_BWEN_BEG:
341 : case HTTPD_POLICY_PATH_LIM_BWEN_END:
342 : case HTTPD_POLICY_PATH_LIM_BWEN_EQ:
343 96 : httpd_policy_path_mod_bwen(s1, pos, len);
344 96 : break;
345 :
346 : case HTTPD_POLICY_PATH_LIM_BWES_FULL:
347 : case HTTPD_POLICY_PATH_LIM_BWES_BEG:
348 : case HTTPD_POLICY_PATH_LIM_BWES_END:
349 : case HTTPD_POLICY_PATH_LIM_BWES_EQ:
350 96 : httpd_policy_path_mod_bwes(s1, pos, len);
351 : break;
352 : }
353 :
354 176776 : if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_FULL)
355 2016 : return (HTTPD_POLICY__TRUE);
356 :
357 87380 : HTTPD_POLICY__ASSERT(ref);
358 174760 : srch = ref->ptr;
359 :
360 : if (0) { }
361 174760 : else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_BEG)
362 : {
363 95272 : if (!httpd_policy_path_beg_eq(srch->s1, s1, pos, len))
364 89896 : goto path_no_match;
365 : }
366 79488 : else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_END)
367 : {
368 37176 : if (!httpd_policy_path_end_eq(srch->s1, s1, pos, len))
369 32216 : goto path_no_match;
370 : }
371 42312 : else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_EQ)
372 : {
373 42312 : if (!httpd_policy_path_eq(srch->s1, s1, pos, len))
374 39336 : goto path_no_match;
375 : }
376 : else
377 0 : HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
378 :
379 13312 : vstr_ref_del(ref); ref = NULL;
380 13312 : return (HTTPD_POLICY__TRUE);
381 161448 : path_no_match:
382 161448 : vstr_ref_del(ref); ref = NULL;
383 161448 : return (HTTPD_POLICY__FALSE);
384 : }
385 :
386 : static inline int httpd_policy__uri_eq(const Vstr_base *s1,
387 : const Vstr_base *s2,
388 : size_t p2, size_t l2, size_t *ret_len)
389 5184 : {
390 5184 : size_t p1 = 1;
391 5184 : size_t l1 = s1->len;
392 :
393 11584 : while (l1 && (l2 >= l1))
394 : {
395 5184 : size_t tmp = vstr_cspn_cstr_chrs_fwd(s2, p2, l1, "%");
396 5184 : unsigned int val1 = 0;
397 5184 : unsigned int val2 = 0;
398 5184 : unsigned int num_flags = VSTR_FLAG02(PARSE_NUM_NO, BEG_ZERO, BEG_PM);
399 :
400 5184 : if (tmp)
401 : {
402 4064 : if (!vstr_cmp_eq(s1, p1, tmp, s2, p2, tmp))
403 2944 : return (HTTPD_POLICY__FALSE);
404 1120 : l1 -= tmp; p1 += tmp;
405 1120 : l2 -= tmp; p2 += tmp;
406 1120 : continue;
407 : }
408 :
409 1120 : if (l2 < 3)
410 0 : return (HTTPD_POLICY__FALSE);
411 560 : HTTPD_POLICY__ASSERT(vstr_export_chr(s2, p2) == '%');
412 :
413 1120 : val1 = (unsigned char)vstr_export_chr(s1, p1);
414 1120 : val2 = vstr_parse_ushort(s2, p2 + 1, 2, 16 | num_flags, &tmp, NULL);
415 :
416 1120 : if ((tmp != 2) || (val1 != val2))
417 1024 : return (HTTPD_POLICY__FALSE);
418 :
419 96 : l1 -= 1; p1 += 1;
420 96 : l2 -= 3; p2 += 3;
421 : }
422 :
423 1216 : *ret_len = l2;
424 1216 : return (!l1);
425 : }
426 :
427 : HTTPD_POLICY__EI int httpd_policy_uri_eq(const Vstr_base *s1,
428 : const Vstr_base *s2,
429 : size_t *p2, size_t *l2)
430 0 : {
431 0 : size_t tmp = 0;
432 0 : return (httpd_policy__uri_eq(s1, s2, *p2, *l2, &tmp) && !tmp);
433 : }
434 :
435 : /* if the s1 is equal to the begining of s2 */
436 : HTTPD_POLICY__EI int httpd_policy_uri_beg_eq(const Vstr_base *s1,
437 : const Vstr_base *s2,
438 : size_t *p2, size_t *l2)
439 832 : {
440 832 : size_t tmp = 0;
441 :
442 832 : if (!httpd_policy__uri_eq(s1, s2, *p2, *l2, &tmp))
443 0 : return (HTTPD_POLICY__FALSE);
444 :
445 832 : if (tmp) *l2 -= tmp;
446 :
447 832 : return (HTTPD_POLICY__TRUE);
448 : }
449 :
450 : /* if the s1 is equal to the end of s2 */
451 : HTTPD_POLICY__EI int httpd_policy_uri_end_eq(const Vstr_base *s1,
452 : const Vstr_base *s2,
453 : size_t *p2, size_t *l2)
454 1792 : {
455 1792 : if (!vstr_srch_chr_fwd(s2, *p2, *l2, '%'))
456 : {
457 1408 : if (*l2 > s1->len)
458 : {
459 1408 : *p2 += (*l2 - s1->len);
460 1408 : *l2 = s1->len;
461 : }
462 1408 : return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
463 : }
464 :
465 384 : if (*l2 > (s1->len * 3))
466 : {
467 192 : *p2 += (*l2 - (s1->len * 3));
468 192 : *l2 = (s1->len * 3);
469 : }
470 :
471 4544 : while (*l2 >= s1->len)
472 : {
473 4352 : size_t tmp = 0;
474 4352 : if (httpd_policy__uri_eq(s1, s2, *p2, *l2, &tmp) && !tmp)
475 384 : return (HTTPD_POLICY__TRUE);
476 3968 : *l2 -= 1; *p2 += 1;
477 : }
478 :
479 0 : return (HTTPD_POLICY__FALSE);
480 : }
481 :
482 : HTTPD_POLICY__EI void httpd_policy_uri_mod_name(const Vstr_base *s1,
483 : size_t *pos, size_t *len)
484 800 : {
485 800 : size_t srch1 = vstr_srch_chr_rev(s1, *pos, *len, '/');
486 800 : size_t srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2f");
487 :
488 800 : if (!srch1 && !srch2)
489 0 : return;
490 :
491 800 : if (srch1 < srch2)
492 0 : srch1 = srch2 + 2;
493 :
494 800 : *len -= vstr_sc_posdiff(*pos, srch1);
495 800 : *pos += vstr_sc_posdiff(*pos, srch1);
496 : }
497 :
498 : HTTPD_POLICY__EI void httpd_policy_uri_mod_dirn(const Vstr_base *s1,
499 : size_t *pos, size_t *len)
500 160 : {
501 160 : size_t srch1 = vstr_srch_chr_rev(s1, *pos, *len, '/');
502 160 : size_t srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2f");
503 :
504 160 : if (!srch1 && !srch2)
505 : {
506 0 : *len = 0;
507 0 : return;
508 : }
509 :
510 160 : if (srch1 < srch2)
511 0 : srch1 = srch2 + 2;
512 :
513 160 : *len = vstr_sc_posdiff(*pos, srch1);
514 : }
515 :
516 : HTTPD_POLICY__EI void httpd_policy_uri_mod_extn(const Vstr_base *s1,
517 : size_t *pos, size_t *len)
518 160 : {
519 160 : size_t srch1 = 0;
520 160 : size_t srch2 = 0;
521 :
522 160 : httpd_policy_uri_mod_name(s1, pos, len);
523 :
524 160 : srch1 = vstr_srch_chr_rev(s1, *pos, *len, '.');
525 160 : srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2e");
526 :
527 160 : if (srch1 < srch2)
528 64 : srch1 = srch2;
529 :
530 160 : if (srch1)
531 : { /* include '.' or "%2e" */
532 160 : *len -= srch1 - *pos;
533 160 : *pos = srch1;
534 : }
535 : else
536 : { /* at point just after basename */
537 0 : *pos = vstr_sc_poslast(*pos, *len);
538 0 : *len = 0;
539 : }
540 160 : }
541 :
542 : HTTPD_POLICY__EI void httpd_policy_uri_mod_exts(const Vstr_base *s1,
543 : size_t *pos, size_t *len)
544 160 : {
545 160 : size_t srch1 = 0;
546 160 : size_t srch2 = 0;
547 :
548 160 : httpd_policy_uri_mod_name(s1, pos, len);
549 :
550 160 : srch1 = vstr_srch_chr_fwd(s1, *pos, *len, '.');
551 160 : srch2 = vstr_srch_case_cstr_buf_fwd(s1, *pos, *len, "%2e");
552 160 : if (!srch1) srch1 = srch2;
553 160 : if (!srch2) srch2 = srch1;
554 :
555 160 : if (srch1 > srch2) srch1 = srch2;
556 :
557 160 : if (srch1)
558 : { /* include '.' or "%2e" */
559 160 : *len -= srch1 - *pos;
560 160 : *pos = srch1;
561 : }
562 : else
563 : { /* at point just after basename */
564 0 : *pos = vstr_sc_poslast(*pos, *len);
565 0 : *len = 0;
566 : }
567 160 : }
568 :
569 : HTTPD_POLICY__EI void httpd_policy_uri_mod_bwen(const Vstr_base *s1,
570 : size_t *pos, size_t *len)
571 160 : {
572 160 : size_t srch1 = 0;
573 160 : size_t srch2 = 0;
574 :
575 160 : httpd_policy_uri_mod_name(s1, pos, len);
576 :
577 160 : srch1 = vstr_srch_chr_rev(s1, *pos, *len, '.');
578 160 : srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2e");
579 :
580 160 : if (srch1 < srch2) srch1 = srch2;
581 :
582 160 : if (srch1)
583 160 : *len = vstr_sc_posdiff(*pos, srch1) - 1; /* don't include '.' */
584 160 : }
585 :
586 : HTTPD_POLICY__EI void httpd_policy_uri_mod_bwes(const Vstr_base *s1,
587 : size_t *pos, size_t *len)
588 160 : {
589 160 : size_t srch1 = 0;
590 160 : size_t srch2 = 0;
591 :
592 160 : httpd_policy_uri_mod_name(s1, pos, len);
593 :
594 160 : srch1 = vstr_srch_chr_fwd(s1, *pos, *len, '.');
595 160 : srch2 = vstr_srch_case_cstr_buf_fwd(s1, *pos, *len, "%2e");
596 160 : if (!srch1) srch1 = srch2;
597 160 : if (!srch2) srch2 = srch1;
598 :
599 160 : if (srch1 > srch2) srch1 = srch2;
600 :
601 160 : if (srch1)
602 160 : *len = vstr_sc_posdiff(*pos, srch1) - 1; /* don't include '.' */
603 160 : }
604 :
605 : HTTPD_POLICY__EI int httpd_policy_uri_lim_eq(const Vstr_base *s1,
606 : size_t *pos, size_t *len,
607 : unsigned int lim,
608 : int slash_dot_safe, Vstr_ref *ref)
609 4864 : {
610 4864 : const Httpd_policy_path *srch = NULL;
611 :
612 4864 : switch (lim)
613 : {
614 0 : default: HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
615 : case HTTPD_POLICY_PATH_LIM_NONE:
616 864 : HTTPD_POLICY__ASSERT(!ref);
617 1728 : return (HTTPD_POLICY__TRUE);
618 :
619 : case HTTPD_POLICY_PATH_LIM_PATH_FULL:
620 : case HTTPD_POLICY_PATH_LIM_PATH_BEG:
621 : case HTTPD_POLICY_PATH_LIM_PATH_END:
622 : case HTTPD_POLICY_PATH_LIM_PATH_EQ:
623 1312 : break;
624 :
625 : case HTTPD_POLICY_PATH_LIM_NAME_FULL:
626 : case HTTPD_POLICY_PATH_LIM_NAME_BEG:
627 : case HTTPD_POLICY_PATH_LIM_NAME_END:
628 : case HTTPD_POLICY_PATH_LIM_NAME_EQ:
629 0 : if (slash_dot_safe)
630 0 : httpd_policy_path_mod_name(s1, pos, len);
631 : else
632 0 : httpd_policy_uri_mod_name(s1, pos, len);
633 0 : break;
634 :
635 : case HTTPD_POLICY_PATH_LIM_EXTN_FULL:
636 : case HTTPD_POLICY_PATH_LIM_EXTN_BEG:
637 : case HTTPD_POLICY_PATH_LIM_EXTN_END:
638 : case HTTPD_POLICY_PATH_LIM_EXTN_EQ:
639 256 : if (slash_dot_safe)
640 256 : httpd_policy_path_mod_extn(s1, pos, len);
641 : else
642 0 : httpd_policy_uri_mod_extn(s1, pos, len);
643 128 : break;
644 :
645 : case HTTPD_POLICY_PATH_LIM_EXTS_FULL:
646 : case HTTPD_POLICY_PATH_LIM_EXTS_BEG:
647 : case HTTPD_POLICY_PATH_LIM_EXTS_END:
648 : case HTTPD_POLICY_PATH_LIM_EXTS_EQ:
649 256 : if (slash_dot_safe)
650 256 : httpd_policy_path_mod_exts(s1, pos, len);
651 : else
652 0 : httpd_policy_uri_mod_exts(s1, pos, len);
653 128 : break;
654 :
655 : case HTTPD_POLICY_PATH_LIM_BWEN_FULL:
656 : case HTTPD_POLICY_PATH_LIM_BWEN_BEG:
657 : case HTTPD_POLICY_PATH_LIM_BWEN_END:
658 : case HTTPD_POLICY_PATH_LIM_BWEN_EQ:
659 0 : if (slash_dot_safe)
660 0 : httpd_policy_path_mod_bwen(s1, pos, len);
661 : else
662 0 : httpd_policy_uri_mod_bwen(s1, pos, len);
663 0 : break;
664 :
665 : case HTTPD_POLICY_PATH_LIM_BWES_FULL:
666 : case HTTPD_POLICY_PATH_LIM_BWES_BEG:
667 : case HTTPD_POLICY_PATH_LIM_BWES_END:
668 : case HTTPD_POLICY_PATH_LIM_BWES_EQ:
669 0 : if (slash_dot_safe)
670 0 : httpd_policy_path_mod_bwes(s1, pos, len);
671 : else
672 0 : httpd_policy_uri_mod_bwes(s1, pos, len);
673 : break;
674 : }
675 :
676 3136 : if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_FULL)
677 : {
678 256 : HTTPD_POLICY__ASSERT(!ref);
679 512 : return (HTTPD_POLICY__TRUE);
680 : }
681 :
682 1312 : HTTPD_POLICY__ASSERT(ref);
683 2624 : srch = ref->ptr;
684 :
685 : if (0) { }
686 2624 : else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_BEG)
687 : {
688 832 : if (!httpd_policy_uri_beg_eq(srch->s1, s1, pos, len))
689 0 : goto path_no_match;
690 : }
691 1792 : else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_END)
692 : {
693 1792 : if (!httpd_policy_uri_end_eq(srch->s1, s1, pos, len))
694 0 : goto path_no_match;
695 : }
696 0 : else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_EQ)
697 : {
698 0 : if (!httpd_policy_uri_eq(srch->s1, s1, pos, len))
699 0 : goto path_no_match;
700 : }
701 : else
702 0 : HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
703 :
704 2624 : vstr_ref_del(ref); ref = NULL;
705 2624 : return (HTTPD_POLICY__TRUE);
706 0 : path_no_match:
707 0 : vstr_ref_del(ref); ref = NULL;
708 0 : return (HTTPD_POLICY__FALSE);
709 : }
710 :
711 : HTTPD_POLICY__EI int httpd_policy_path_req2lim(unsigned int type)
712 177384 : {
713 177384 : unsigned int lim = HTTPD_POLICY_PATH_LIM_NONE;
714 :
715 177384 : switch (type)
716 : {
717 95944 : case HTTPD_POLICY_REQ_PATH_BEG: lim = HTTPD_POLICY_PATH_LIM_PATH_BEG; break;
718 38808 : case HTTPD_POLICY_REQ_PATH_END: lim = HTTPD_POLICY_PATH_LIM_PATH_END; break;
719 42152 : case HTTPD_POLICY_REQ_PATH_EQ: lim = HTTPD_POLICY_PATH_LIM_PATH_EQ; break;
720 :
721 32 : case HTTPD_POLICY_REQ_NAME_BEG: lim = HTTPD_POLICY_PATH_LIM_NAME_BEG; break;
722 32 : case HTTPD_POLICY_REQ_NAME_END: lim = HTTPD_POLICY_PATH_LIM_NAME_END; break;
723 32 : case HTTPD_POLICY_REQ_NAME_EQ: lim = HTTPD_POLICY_PATH_LIM_NAME_EQ; break;
724 :
725 32 : case HTTPD_POLICY_REQ_BWEN_BEG: lim = HTTPD_POLICY_PATH_LIM_BWEN_BEG; break;
726 32 : case HTTPD_POLICY_REQ_BWEN_END: lim = HTTPD_POLICY_PATH_LIM_BWEN_END; break;
727 32 : case HTTPD_POLICY_REQ_BWEN_EQ: lim = HTTPD_POLICY_PATH_LIM_BWEN_EQ; break;
728 :
729 32 : case HTTPD_POLICY_REQ_BWES_BEG: lim = HTTPD_POLICY_PATH_LIM_BWES_BEG; break;
730 32 : case HTTPD_POLICY_REQ_BWES_END: lim = HTTPD_POLICY_PATH_LIM_BWES_END; break;
731 32 : case HTTPD_POLICY_REQ_BWES_EQ: lim = HTTPD_POLICY_PATH_LIM_BWES_EQ; break;
732 :
733 32 : case HTTPD_POLICY_REQ_EXTN_BEG: lim = HTTPD_POLICY_PATH_LIM_EXTN_BEG; break;
734 32 : case HTTPD_POLICY_REQ_EXTN_END: lim = HTTPD_POLICY_PATH_LIM_EXTN_END; break;
735 32 : case HTTPD_POLICY_REQ_EXTN_EQ: lim = HTTPD_POLICY_PATH_LIM_EXTN_EQ; break;
736 :
737 32 : case HTTPD_POLICY_REQ_EXTS_BEG: lim = HTTPD_POLICY_PATH_LIM_EXTS_BEG; break;
738 32 : case HTTPD_POLICY_REQ_EXTS_END: lim = HTTPD_POLICY_PATH_LIM_EXTS_END; break;
739 32 : case HTTPD_POLICY_REQ_EXTS_EQ: lim = HTTPD_POLICY_PATH_LIM_EXTS_EQ; break;
740 :
741 : default:
742 0 : HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
743 : }
744 :
745 177384 : return (lim);
746 : }
747 :
748 : HTTPD_POLICY__EI int httpd_policy_ipv4_make(struct Con *con,
749 : Httpd_req_data *req,
750 : Conf_parse *conf, Conf_token *token,
751 : unsigned int type,
752 : struct sockaddr *sa, int *matches)
753 350 : {
754 175 : HTTPD_POLICY__ASSERT(con);
755 175 : HTTPD_POLICY__ASSERT(EVNT_ACPT_EXISTS(con->evnt));
756 175 : HTTPD_POLICY__ASSERT((sa == CON_CEVNT_SA(con)) || (sa == CON_SEVNT_SA(con)));
757 :
758 350 : if (sa == CON_CEVNT_SA(con))
759 : {
760 4 : if (req)
761 4 : req->vary_star = HTTPD_POLICY__TRUE;
762 : else
763 0 : con->vary_star = HTTPD_POLICY__TRUE;
764 : }
765 :
766 350 : return (opt_policy_ipv4_make(conf, token, type, sa, matches));
767 : }
768 :
769 : HTTPD_POLICY__EI int httpd_policy_ipv4_cidr_eq(struct Con *con,
770 : Httpd_req_data *req,
771 : Opt_policy_ipv4 *ipv4,
772 : struct sockaddr *sa)
773 40486 : {
774 20243 : HTTPD_POLICY__ASSERT(con);
775 20243 : HTTPD_POLICY__ASSERT((sa == CON_CEVNT_SA(con)) || (sa == CON_SEVNT_SA(con)));
776 :
777 40486 : if (sa == EVNT_SA(con->evnt))
778 : {
779 828 : if (req)
780 828 : req->vary_star = HTTPD_POLICY__TRUE;
781 : else
782 0 : con->vary_star = HTTPD_POLICY__TRUE;
783 : }
784 :
785 40486 : return (opt_policy_ipv4_cidr_eq(ipv4, sa));
786 : }
787 :
788 :
789 : #endif
790 :
791 : #endif
|