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(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 # ifdef VSTR_AUTOCONF_NDEBUG
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 #ifndef VSTR_AUTOCONF_NDEBUG
133 # define HTTPD_POLICY__ASSERT ASSERT
134 #else
135 # define HTTPD_POLICY__ASSERT(x)
136 #endif
137
138 #define HTTPD_POLICY__TRUE 1
139 #define HTTPD_POLICY__FALSE 0
140
httpd_policy_change_con(struct Con * con,const Httpd_policy_opts * policy)141 extern inline void httpd_policy_change_con(struct Con *con,
142 const Httpd_policy_opts *policy)
143 {
144 con->use_sendfile = policy->use_sendfile;
145 con->use_posix_fadvise = policy->use_posix_fadvise;
146 con->policy = policy;
147 }
148
httpd_policy_change_req(Httpd_req_data * req,const Httpd_policy_opts * policy)149 extern inline void httpd_policy_change_req(Httpd_req_data *req,
150 const Httpd_policy_opts *policy)
151 {
152 req->parse_accept = policy->use_err_406;
153 req->parse_accept_language = policy->use_err_406;
154 req->allow_accept_encoding = policy->use_enc_content_replacement;
155 if (req->vhost_prefix_len && !policy->use_vhosts_name)
156 { /* NOTE: doesn't do chk_host properly */
157 vstr_del(req->fname, 1, req->vhost_prefix_len);
158 req->vhost_prefix_len = 0;
159 }
160 if (!req->chked_encoded_path)
161 {
162 req->chk_encoded_slash = policy->chk_encoded_slash;
163 req->chk_encoded_dot = policy->chk_encoded_dot;
164 }
165 req->policy = policy;
166 }
167
httpd_policy_path_eq(const Vstr_base * s1,const Vstr_base * s2,size_t * p2,size_t * l2)168 extern inline int httpd_policy_path_eq(const Vstr_base *s1,
169 const Vstr_base *s2,
170 size_t *p2, size_t *l2)
171 {
172 return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
173 }
174
175 /* if the s1 is equal to the begining of s2 */
httpd_policy_path_beg_eq(const Vstr_base * s1,const Vstr_base * s2,size_t * p2,size_t * l2)176 extern inline int httpd_policy_path_beg_eq(const Vstr_base *s1,
177 const Vstr_base *s2,
178 size_t *p2, size_t *l2)
179 {
180 if (*l2 > s1->len)
181 *l2 = s1->len;
182 return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
183 }
184
185 /* if the s1 is equal to the end of s2 */
httpd_policy_path_end_eq(const Vstr_base * s1,const Vstr_base * s2,size_t * p2,size_t * l2)186 extern inline int httpd_policy_path_end_eq(const Vstr_base *s1,
187 const Vstr_base *s2,
188 size_t *p2, size_t *l2)
189 {
190 if (*l2 > s1->len)
191 {
192 *p2 += (*l2 - s1->len);
193 *l2 = s1->len;
194 }
195 return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
196 }
197
httpd_policy_path_mod_name(const Vstr_base * s1,size_t * pos,size_t * len)198 extern inline void httpd_policy_path_mod_name(const Vstr_base *s1,
199 size_t *pos, size_t *len)
200 {
201 size_t srch = vstr_srch_chr_rev(s1, *pos, *len, '/');
202 HTTPD_POLICY__ASSERT(srch);
203
204 *len -= vstr_sc_posdiff(*pos, srch);
205 *pos += vstr_sc_posdiff(*pos, srch);
206 }
207
httpd_policy_path_mod_dirn(const Vstr_base * s1,size_t * pos,size_t * len)208 extern inline void httpd_policy_path_mod_dirn(const Vstr_base *s1,
209 size_t *pos, size_t *len)
210 {
211 size_t srch = vstr_srch_chr_rev(s1, *pos, *len, '/');
212 HTTPD_POLICY__ASSERT(srch);
213
214 *len = vstr_sc_posdiff(*pos, srch);
215 }
216
httpd_policy_path_mod_extn(const Vstr_base * s1,size_t * pos,size_t * len)217 extern inline void httpd_policy_path_mod_extn(const Vstr_base *s1,
218 size_t *pos, size_t *len)
219 {
220 size_t srch = 0;
221
222 httpd_policy_path_mod_name(s1, pos, len);
223
224 if ((srch = vstr_srch_chr_rev(s1, *pos, *len, '.')))
225 { /* include '.' */
226 *len -= srch - *pos;
227 *pos = srch;
228 }
229 else
230 { /* at point just after basename */
231 *pos = vstr_sc_poslast(*pos, *len);
232 *len = 0;
233 }
234 }
235
httpd_policy_path_mod_exts(const Vstr_base * s1,size_t * pos,size_t * len)236 extern inline void httpd_policy_path_mod_exts(const Vstr_base *s1,
237 size_t *pos, size_t *len)
238 {
239 size_t srch = 0;
240
241 httpd_policy_path_mod_name(s1, pos, len);
242
243 if ((srch = vstr_srch_chr_fwd(s1, *pos, *len, '.')))
244 { /* include '.' */
245 *len -= srch - *pos;
246 *pos = srch;
247 }
248 else
249 { /* at point just after basename */
250 *pos = vstr_sc_poslast(*pos, *len);
251 *len = 0;
252 }
253 }
254
httpd_policy_path_mod_bwen(const Vstr_base * s1,size_t * pos,size_t * len)255 extern inline void httpd_policy_path_mod_bwen(const Vstr_base *s1,
256 size_t *pos, size_t *len)
257 {
258 size_t srch = 0;
259
260 httpd_policy_path_mod_name(s1, pos, len);
261
262 if ((srch = vstr_srch_chr_rev(s1, *pos, *len, '.')))
263 *len = vstr_sc_posdiff(*pos, srch) - 1; /* don't include '.' */
264 }
265
httpd_policy_path_mod_bwes(const Vstr_base * s1,size_t * pos,size_t * len)266 extern inline void httpd_policy_path_mod_bwes(const Vstr_base *s1,
267 size_t *pos, size_t *len)
268 {
269 size_t srch = 0;
270
271 httpd_policy_path_mod_name(s1, pos, len);
272
273 if ((srch = vstr_srch_chr_fwd(s1, *pos, *len, '.')))
274 *len = vstr_sc_posdiff(*pos, srch) - 1; /* don't include '.' */
275 }
276
httpd_policy_path_lim_eq(const Vstr_base * s1,size_t * pos,size_t * len,unsigned int lim,size_t vhost_prefix_len,Vstr_ref * ref)277 extern inline int httpd_policy_path_lim_eq(const Vstr_base *s1,
278 size_t *pos, size_t *len,
279 unsigned int lim,
280 size_t vhost_prefix_len,
281 Vstr_ref *ref)
282 {
283 const Httpd_policy_path *srch = NULL;
284
285 if (lim == HTTPD_POLICY_PATH_LIM_NONE)
286 return (HTTPD_POLICY__TRUE);
287
288 *len -= vhost_prefix_len;
289 *pos += vhost_prefix_len;
290
291 switch (lim)
292 {
293 default: HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
294
295 case HTTPD_POLICY_PATH_LIM_PATH_FULL:
296 case HTTPD_POLICY_PATH_LIM_PATH_BEG:
297 case HTTPD_POLICY_PATH_LIM_PATH_END:
298 case HTTPD_POLICY_PATH_LIM_PATH_EQ:
299 break;
300
301 case HTTPD_POLICY_PATH_LIM_NAME_FULL:
302 case HTTPD_POLICY_PATH_LIM_NAME_BEG:
303 case HTTPD_POLICY_PATH_LIM_NAME_END:
304 case HTTPD_POLICY_PATH_LIM_NAME_EQ:
305 httpd_policy_path_mod_name(s1, pos, len);
306 break;
307
308 case HTTPD_POLICY_PATH_LIM_EXTN_FULL:
309 case HTTPD_POLICY_PATH_LIM_EXTN_BEG:
310 case HTTPD_POLICY_PATH_LIM_EXTN_END:
311 case HTTPD_POLICY_PATH_LIM_EXTN_EQ:
312 httpd_policy_path_mod_extn(s1, pos, len);
313 break;
314
315 case HTTPD_POLICY_PATH_LIM_EXTS_FULL:
316 case HTTPD_POLICY_PATH_LIM_EXTS_BEG:
317 case HTTPD_POLICY_PATH_LIM_EXTS_END:
318 case HTTPD_POLICY_PATH_LIM_EXTS_EQ:
319 httpd_policy_path_mod_exts(s1, pos, len);
320 break;
321
322 case HTTPD_POLICY_PATH_LIM_BWEN_FULL:
323 case HTTPD_POLICY_PATH_LIM_BWEN_BEG:
324 case HTTPD_POLICY_PATH_LIM_BWEN_END:
325 case HTTPD_POLICY_PATH_LIM_BWEN_EQ:
326 httpd_policy_path_mod_bwen(s1, pos, len);
327 break;
328
329 case HTTPD_POLICY_PATH_LIM_BWES_FULL:
330 case HTTPD_POLICY_PATH_LIM_BWES_BEG:
331 case HTTPD_POLICY_PATH_LIM_BWES_END:
332 case HTTPD_POLICY_PATH_LIM_BWES_EQ:
333 httpd_policy_path_mod_bwes(s1, pos, len);
334 break;
335 }
336
337 if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_FULL)
338 return (HTTPD_POLICY__TRUE);
339
340 HTTPD_POLICY__ASSERT(ref);
341 srch = ref->ptr;
342
343 if (0) { }
344 else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_BEG)
345 {
346 if (!httpd_policy_path_beg_eq(srch->s1, s1, pos, len))
347 goto path_no_match;
348 }
349 else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_END)
350 {
351 if (!httpd_policy_path_end_eq(srch->s1, s1, pos, len))
352 goto path_no_match;
353 }
354 else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_EQ)
355 {
356 if (!httpd_policy_path_eq(srch->s1, s1, pos, len))
357 goto path_no_match;
358 }
359 else
360 HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
361
362 vstr_ref_del(ref); ref = NULL;
363 return (HTTPD_POLICY__TRUE);
364 path_no_match:
365 vstr_ref_del(ref); ref = NULL;
366 return (HTTPD_POLICY__FALSE);
367 }
368
httpd_policy__uri_eq(const Vstr_base * s1,const Vstr_base * s2,size_t p2,size_t l2,size_t * ret_len)369 static inline int httpd_policy__uri_eq(const Vstr_base *s1,
370 const Vstr_base *s2,
371 size_t p2, size_t l2, size_t *ret_len)
372 {
373 size_t p1 = 1;
374 size_t l1 = s1->len;
375
376 while (l1 && (l2 >= l1))
377 {
378 size_t tmp = vstr_cspn_cstr_chrs_fwd(s2, p2, l1, "%");
379 unsigned int val1 = 0;
380 unsigned int val2 = 0;
381 unsigned int num_flags = VSTR_FLAG02(PARSE_NUM_NO, BEG_ZERO, BEG_PM);
382
383 if (tmp)
384 {
385 if (!vstr_cmp_eq(s1, p1, tmp, s2, p2, tmp))
386 return (HTTPD_POLICY__FALSE);
387 l1 -= tmp; p1 += tmp;
388 l2 -= tmp; p2 += tmp;
389 continue;
390 }
391
392 if (l2 < 3)
393 return (HTTPD_POLICY__FALSE);
394 HTTPD_POLICY__ASSERT(vstr_export_chr(s2, p2) == '%');
395
396 val1 = (unsigned char)vstr_export_chr(s1, p1);
397 val2 = vstr_parse_ushort(s2, p2 + 1, 2, 16 | num_flags, &tmp, NULL);
398
399 if ((tmp != 2) || (val1 != val2))
400 return (HTTPD_POLICY__FALSE);
401
402 l1 -= 1; p1 += 1;
403 l2 -= 3; p2 += 3;
404 }
405
406 *ret_len = l2;
407 return (!l1);
408 }
409
httpd_policy_uri_eq(const Vstr_base * s1,const Vstr_base * s2,size_t * p2,size_t * l2)410 extern inline int httpd_policy_uri_eq(const Vstr_base *s1,
411 const Vstr_base *s2,
412 size_t *p2, size_t *l2)
413 {
414 size_t tmp = 0;
415 return (httpd_policy__uri_eq(s1, s2, *p2, *l2, &tmp) && !tmp);
416 }
417
418 /* if the s1 is equal to the begining of s2 */
httpd_policy_uri_beg_eq(const Vstr_base * s1,const Vstr_base * s2,size_t * p2,size_t * l2)419 extern inline int httpd_policy_uri_beg_eq(const Vstr_base *s1,
420 const Vstr_base *s2,
421 size_t *p2, size_t *l2)
422 {
423 size_t tmp = 0;
424
425 if (!httpd_policy__uri_eq(s1, s2, *p2, *l2, &tmp))
426 return (HTTPD_POLICY__FALSE);
427
428 if (tmp) *l2 -= tmp;
429
430 return (HTTPD_POLICY__TRUE);
431 }
432
433 /* if the s1 is equal to the end of s2 */
httpd_policy_uri_end_eq(const Vstr_base * s1,const Vstr_base * s2,size_t * p2,size_t * l2)434 extern inline int httpd_policy_uri_end_eq(const Vstr_base *s1,
435 const Vstr_base *s2,
436 size_t *p2, size_t *l2)
437 {
438 if (!vstr_srch_chr_fwd(s2, *p2, *l2, '%'))
439 {
440 if (*l2 > s1->len)
441 {
442 *p2 += (*l2 - s1->len);
443 *l2 = s1->len;
444 }
445 return (vstr_cmp_eq(s1, 1, s1->len, s2, *p2, *l2));
446 }
447
448 if (*l2 > (s1->len * 3))
449 {
450 *p2 += (*l2 - (s1->len * 3));
451 *l2 = (s1->len * 3);
452 }
453
454 while (*l2 >= s1->len)
455 {
456 size_t tmp = 0;
457 if (httpd_policy__uri_eq(s1, s2, *p2, *l2, &tmp) && !tmp)
458 return (HTTPD_POLICY__TRUE);
459 *l2 -= 1; *p2 += 1;
460 }
461
462 return (HTTPD_POLICY__FALSE);
463 }
464
httpd_policy_uri_mod_name(const Vstr_base * s1,size_t * pos,size_t * len)465 extern inline void httpd_policy_uri_mod_name(const Vstr_base *s1,
466 size_t *pos, size_t *len)
467 {
468 size_t srch1 = vstr_srch_chr_rev(s1, *pos, *len, '/');
469 size_t srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2f");
470 HTTPD_POLICY__ASSERT(srch1);
471
472 if (srch1 < srch2)
473 srch1 = srch2 + 2;
474
475 *len -= vstr_sc_posdiff(*pos, srch1);
476 *pos += vstr_sc_posdiff(*pos, srch1);
477 }
478
httpd_policy_uri_mod_dirn(const Vstr_base * s1,size_t * pos,size_t * len)479 extern inline void httpd_policy_uri_mod_dirn(const Vstr_base *s1,
480 size_t *pos, size_t *len)
481 {
482 size_t srch1 = vstr_srch_chr_rev(s1, *pos, *len, '/');
483 size_t srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2f");
484 HTTPD_POLICY__ASSERT(srch1);
485
486 if (srch1 < srch2)
487 srch1 = srch2 + 2;
488
489 *len = vstr_sc_posdiff(*pos, srch1);
490 }
491
httpd_policy_uri_mod_extn(const Vstr_base * s1,size_t * pos,size_t * len)492 extern inline void httpd_policy_uri_mod_extn(const Vstr_base *s1,
493 size_t *pos, size_t *len)
494 {
495 size_t srch1 = 0;
496 size_t srch2 = 0;
497
498 httpd_policy_uri_mod_name(s1, pos, len);
499
500 srch1 = vstr_srch_chr_rev(s1, *pos, *len, '.');
501 srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2e");
502
503 if (srch1 < srch2)
504 srch1 = srch2;
505
506 if (srch1)
507 { /* include '.' or "%2e" */
508 *len -= srch1 - *pos;
509 *pos = srch1;
510 }
511 else
512 { /* at point just after basename */
513 *pos = vstr_sc_poslast(*pos, *len);
514 *len = 0;
515 }
516 }
517
httpd_policy_uri_mod_exts(const Vstr_base * s1,size_t * pos,size_t * len)518 extern inline void httpd_policy_uri_mod_exts(const Vstr_base *s1,
519 size_t *pos, size_t *len)
520 {
521 size_t srch1 = 0;
522 size_t srch2 = 0;
523
524 httpd_policy_uri_mod_name(s1, pos, len);
525
526 srch1 = vstr_srch_chr_fwd(s1, *pos, *len, '.');
527 srch2 = vstr_srch_case_cstr_buf_fwd(s1, *pos, *len, "%2e");
528
529 if (srch1 > srch2)
530 srch1 = srch2;
531
532 if (srch1)
533 { /* include '.' or "%2e" */
534 *len -= srch1 - *pos;
535 *pos = srch1;
536 }
537 else
538 { /* at point just after basename */
539 *pos = vstr_sc_poslast(*pos, *len);
540 *len = 0;
541 }
542 }
543
httpd_policy_uri_mod_bwen(const Vstr_base * s1,size_t * pos,size_t * len)544 extern inline void httpd_policy_uri_mod_bwen(const Vstr_base *s1,
545 size_t *pos, size_t *len)
546 {
547 size_t srch1 = 0;
548 size_t srch2 = 0;
549 unsigned int num = 1;
550
551 httpd_policy_uri_mod_name(s1, pos, len);
552
553 srch1 = vstr_srch_chr_rev(s1, *pos, *len, '.');
554 srch2 = vstr_srch_case_cstr_buf_rev(s1, *pos, *len, "%2e");
555
556 if (srch1 < srch2)
557 {
558 srch1 = srch2;
559 num = 3;
560 }
561
562 if (srch1)
563 *len = vstr_sc_posdiff(*pos, srch1) - num; /* don't include '.' */
564 }
565
httpd_policy_uri_mod_bwes(const Vstr_base * s1,size_t * pos,size_t * len)566 extern inline void httpd_policy_uri_mod_bwes(const Vstr_base *s1,
567 size_t *pos, size_t *len)
568 {
569 size_t srch1 = 0;
570 size_t srch2 = 0;
571 unsigned int num = 1;
572
573 httpd_policy_uri_mod_name(s1, pos, len);
574
575 srch1 = vstr_srch_chr_fwd(s1, *pos, *len, '.');
576 srch2 = vstr_srch_case_cstr_buf_fwd(s1, *pos, *len, "%2e");
577
578 if (srch1 > srch2)
579 {
580 srch1 = srch2;
581 num = 3;
582 }
583
584 if (srch1)
585 *len = vstr_sc_posdiff(*pos, srch1) - num; /* don't include '.' */
586 }
587
httpd_policy_uri_lim_eq(const Vstr_base * s1,size_t * pos,size_t * len,unsigned int lim,int slash_dot_safe,Vstr_ref * ref)588 extern inline int httpd_policy_uri_lim_eq(const Vstr_base *s1,
589 size_t *pos, size_t *len,
590 unsigned int lim, int slash_dot_safe,
591 Vstr_ref *ref)
592 {
593 const Httpd_policy_path *srch = NULL;
594
595 switch (lim)
596 {
597 default: HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
598 case HTTPD_POLICY_PATH_LIM_NONE:
599 HTTPD_POLICY__ASSERT(!ref);
600 return (HTTPD_POLICY__TRUE);
601
602 case HTTPD_POLICY_PATH_LIM_PATH_FULL:
603 case HTTPD_POLICY_PATH_LIM_PATH_BEG:
604 case HTTPD_POLICY_PATH_LIM_PATH_END:
605 case HTTPD_POLICY_PATH_LIM_PATH_EQ:
606 break;
607
608 case HTTPD_POLICY_PATH_LIM_NAME_FULL:
609 case HTTPD_POLICY_PATH_LIM_NAME_BEG:
610 case HTTPD_POLICY_PATH_LIM_NAME_END:
611 case HTTPD_POLICY_PATH_LIM_NAME_EQ:
612 if (slash_dot_safe)
613 httpd_policy_path_mod_name(s1, pos, len);
614 else
615 httpd_policy_uri_mod_name(s1, pos, len);
616 break;
617
618 case HTTPD_POLICY_PATH_LIM_EXTN_FULL:
619 case HTTPD_POLICY_PATH_LIM_EXTN_BEG:
620 case HTTPD_POLICY_PATH_LIM_EXTN_END:
621 case HTTPD_POLICY_PATH_LIM_EXTN_EQ:
622 if (slash_dot_safe)
623 httpd_policy_path_mod_extn(s1, pos, len);
624 else
625 httpd_policy_uri_mod_extn(s1, pos, len);
626 break;
627
628 case HTTPD_POLICY_PATH_LIM_EXTS_FULL:
629 case HTTPD_POLICY_PATH_LIM_EXTS_BEG:
630 case HTTPD_POLICY_PATH_LIM_EXTS_END:
631 case HTTPD_POLICY_PATH_LIM_EXTS_EQ:
632 if (slash_dot_safe)
633 httpd_policy_path_mod_exts(s1, pos, len);
634 else
635 httpd_policy_uri_mod_exts(s1, pos, len);
636 break;
637
638 case HTTPD_POLICY_PATH_LIM_BWEN_FULL:
639 case HTTPD_POLICY_PATH_LIM_BWEN_BEG:
640 case HTTPD_POLICY_PATH_LIM_BWEN_END:
641 case HTTPD_POLICY_PATH_LIM_BWEN_EQ:
642 if (slash_dot_safe)
643 httpd_policy_path_mod_bwen(s1, pos, len);
644 else
645 httpd_policy_uri_mod_bwen(s1, pos, len);
646 break;
647
648 case HTTPD_POLICY_PATH_LIM_BWES_FULL:
649 case HTTPD_POLICY_PATH_LIM_BWES_BEG:
650 case HTTPD_POLICY_PATH_LIM_BWES_END:
651 case HTTPD_POLICY_PATH_LIM_BWES_EQ:
652 if (slash_dot_safe)
653 httpd_policy_path_mod_bwes(s1, pos, len);
654 else
655 httpd_policy_uri_mod_bwes(s1, pos, len);
656 break;
657 }
658
659 if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_FULL)
660 {
661 HTTPD_POLICY__ASSERT(!ref);
662 return (HTTPD_POLICY__TRUE);
663 }
664
665 HTTPD_POLICY__ASSERT(ref);
666 srch = ref->ptr;
667
668 if (0) { }
669 else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_BEG)
670 {
671 if (!httpd_policy_uri_beg_eq(srch->s1, s1, pos, len))
672 goto path_no_match;
673 }
674 else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_END)
675 {
676 if (!httpd_policy_uri_end_eq(srch->s1, s1, pos, len))
677 goto path_no_match;
678 }
679 else if ((lim & HTTPD_POLICY__PATH_LIM_MASK) == HTTPD_POLICY__PATH_LIM_EQ)
680 {
681 if (!httpd_policy_uri_eq(srch->s1, s1, pos, len))
682 goto path_no_match;
683 }
684 else
685 HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
686
687 vstr_ref_del(ref); ref = NULL;
688 return (HTTPD_POLICY__TRUE);
689 path_no_match:
690 vstr_ref_del(ref); ref = NULL;
691 return (HTTPD_POLICY__FALSE);
692 }
693
httpd_policy_path_req2lim(unsigned int type)694 extern inline int httpd_policy_path_req2lim(unsigned int type)
695 {
696 unsigned int lim = HTTPD_POLICY_PATH_LIM_NONE;
697
698 switch (type)
699 {
700 case HTTPD_POLICY_REQ_PATH_BEG: lim = HTTPD_POLICY_PATH_LIM_PATH_BEG; break;
701 case HTTPD_POLICY_REQ_PATH_END: lim = HTTPD_POLICY_PATH_LIM_PATH_END; break;
702 case HTTPD_POLICY_REQ_PATH_EQ: lim = HTTPD_POLICY_PATH_LIM_PATH_EQ; break;
703
704 case HTTPD_POLICY_REQ_NAME_BEG: lim = HTTPD_POLICY_PATH_LIM_NAME_BEG; break;
705 case HTTPD_POLICY_REQ_NAME_END: lim = HTTPD_POLICY_PATH_LIM_NAME_END; break;
706 case HTTPD_POLICY_REQ_NAME_EQ: lim = HTTPD_POLICY_PATH_LIM_NAME_EQ; break;
707
708 case HTTPD_POLICY_REQ_BWEN_BEG: lim = HTTPD_POLICY_PATH_LIM_BWEN_BEG; break;
709 case HTTPD_POLICY_REQ_BWEN_END: lim = HTTPD_POLICY_PATH_LIM_BWEN_END; break;
710 case HTTPD_POLICY_REQ_BWEN_EQ: lim = HTTPD_POLICY_PATH_LIM_BWEN_EQ; break;
711
712 case HTTPD_POLICY_REQ_BWES_BEG: lim = HTTPD_POLICY_PATH_LIM_BWES_BEG; break;
713 case HTTPD_POLICY_REQ_BWES_END: lim = HTTPD_POLICY_PATH_LIM_BWES_END; break;
714 case HTTPD_POLICY_REQ_BWES_EQ: lim = HTTPD_POLICY_PATH_LIM_BWES_EQ; break;
715
716 case HTTPD_POLICY_REQ_EXTN_BEG: lim = HTTPD_POLICY_PATH_LIM_EXTN_BEG; break;
717 case HTTPD_POLICY_REQ_EXTN_END: lim = HTTPD_POLICY_PATH_LIM_EXTN_END; break;
718 case HTTPD_POLICY_REQ_EXTN_EQ: lim = HTTPD_POLICY_PATH_LIM_EXTN_EQ; break;
719
720 case HTTPD_POLICY_REQ_EXTS_BEG: lim = HTTPD_POLICY_PATH_LIM_EXTS_BEG; break;
721 case HTTPD_POLICY_REQ_EXTS_END: lim = HTTPD_POLICY_PATH_LIM_EXTS_END; break;
722 case HTTPD_POLICY_REQ_EXTS_EQ: lim = HTTPD_POLICY_PATH_LIM_EXTS_EQ; break;
723
724 default:
725 HTTPD_POLICY__ASSERT(HTTPD_POLICY__FALSE);
726 }
727
728 return (lim);
729 }
730
httpd_policy_ipv4_make(struct Con * con,Httpd_req_data * req,Conf_parse * conf,Conf_token * token,unsigned int type,struct sockaddr * sa,int * matches)731 extern inline int httpd_policy_ipv4_make(struct Con *con, Httpd_req_data *req,
732 Conf_parse *conf, Conf_token *token,
733 unsigned int type,
734 struct sockaddr *sa, int *matches)
735 {
736 HTTPD_POLICY__ASSERT(con);
737
738 if (sa == EVNT_SA(con->evnt))
739 {
740 if (req)
741 req->vary_star = HTTPD_POLICY__TRUE;
742 else
743 con->vary_star = HTTPD_POLICY__TRUE;
744 }
745
746 return (opt_policy_ipv4_make(conf, token, type, sa, matches));
747 }
748
httpd_policy_ipv4_cidr_eq(struct Con * con,Httpd_req_data * req,Opt_policy_ipv4 * ipv4,struct sockaddr * sa)749 extern inline int httpd_policy_ipv4_cidr_eq(struct Con *con,Httpd_req_data *req,
750 Opt_policy_ipv4 *ipv4,
751 struct sockaddr *sa)
752 {
753 HTTPD_POLICY__ASSERT(con);
754
755 if (sa == EVNT_SA(con->evnt))
756 {
757 if (req)
758 req->vary_star = HTTPD_POLICY__TRUE;
759 else
760 con->vary_star = HTTPD_POLICY__TRUE;
761 }
762
763 return (opt_policy_ipv4_cidr_eq(ipv4, sa));
764 }
765
766
767 #endif
768
769 #endif
770