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 #define HTTPD_CONF_MAIN_MATCH_CON 1
11 #define HTTPD_CONF_MAIN_MATCH_REQ 2
12
13 #define HTTPD_POLICY_CON_POLICY 3
14 #define HTTPD_POLICY_REQ_POLICY 4
15
16 #define HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ 5
17 #define HTTPD_POLICY_SERVER_IPV4_CIDR_EQ 6
18
19 static int httpd__policy_connection_tst_d1(struct Con *,
20 Conf_parse *, Conf_token *,
21 int *);
22
httpd__policy_connection_tst_op_d1(Conf_parse * conf,Conf_token * token,int * matches,void * con)23 static int httpd__policy_connection_tst_op_d1(Conf_parse *conf,
24 Conf_token *token,
25 int *matches, void *con)
26 {
27 return (httpd__policy_connection_tst_d1(con, conf, token, matches));
28 }
29
30
httpd__policy_connection_tst_d1(struct Con * con,Conf_parse * conf,Conf_token * token,int * matches)31 static int httpd__policy_connection_tst_d1(struct Con *con,
32 Conf_parse *conf, Conf_token *token,
33 int *matches)
34 {
35 int clist = FALSE;
36
37 ASSERT(con);
38 ASSERT(matches);
39
40 CONF_SC_TOGGLE_CLIST_VAR(clist);
41
42 if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
43 {
44 unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
45 unsigned int nxt = 0;
46 Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
47
48 switch (type)
49 {
50 case HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ:
51 {
52 struct sockaddr *sa = CON_CEVNT_SA(con);
53 *matches = httpd_policy_ipv4_cidr_eq(con, NULL, ref->ptr, sa);
54 }
55 break;
56
57 case HTTPD_POLICY_SERVER_IPV4_CIDR_EQ:
58 {
59 struct sockaddr *sa = CON_SEVNT_SA(con);
60 *matches = httpd_policy_ipv4_cidr_eq(con, NULL, ref->ptr, sa);
61 }
62 break;
63
64 default:
65 vstr_ref_del(ref);
66 return (FALSE);
67 }
68
69 vstr_ref_del(ref);
70 if (nxt)
71 return (conf_parse_num_token(conf, token, nxt));
72 }
73
74 else if (OPT_SERV_SYM_EQ("policy-eq") || OPT_SERV_SYM_EQ("policy=="))
75 return (opt_policy_name_eq(conf, token, con->policy->s, matches));
76 else if (OPT_SERV_SYM_EQ("client-ipv4-cidr-eq") ||
77 OPT_SERV_SYM_EQ("client-ipv4-cidr=="))
78 return (httpd_policy_ipv4_make(con, NULL, conf, token,
79 HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ,
80 CON_CEVNT_SA(con), matches));
81 else if (OPT_SERV_SYM_EQ("server-ipv4-cidr-eq") ||
82 OPT_SERV_SYM_EQ("server-ipv4-cidr=="))
83 return (httpd_policy_ipv4_make(con, NULL, conf, token,
84 HTTPD_POLICY_SERVER_IPV4_CIDR_EQ,
85 CON_SEVNT_SA(con), matches));
86 else if (OPT_SERV_SYM_EQ("server-ipv4-port-eq") ||
87 OPT_SERV_SYM_EQ("server-ipv4-port=="))
88 {
89 struct sockaddr *sa = CON_SEVNT_SA(con);
90 unsigned int tst_port = 0;
91
92 OPT_SERV_X_UINT(tst_port);
93
94 if (sa->sa_family != AF_INET)
95 *matches = FALSE;
96 else
97 {
98 struct sockaddr_in *sin = CON_SEVNT_SA_IN4(con);
99 *matches = tst_port == ntohs(sin->sin_port);
100 }
101 }
102
103 else
104 return (opt_serv_sc_tst(conf, token, matches,
105 httpd__policy_connection_tst_op_d1, con));
106
107 return (TRUE);
108 }
109
httpd__policy_build(struct Con * con,Conf_parse * conf,Conf_token * token,unsigned int utype)110 static const Httpd_policy_opts *httpd__policy_build(struct Con *con,
111 Conf_parse *conf,
112 Conf_token *token,
113 unsigned int utype)
114 {
115 Opt_serv_policy_opts *policy = NULL;
116 Vstr_ref *ref = NULL;
117 Conf_token save;
118
119 save = *token;
120 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
121 if (!(policy = opt_policy_find(con->policy->s->beg, conf, token)))
122 return (NULL);
123
124 ref = policy->ref;
125 if (!conf_token_set_user_value(conf, &save, utype, ref, token->num))
126 return (NULL);
127
128 return ((const Httpd_policy_opts *)policy);
129 }
130
httpd__policy_connection_d1(struct Con * con,Conf_parse * conf,Conf_token * token)131 static int httpd__policy_connection_d1(struct Con *con,
132 Conf_parse *conf, Conf_token *token)
133 {
134 int clist = FALSE;
135
136 CONF_SC_TOGGLE_CLIST_VAR(clist);
137
138 if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
139 {
140 unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
141 unsigned int nxt = 0;
142 Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
143
144 switch (type)
145 {
146 case HTTPD_POLICY_CON_POLICY:
147 httpd_policy_change_con(con, ref->ptr);
148 break;
149
150 default:
151 vstr_ref_del(ref);
152 return (FALSE);
153 }
154
155 vstr_ref_del(ref);
156 if (nxt)
157 return (conf_parse_num_token(conf, token, nxt));
158 }
159
160 else if (OPT_SERV_SYM_EQ("<close>"))
161 {
162 evnt_close(con->evnt);
163 return (TRUE);
164 }
165 else if (OPT_SERV_SYM_EQ("policy"))
166 {
167 const Httpd_policy_opts *policy = NULL;
168
169 policy = httpd__policy_build(con, conf, token, HTTPD_POLICY_CON_POLICY);
170 httpd_policy_change_con(con, policy);
171 }
172 else if (OPT_SERV_SYM_EQ("Vary:_*"))
173 OPT_SERV_X_TOGGLE(con->vary_star);
174
175 else
176 return (FALSE);
177
178 return (TRUE);
179 }
180
httpd__policy_connection_d0(struct Con * con,Conf_parse * conf,Conf_token * token)181 static int httpd__policy_connection_d0(struct Con *con,
182 Conf_parse *conf, Conf_token *token)
183 {
184 unsigned int depth = token->depth_num;
185 int matches = TRUE;
186
187 CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
188 ++depth;
189 while (conf_token_list_num(token, depth))
190 {
191 CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
192
193 if (!httpd__policy_connection_tst_d1(con, conf, token, &matches))
194 return (FALSE);
195
196 if (!matches)
197 return (TRUE);
198 }
199 --depth;
200
201 while (conf_token_list_num(token, depth))
202 {
203 CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
204
205 if (!httpd__policy_connection_d1(con, conf, token))
206 return (FALSE);
207 if (con->evnt->flag_q_closed) /* don't do anything else */
208 return (TRUE);
209 }
210
211 return (TRUE);
212 }
213
httpd_policy_connection(struct Con * con,Conf_parse * conf,const Conf_token * beg_token)214 int httpd_policy_connection(struct Con *con,
215 Conf_parse *conf, const Conf_token *beg_token)
216 {
217 Conf_token token[1];
218 unsigned int num = 0;
219
220 if (!beg_token->num) /* not been parsed */
221 return (TRUE);
222
223 *token = *beg_token;
224
225 num = token->num;
226 while (num)
227 {
228 if (!conf_parse_num_token(conf, token, num))
229 goto conf_fail;
230
231 assert(token->type == (CONF_TOKEN_TYPE_USER_BEG+HTTPD_CONF_MAIN_MATCH_CON));
232
233 conf_token_get_user_value(conf, token, &num);
234
235 if (!httpd__policy_connection_d0(con, conf, token))
236 goto conf_fail;
237 }
238
239 vstr_del(conf->tmp, 1, conf->tmp->len);
240 return (TRUE);
241
242 conf_fail:
243 vstr_del(conf->tmp, 1, conf->tmp->len);
244 conf_parse_backtrace(conf->tmp, "<policy-connection>", conf, token);
245 return (FALSE);
246 }
247
248 struct Httpd__policy_req_tst_data
249 {
250 struct Con *con;
251 Httpd_req_data *req;
252 };
253
254 static int httpd__policy_request_tst_d1(struct Con *, Httpd_req_data *,
255 Conf_parse *, Conf_token *, int *);
256
httpd__policy_request_tst_op_d1(Conf_parse * conf,Conf_token * token,int * matches,void * passed_data)257 static int httpd__policy_request_tst_op_d1(Conf_parse *conf, Conf_token *token,
258 int *matches, void *passed_data)
259 {
260 struct Httpd__policy_req_tst_data *data = passed_data;
261 struct Con *con = data->con;
262 Httpd_req_data *req = data->req;
263
264 return (httpd__policy_request_tst_d1(con, req, conf, token, matches));
265 }
266
httpd__policy_request_tst_d1(struct Con * con,Httpd_req_data * req,Conf_parse * conf,Conf_token * token,int * matches)267 static int httpd__policy_request_tst_d1(struct Con *con,
268 Httpd_req_data *req,
269 Conf_parse *conf, Conf_token *token,
270 int *matches)
271 {
272 Vstr_base *http_data = con->evnt->io_r;
273 int clist = FALSE;
274
275 ASSERT(con && req);
276 ASSERT(matches);
277
278 CONF_SC_TOGGLE_CLIST_VAR(clist);
279
280 if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
281 {
282 unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
283 unsigned int nxt = 0;
284 Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
285
286 switch (type)
287 {
288 case HTTPD_POLICY_REQ_PATH_BEG:
289 case HTTPD_POLICY_REQ_PATH_END:
290 case HTTPD_POLICY_REQ_PATH_EQ:
291
292 case HTTPD_POLICY_REQ_NAME_BEG:
293 case HTTPD_POLICY_REQ_NAME_END:
294 case HTTPD_POLICY_REQ_NAME_EQ:
295
296 case HTTPD_POLICY_REQ_BWEN_BEG:
297 case HTTPD_POLICY_REQ_BWEN_END:
298 case HTTPD_POLICY_REQ_BWEN_EQ:
299
300 case HTTPD_POLICY_REQ_BWES_BEG:
301 case HTTPD_POLICY_REQ_BWES_END:
302 case HTTPD_POLICY_REQ_BWES_EQ:
303
304 case HTTPD_POLICY_REQ_EXTN_BEG:
305 case HTTPD_POLICY_REQ_EXTN_END:
306 case HTTPD_POLICY_REQ_EXTN_EQ:
307
308 case HTTPD_POLICY_REQ_EXTS_BEG:
309 case HTTPD_POLICY_REQ_EXTS_END:
310 case HTTPD_POLICY_REQ_EXTS_EQ:
311 {
312 size_t pos = 1;
313 size_t len = req->fname->len;
314 unsigned int lim = httpd_policy_path_req2lim(type);
315
316 vstr_ref_add(ref);
317 *matches = httpd_policy_path_lim_eq(req->fname, &pos, &len, lim,
318 req->vhost_prefix_len, ref);
319 }
320 break;
321
322 case HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ:
323 {
324 struct sockaddr *sa = CON_CEVNT_SA(con);
325 *matches = httpd_policy_ipv4_cidr_eq(con, req, ref->ptr, sa);
326 }
327 break;
328
329 case HTTPD_POLICY_SERVER_IPV4_CIDR_EQ:
330 {
331 struct sockaddr *sa = CON_SEVNT_SA(con);
332 *matches = httpd_policy_ipv4_cidr_eq(con, req, ref->ptr, sa);
333 }
334
335 default:
336 vstr_ref_del(ref);
337 return (FALSE);
338 }
339
340 vstr_ref_del(ref);
341 if (nxt)
342 return (conf_parse_num_token(conf, token, nxt));
343 }
344
345 else if (OPT_SERV_SYM_EQ("policy-eq") || OPT_SERV_SYM_EQ("policy=="))
346 return (opt_policy_name_eq(conf, token, req->policy->s, matches));
347 else if (OPT_SERV_SYM_EQ("client-ipv4-cidr-eq") ||
348 OPT_SERV_SYM_EQ("client-ipv4-cidr=="))
349 return (httpd_policy_ipv4_make(con, req, conf, token,
350 HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ,
351 CON_CEVNT_SA(con), matches));
352 else if (OPT_SERV_SYM_EQ("server-ipv4-cidr-eq") ||
353 OPT_SERV_SYM_EQ("server-ipv4-cidr=="))
354 return (httpd_policy_ipv4_make(con, req, conf, token,
355 HTTPD_POLICY_SERVER_IPV4_CIDR_EQ,
356 CON_SEVNT_SA(con), matches));
357 else if (OPT_SERV_SYM_EQ("hostname-eq") || OPT_SERV_SYM_EQ("hostname=="))
358 { /* doesn't do escaping because DNS is ASCII */
359 Vstr_sect_node *h_h = req->http_hdrs->hdr_host;
360 Vstr_base *d_h = req->policy->default_hostname;
361
362 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
363 if (h_h->len)
364 *matches = conf_token_cmp_case_val_eq(conf, token,
365 http_data, h_h->pos, h_h->len);
366 else
367 *matches = conf_token_cmp_case_val_eq(conf, token,
368 d_h, 1, d_h->len);
369 }
370 else if (OPT_SERV_SYM_EQ("user-agent-eq") || OPT_SERV_SYM_EQ("UA-eq") ||
371 OPT_SERV_SYM_EQ("user-agent==") || OPT_SERV_SYM_EQ("UA=="))
372 { /* doesn't do escaping because URLs are ASCII */
373 Vstr_sect_node *h_ua = req->http_hdrs->hdr_ua;
374
375 req->vary_ua = TRUE;
376 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
377 *matches = conf_token_cmp_case_val_eq(conf, token, http_data, 1, h_ua->len);
378 }
379 else if (OPT_SERV_SYM_EQ("user-agent-search-eq") ||
380 OPT_SERV_SYM_EQ("user-agent-search==") ||
381 OPT_SERV_SYM_EQ("user-agent-srch-eq") ||
382 OPT_SERV_SYM_EQ("user-agent-srch==") ||
383 OPT_SERV_SYM_EQ("UA-srch-eq") ||
384 OPT_SERV_SYM_EQ("UA-srch=="))
385 { /* doesn't do escaping because URLs are ASCII */
386 Vstr_sect_node *h_ua = req->http_hdrs->hdr_ua;
387
388 req->vary_ua = TRUE;
389 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
390 *matches = !!conf_token_srch_case_val(conf, token, http_data, 1, h_ua->len);
391 }
392 else if (OPT_SERV_SYM_EQ("referrer-eq") || OPT_SERV_SYM_EQ("referer-eq") ||
393 OPT_SERV_SYM_EQ("referrer==") || OPT_SERV_SYM_EQ("referer=="))
394 { /* doesn't do escaping because URLs are ASCII */
395 Vstr_sect_node *h_ref = req->http_hdrs->hdr_referer;
396
397 req->vary_rf = TRUE;
398 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
399 *matches = conf_token_cmp_case_val_eq(conf, token,
400 http_data, 1, h_ref->len);
401 }
402 else if (OPT_SERV_SYM_EQ("referrer-beg") || OPT_SERV_SYM_EQ("referer-beg"))
403 { /* doesn't do escaping because URLs are ASCII */
404 Vstr_sect_node *h_ref = req->http_hdrs->hdr_referer;
405
406 req->vary_rf = TRUE;
407 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
408 *matches = conf_token_cmp_case_val_beg_eq(conf, token,
409 http_data, 1, h_ref->len);
410 }
411 else if (OPT_SERV_SYM_EQ("referrer-search-eq") ||
412 OPT_SERV_SYM_EQ("referrer-search==") ||
413 OPT_SERV_SYM_EQ("referrer-srch-eq") ||
414 OPT_SERV_SYM_EQ("referrer-srch==") ||
415 OPT_SERV_SYM_EQ("referer-search-eq") ||
416 OPT_SERV_SYM_EQ("referer-search==") ||
417 OPT_SERV_SYM_EQ("referer-srch-eq") ||
418 OPT_SERV_SYM_EQ("referer-srch=="))
419 { /* doesn't do escaping because URLs are ASCII */
420 Vstr_sect_node *h_ref = req->http_hdrs->hdr_referer;
421
422 req->vary_rf = TRUE;
423 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
424 *matches = !!conf_token_srch_case_val(conf, token,
425 http_data, 1, h_ref->len);
426 }
427 else if (OPT_SERV_SYM_EQ("http-0.9-eq") || OPT_SERV_SYM_EQ("http-0.9=="))
428 *matches = req->ver_0_9;
429 else if (OPT_SERV_SYM_EQ("http-1.0-eq") || OPT_SERV_SYM_EQ("http-1.0=="))
430 *matches = !req->ver_0_9 && !req->ver_1_1;
431 else if (OPT_SERV_SYM_EQ("http-1.1-eq") || OPT_SERV_SYM_EQ("http-1.1=="))
432 *matches = !req->ver_0_9 && req->ver_1_1;
433 else if (OPT_SERV_SYM_EQ("method-eq") || OPT_SERV_SYM_EQ("method=="))
434 { /* doesn't do escaping because methods are ASCII */
435 Vstr_sect_node *meth = VSTR_SECTS_NUM(req->sects, 1);
436
437 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
438 *matches = conf_token_cmp_case_val_eq(conf, token,
439 http_data, meth->pos, meth->len);
440 }
441 else if (OPT_SERV_SYM_EQ("tm-dow-eq") || OPT_SERV_SYM_EQ("tm-dow=="))
442 { /* so we can do msff :) */
443 Opt_serv_opts *opts = req->policy->s->beg;
444 Httpd_opts *hopts = (Httpd_opts *)opts;
445 const struct tm *tm = date_gmtime(hopts->date, req->now);
446 int tmp = 0;
447
448 if (!tm) return (FALSE);
449
450 /* vary_star ... or nothing ? */
451 OPT_SERV_X_UINT(tmp);
452 *matches = tmp == tm->tm_wday;
453 }
454 else
455 { /* spend time doing path/name/extn/bnwe */
456 Vstr_ref *ref = NULL;
457 unsigned int type = HTTPD_POLICY_REQ_PATH_BEG;
458 unsigned int lim = 0;
459 size_t pos = 1;
460 size_t len = req->fname->len;
461
462 if (0) { }
463 else if (OPT_SERV_SYM_EQ("path-beg"))
464 type = HTTPD_POLICY_REQ_PATH_BEG;
465 else if (OPT_SERV_SYM_EQ("path-end"))
466 type = HTTPD_POLICY_REQ_PATH_END;
467 else if (OPT_SERV_SYM_EQ("path-eq") || OPT_SERV_SYM_EQ("path=="))
468 type = HTTPD_POLICY_REQ_PATH_EQ;
469 else if (OPT_SERV_SYM_EQ("basename-beg"))
470 type = HTTPD_POLICY_REQ_NAME_BEG;
471 else if (OPT_SERV_SYM_EQ("basename-end"))
472 type = HTTPD_POLICY_REQ_NAME_END;
473 else if (OPT_SERV_SYM_EQ("basename-eq") || OPT_SERV_SYM_EQ("basename=="))
474 type = HTTPD_POLICY_REQ_NAME_EQ;
475 else if (OPT_SERV_SYM_EQ("extension-beg"))
476 type = HTTPD_POLICY_REQ_EXTN_BEG;
477 else if (OPT_SERV_SYM_EQ("extension-end"))
478 type = HTTPD_POLICY_REQ_EXTN_END;
479 else if (OPT_SERV_SYM_EQ("extension-eq") || OPT_SERV_SYM_EQ("extension=="))
480 type = HTTPD_POLICY_REQ_EXTN_EQ;
481 else if (OPT_SERV_SYM_EQ("extensions-beg"))
482 type = HTTPD_POLICY_REQ_EXTS_BEG;
483 else if (OPT_SERV_SYM_EQ("extensions-end"))
484 type = HTTPD_POLICY_REQ_EXTS_END;
485 else if (OPT_SERV_SYM_EQ("extensions-eq") ||
486 OPT_SERV_SYM_EQ("extensions=="))
487 type = HTTPD_POLICY_REQ_EXTS_EQ;
488 else if (OPT_SERV_SYM_EQ("basename-without-extension-beg"))
489 type = HTTPD_POLICY_REQ_BWEN_BEG;
490 else if (OPT_SERV_SYM_EQ("basename-without-extension-end"))
491 type = HTTPD_POLICY_REQ_BWEN_END;
492 else if (OPT_SERV_SYM_EQ("basename-without-extension-eq") ||
493 OPT_SERV_SYM_EQ("basename-without-extension=="))
494 type = HTTPD_POLICY_REQ_BWEN_EQ;
495 else if (OPT_SERV_SYM_EQ("basename-without-extensions-beg"))
496 type = HTTPD_POLICY_REQ_BWES_BEG;
497 else if (OPT_SERV_SYM_EQ("basename-without-extensions-end"))
498 type = HTTPD_POLICY_REQ_BWES_END;
499 else if (OPT_SERV_SYM_EQ("basename-without-extensions-eq") ||
500 OPT_SERV_SYM_EQ("basename-without-extensions=="))
501 type = HTTPD_POLICY_REQ_BWES_EQ;
502 else
503 {
504 struct Httpd__policy_req_tst_data data[1];
505
506 data->con = con;
507 data->req = req;
508 return (opt_serv_sc_tst(conf, token, matches,
509 httpd__policy_request_tst_op_d1, data));
510 }
511
512 if (!httpd_policy_path_make(con, req, conf, token, type, &ref))
513 {
514 vstr_ref_del(ref);
515 return (FALSE);
516 }
517
518 lim = httpd_policy_path_req2lim(type);
519 *matches = httpd_policy_path_lim_eq(req->fname, &pos, &len, lim,
520 req->vhost_prefix_len, ref);
521 }
522
523 return (TRUE);
524 }
525
httpd__policy_request_d1(struct Con * con,struct Httpd_req_data * req,Conf_parse * conf,Conf_token * token)526 static int httpd__policy_request_d1(struct Con *con, struct Httpd_req_data *req,
527 Conf_parse *conf, Conf_token *token)
528 {
529 int clist = FALSE;
530
531 CONF_SC_TOGGLE_CLIST_VAR(clist);
532
533 if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
534 {
535 unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
536 unsigned int nxt = 0;
537 Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
538
539 switch (type)
540 {
541 case HTTPD_POLICY_CON_POLICY:
542 httpd_policy_change_con(con, ref->ptr);
543 break;
544
545 case HTTPD_POLICY_REQ_POLICY:
546 httpd_policy_change_req(req, ref->ptr);
547 break;
548
549 default:
550 vstr_ref_del(ref);
551 return (FALSE);
552 }
553
554 vstr_ref_del(ref);
555 if (nxt)
556 return (conf_parse_num_token(conf, token, nxt));
557 }
558
559 else if (OPT_SERV_SYM_EQ("<close>"))
560 {
561 evnt_close(con->evnt);
562 return (TRUE);
563 }
564 else if (OPT_SERV_SYM_EQ("connection-policy"))
565 {
566 const Httpd_policy_opts *policy = NULL;
567
568 policy = httpd__policy_build(con, conf, token, HTTPD_POLICY_CON_POLICY);
569 httpd_policy_change_con(con, policy);
570 }
571 else if (OPT_SERV_SYM_EQ("policy"))
572 {
573 const Httpd_policy_opts *policy = NULL;
574
575 policy = httpd__policy_build(con, conf, token, HTTPD_POLICY_REQ_POLICY);
576 httpd_policy_change_req(req, policy);
577 }
578 else if (OPT_SERV_SYM_EQ("org.and.jhttpd-conf-req-1.0"))
579 {
580 Httpd_opts *opts = (Httpd_opts *)con->policy->s->beg;
581 return (httpd_conf_req_d0(con, req, /* server beg time is "close engouh" */
582 opts->beg_time, conf, token));
583 }
584 else
585 return (FALSE);
586
587 return (TRUE);
588 }
589
httpd__policy_request_d0(struct Con * con,struct Httpd_req_data * req,Conf_parse * conf,Conf_token * token)590 static int httpd__policy_request_d0(struct Con *con, struct Httpd_req_data *req,
591 Conf_parse *conf, Conf_token *token)
592 {
593 unsigned int depth = token->depth_num;
594 int matches = TRUE;
595
596 CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
597 ++depth;
598 while (conf_token_list_num(token, depth))
599 {
600 CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
601
602 if (!httpd__policy_request_tst_d1(con, req, conf, token, &matches))
603 return (FALSE);
604
605 if (!matches)
606 return (TRUE);
607 }
608 --depth;
609
610 while (conf_token_list_num(token, depth))
611 {
612 CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
613
614 if (!httpd__policy_request_d1(con, req, conf, token))
615 return (FALSE);
616 if (con->evnt->flag_q_closed) /* don't do anything else */
617 return (TRUE);
618 }
619
620 return (TRUE);
621 }
622
httpd_policy_request(struct Con * con,struct Httpd_req_data * req,Conf_parse * conf,const Conf_token * beg_token)623 int httpd_policy_request(struct Con *con, struct Httpd_req_data *req,
624 Conf_parse *conf, const Conf_token *beg_token)
625 {
626 Conf_token token[1];
627 unsigned int num = 0;
628
629 if (!beg_token->num) /* not been parsed */
630 return (TRUE);
631
632 *token = *beg_token;
633
634 num = token->num;
635 while (num)
636 {
637 if (!conf_parse_num_token(conf, token, num))
638 goto conf_fail;
639
640 assert(token->type == (CONF_TOKEN_TYPE_USER_BEG+HTTPD_CONF_MAIN_MATCH_REQ));
641
642 conf_token_get_user_value(conf, token, &num);
643
644 if (!httpd__policy_request_d0(con, req, conf, token))
645 goto conf_fail;
646 }
647
648 vstr_del(conf->tmp, 1, conf->tmp->len);
649 return (TRUE);
650
651 conf_fail:
652 vstr_del(conf->tmp, 1, conf->tmp->len);
653 if (!req->user_return_error_code)
654 {
655 conf_parse_backtrace(conf->tmp, "<policy-request>", conf, token);
656 HTTPD_ERR(req, 503);
657 }
658 return (FALSE);
659 }
660
httpd__conf_main_policy_http_d1(Httpd_policy_opts * opts,const Conf_parse * conf,Conf_token * token)661 static int httpd__conf_main_policy_http_d1(Httpd_policy_opts *opts,
662 const Conf_parse *conf,
663 Conf_token *token)
664 {
665 int clist = FALSE;
666
667 CONF_SC_MAKE_CLIST_BEG(policy_http_d1, clist);
668
669 else if (OPT_SERV_SYM_EQ("authorization") || OPT_SERV_SYM_EQ("auth"))
670 { /* token is output of: echo -n foo:bar | openssl enc -base64 */
671 /* see it with: echo token | openssl enc -d -base64 && echo */
672 unsigned int depth = token->depth_num;
673
674 CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
675 if (!OPT_SERV_SYM_EQ("basic-encoded")) return (FALSE);
676 CONF_SC_MAKE_CLIST_MID(depth, clist);
677
678 else if (OPT_SERV_SYM_EQ("realm")) OPT_SERV_X_VSTR(opts->auth_realm);
679 else if (OPT_SERV_SYM_EQ("token")) OPT_SERV_X_VSTR(opts->auth_token);
680
681 CONF_SC_MAKE_CLIST_END();
682 }
683 else if (OPT_SERV_SYM_EQ("canonize-host"))
684 OPT_SERV_X_TOGGLE(opts->use_canonize_host);
685 else if (OPT_SERV_SYM_EQ("check-dot-directory") ||
686 OPT_SERV_SYM_EQ("chk-dot-dir") ||
687 OPT_SERV_SYM_EQ("chk-.-dir"))
688 OPT_SERV_X_TOGGLE(opts->chk_dot_dir);
689 else if (OPT_SERV_SYM_EQ("check-double-headr") ||
690 OPT_SERV_SYM_EQ("chk-dbl-hdr") ||
691 OPT_SERV_SYM_EQ("check-*2-hdr") ||
692 OPT_SERV_SYM_EQ("check-*2-header"))
693 OPT_SERV_X_TOGGLE(opts->use_x2_hdr_chk);
694 else if (OPT_SERV_SYM_EQ("check-encoded-slash") ||
695 OPT_SERV_SYM_EQ("chk-enc-/"))
696 OPT_SERV_X_TOGGLE(opts->chk_encoded_slash);
697 else if (OPT_SERV_SYM_EQ("check-encoded-dot") ||
698 OPT_SERV_SYM_EQ("chk-enc-."))
699 OPT_SERV_X_TOGGLE(opts->chk_encoded_dot);
700 else if (OPT_SERV_SYM_EQ("check-host") ||
701 OPT_SERV_SYM_EQ("chk-host"))
702 OPT_SERV_X_TOGGLE(opts->use_host_err_chk);
703 else if (OPT_SERV_SYM_EQ("error-406"))
704 OPT_SERV_X_TOGGLE(opts->use_err_406);
705 else if (OPT_SERV_SYM_EQ("error-host-400"))
706 OPT_SERV_X_TOGGLE(opts->use_host_err_400);
707 else if (OPT_SERV_SYM_EQ("encoded-content-replacement"))
708 OPT_SERV_X_TOGGLE(opts->use_enc_content_replacement);
709 else if (OPT_SERV_SYM_EQ("header-names-strict"))
710 OPT_SERV_X_TOGGLE(opts->use_non_spc_hdrs);
711 else if (OPT_SERV_SYM_EQ("keep-alive"))
712 OPT_SERV_X_TOGGLE(opts->use_keep_alive);
713 else if (OPT_SERV_SYM_EQ("keep-alive-1.0"))
714 OPT_SERV_X_TOGGLE(opts->use_keep_alive_1_0);
715 else if (OPT_SERV_SYM_EQ("range"))
716 OPT_SERV_X_TOGGLE(opts->use_range);
717 else if (OPT_SERV_SYM_EQ("range-1.0"))
718 OPT_SERV_X_TOGGLE(opts->use_range_1_0);
719 else if (OPT_SERV_SYM_EQ("trace-op") || OPT_SERV_SYM_EQ("trace-operation"))
720 OPT_SERV_X_TOGGLE(opts->use_trace_op);
721 else if (OPT_SERV_SYM_EQ("url-remove-fragment"))
722 OPT_SERV_X_TOGGLE(opts->remove_url_frag);
723 else if (OPT_SERV_SYM_EQ("url-remove-query"))
724 OPT_SERV_X_TOGGLE(opts->remove_url_query);
725
726 else if (OPT_SERV_SYM_EQ("limit"))
727 {
728 CONF_SC_MAKE_CLIST_BEG(limit, clist);
729
730 else if (OPT_SERV_SYM_EQ("header-size") ||
731 OPT_SERV_SYM_EQ("header-sz"))
732 OPT_SERV_X_UINT(opts->max_header_sz);
733 else if (OPT_SERV_SYM_EQ("requests"))
734 OPT_SERV_X_UINT(opts->max_requests);
735 else if (OPT_SERV_SYM_EQ("nodes"))
736 {
737 CONF_SC_MAKE_CLIST_BEG(nodes, clist);
738
739 else if (OPT_SERV_SYM_EQ("Accept:"))
740 OPT_SERV_X_UINT(opts->max_A_nodes);
741 else if (OPT_SERV_SYM_EQ("Accept-Charset:"))
742 OPT_SERV_X_UINT(opts->max_AC_nodes);
743 else if (OPT_SERV_SYM_EQ("Accept-Encoding:"))
744 OPT_SERV_X_UINT(opts->max_AE_nodes);
745 else if (OPT_SERV_SYM_EQ("Accept-Language:"))
746 OPT_SERV_X_UINT(opts->max_AL_nodes);
747
748 else if (OPT_SERV_SYM_EQ("Connection:"))
749 OPT_SERV_X_UINT(opts->max_etag_nodes);
750 else if (OPT_SERV_SYM_EQ("ETag:"))
751 OPT_SERV_X_UINT(opts->max_etag_nodes);
752 else if (OPT_SERV_SYM_EQ("Range:"))
753 OPT_SERV_X_UINT(opts->max_range_nodes);
754
755 CONF_SC_MAKE_CLIST_END();
756 }
757
758 CONF_SC_MAKE_CLIST_END();
759 }
760
761 CONF_SC_MAKE_CLIST_END();
762
763 return (TRUE);
764 }
765
httpd__conf_main_policy_d1(Httpd_policy_opts * opts,Conf_parse * conf,Conf_token * token,int clist)766 static int httpd__conf_main_policy_d1(Httpd_policy_opts *opts,
767 Conf_parse *conf, Conf_token *token,
768 int clist)
769 {
770 if (0) { }
771
772 else if (OPT_SERV_SYM_EQ("match-init"))
773 OPT_SERV_SC_MATCH_INIT(opts->s->beg,
774 httpd__conf_main_policy_d1(opts, conf, token,
775 clist));
776
777 else if (OPT_SERV_SYM_EQ("directory-filename"))
778 return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
779 opts->dir_filename));
780 else if (OPT_SERV_SYM_EQ("document-root") ||
781 OPT_SERV_SYM_EQ("doc-root"))
782 return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
783 opts->document_root));
784 else if (OPT_SERV_SYM_EQ("unspecified-hostname"))
785 OPT_SERV_X_VSTR(opts->default_hostname);
786 else if (OPT_SERV_SYM_EQ("MIME/types-default-type"))
787 OPT_SERV_X_VSTR(opts->mime_types_def_ct);
788 else if (OPT_SERV_SYM_EQ("MIME/types-filename-main"))
789 return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
790 opts->mime_types_main));
791 else if (OPT_SERV_SYM_EQ("MIME/types-filename-extra") ||
792 OPT_SERV_SYM_EQ("MIME/types-filename-xtra"))
793 return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
794 opts->mime_types_xtra));
795 else if (OPT_SERV_SYM_EQ("request-configuration-directory") ||
796 OPT_SERV_SYM_EQ("req-conf-dir"))
797 return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
798 opts->req_conf_dir));
799 else if (OPT_SERV_SYM_EQ("request-error-directory") ||
800 OPT_SERV_SYM_EQ("req-err-dir"))
801 return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
802 opts->req_err_dir));
803 else if (OPT_SERV_SYM_EQ("server-name"))
804 OPT_SERV_X_VSTR(opts->server_name);
805
806 else if (OPT_SERV_SYM_EQ("secure-directory-filename"))
807 OPT_SERV_X_TOGGLE(opts->use_secure_dirs);
808 else if (OPT_SERV_SYM_EQ("redirect-filename-directory"))
809 OPT_SERV_X_TOGGLE(opts->use_friendly_dirs);
810 else if (OPT_SERV_SYM_EQ("mmap"))
811 OPT_SERV_X_TOGGLE(opts->use_mmap);
812 else if (OPT_SERV_SYM_EQ("sendfile"))
813 OPT_SERV_X_TOGGLE(opts->use_sendfile);
814 else if (OPT_SERV_SYM_EQ("virtual-hosts") ||
815 OPT_SERV_SYM_EQ("vhosts") ||
816 OPT_SERV_SYM_EQ("virtual-hosts-name") ||
817 OPT_SERV_SYM_EQ("vhosts-name"))
818 OPT_SERV_X_TOGGLE(opts->use_vhosts_name);
819 else if (OPT_SERV_SYM_EQ("public-only"))
820 OPT_SERV_X_TOGGLE(opts->use_public_only);
821 else if (OPT_SERV_SYM_EQ("posix-fadvise"))
822 OPT_SERV_X_TOGGLE(opts->use_posix_fadvise);
823 else if (OPT_SERV_SYM_EQ("tcp-cork"))
824 OPT_SERV_X_TOGGLE(opts->use_tcp_cork);
825 else if (OPT_SERV_SYM_EQ("allow-request-configuration"))
826 OPT_SERV_X_TOGGLE(opts->use_req_conf);
827 else if (OPT_SERV_SYM_EQ("allow-header-splitting"))
828 OPT_SERV_X_TOGGLE(opts->allow_hdr_split);
829 else if (OPT_SERV_SYM_EQ("allow-header-NIL"))
830 OPT_SERV_X_TOGGLE(opts->allow_hdr_nil);
831 else if (OPT_SERV_SYM_EQ("unspecified-hostname-append-port"))
832 OPT_SERV_X_TOGGLE(opts->add_def_port);
833
834 else if (OPT_SERV_SYM_EQ("limit"))
835 {
836 CONF_SC_MAKE_CLIST_BEG(limit, clist);
837
838 else if (OPT_SERV_SYM_EQ("request-configuration-size") ||
839 OPT_SERV_SYM_EQ("request-configuration-sz") ||
840 OPT_SERV_SYM_EQ("req-conf-size") ||
841 OPT_SERV_SYM_EQ("req-conf-sz"))
842 OPT_SERV_X_UINT(opts->max_req_conf_sz);
843 else if (OPT_SERV_SYM_EQ("nodes"))
844 {
845 CONF_SC_MAKE_CLIST_BEG(nodes, clist);
846
847 else if (OPT_SERV_SYM_EQ("Accept:"))
848 OPT_SERV_X_UINT(opts->max_neg_A_nodes);
849 else if (OPT_SERV_SYM_EQ("Accept-Language:"))
850 OPT_SERV_X_UINT(opts->max_neg_AL_nodes);
851
852 CONF_SC_MAKE_CLIST_END();
853 }
854
855 CONF_SC_MAKE_CLIST_END();
856 }
857
858 else if (OPT_SERV_SYM_EQ("HTTP") || OPT_SERV_SYM_EQ("http"))
859 return (httpd__conf_main_policy_http_d1(opts, conf, token));
860
861 else
862 return (FALSE);
863
864 return (TRUE);
865 }
866
httpd__conf_main_policy(Httpd_opts * opts,Conf_parse * conf,Conf_token * token)867 static int httpd__conf_main_policy(Httpd_opts *opts,
868 Conf_parse *conf, Conf_token *token)
869 {
870 Opt_serv_policy_opts *popts = NULL;
871 unsigned int cur_depth = opt_policy_sc_conf_parse(opts->s, conf, token,
872 &popts);
873 int clist = FALSE;
874
875 if (!cur_depth)
876 return (FALSE);
877
878 CONF_SC_MAKE_CLIST_MID(cur_depth, clist);
879
880 else if (httpd__conf_main_policy_d1((Httpd_policy_opts *)popts, conf, token,
881 clist))
882 { }
883
884 CONF_SC_MAKE_CLIST_END();
885
886 return (TRUE);
887 }
888
httpd__conf_main_d1(Httpd_opts * httpd_opts,Conf_parse * conf,Conf_token * token,int clist)889 static int httpd__conf_main_d1(Httpd_opts *httpd_opts,
890 Conf_parse *conf, Conf_token *token, int clist)
891 {
892 if (OPT_SERV_SYM_EQ("org.and.daemon-conf-1.0"))
893 {
894 if (!opt_serv_conf(httpd_opts->s, conf, token))
895 return (FALSE);
896 }
897
898 else if (OPT_SERV_SYM_EQ("match-init"))
899 OPT_SERV_SC_MATCH_INIT(httpd_opts->s,
900 httpd__conf_main_d1(httpd_opts, conf, token, clist));
901
902 else if (OPT_SERV_SYM_EQ("policy"))
903 {
904 if (!httpd__conf_main_policy(httpd_opts, conf, token))
905 return (FALSE);
906 }
907
908 else if (OPT_SERV_SYM_EQ("match-connection"))
909 {
910 if (!conf_token_set_user_value(conf, token,
911 HTTPD_CONF_MAIN_MATCH_CON, NULL, 0))
912 return (FALSE);
913
914 if (!httpd_opts->match_connection->num)
915 *httpd_opts->match_connection = *token;
916 else /* already have one, add this to end... */
917 conf_token_set_user_value(conf, httpd_opts->tmp_match_connection,
918 HTTPD_CONF_MAIN_MATCH_CON, NULL, token->num);
919 *httpd_opts->tmp_match_connection = *token;
920
921 conf_parse_end_token(conf, token, token->depth_num);
922 }
923 else if (OPT_SERV_SYM_EQ("match-request"))
924 {
925 if (!conf_token_set_user_value(conf, token,
926 HTTPD_CONF_MAIN_MATCH_REQ, NULL, 0))
927 return (FALSE);
928
929 if (!httpd_opts->match_request->num)
930 *httpd_opts->match_request = *token;
931 else /* already have one, add this to end... */
932 conf_token_set_user_value(conf, httpd_opts->tmp_match_request,
933 HTTPD_CONF_MAIN_MATCH_REQ, NULL, token->num);
934 *httpd_opts->tmp_match_request = *token;
935
936 conf_parse_end_token(conf, token, token->depth_num);
937 }
938
939 else
940 return (FALSE);
941
942 return (TRUE);
943 }
944
httpd_conf_main(Httpd_opts * opts,Conf_parse * conf,Conf_token * token)945 int httpd_conf_main(Httpd_opts *opts, Conf_parse *conf, Conf_token *token)
946 {
947 unsigned int cur_depth = token->depth_num;
948 int clist = FALSE;
949
950 if (!OPT_SERV_SYM_EQ("org.and.jhttpd-conf-main-1.0"))
951 return (FALSE);
952
953 CONF_SC_MAKE_CLIST_MID(cur_depth, clist);
954
955 else if (httpd__conf_main_d1(opts, conf, token, clist))
956 { }
957
958 CONF_SC_MAKE_CLIST_END();
959
960 /* And they all live together ... dum dum */
961 if (conf->data->conf->malloc_bad)
962 return (FALSE);
963
964 return (TRUE);
965 }
966
967 #define HTTPD_CONF__BEG_APP() do { \
968 ASSERT(!opts->conf_num || (conf->state == CONF_PARSE_STATE_END)); \
969 prev_conf_num = conf->sects->num; \
970 /* reinit */ \
971 conf->state = CONF_PARSE_STATE_BEG; \
972 } while (FALSE)
973
974 /* restore the previous parsing we've done and skip parsing it again */
975 #define HTTPD_CONF__END_APP() do { \
976 if (opts->conf_num) \
977 { \
978 conf_parse_token(conf, token); \
979 conf_parse_num_token(conf, token, prev_conf_num); \
980 } \
981 } while (FALSE)
982
983
httpd_conf_main_parse_cstr(Vstr_base * out,Httpd_opts * opts,const char * data)984 int httpd_conf_main_parse_cstr(Vstr_base *out,
985 Httpd_opts *opts, const char *data)
986 {
987 Conf_parse *conf = opts->conf;
988 Conf_token token[1] = {CONF_TOKEN_INIT};
989 unsigned int prev_conf_num = 0;
990 size_t pos = 1;
991 size_t len = 0;
992
993 ASSERT(opts && data);
994
995 if (!conf && !(conf = conf_parse_make(NULL)))
996 goto conf_malloc_fail;
997
998 pos = conf->data->len + 1;
999 if (!vstr_add_cstr_ptr(conf->data, conf->data->len,
1000 "(org.and.jhttpd-conf-main-1.0 "))
1001 goto read_malloc_fail;
1002 if (!vstr_add_cstr_ptr(conf->data, conf->data->len, data))
1003 goto read_malloc_fail;
1004 if (!vstr_add_cstr_ptr(conf->data, conf->data->len,
1005 ")"))
1006 goto read_malloc_fail;
1007 len = vstr_sc_posdiff(pos, conf->data->len);
1008
1009 HTTPD_CONF__BEG_APP();
1010
1011 if (!conf_parse_lex(conf, pos, len))
1012 goto conf_fail;
1013
1014 HTTPD_CONF__END_APP();
1015
1016 if (!conf_parse_token(conf, token))
1017 goto conf_fail;
1018
1019 if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1))
1020 goto conf_fail;
1021
1022 if (!conf_parse_token(conf, token))
1023 goto conf_fail;
1024
1025 ASSERT(OPT_SERV_SYM_EQ("org.and.jhttpd-conf-main-1.0"));
1026
1027 if (!httpd_conf_main(opts, conf, token))
1028 goto conf_fail;
1029
1030 if (token->num != conf->sects->num)
1031 goto conf_fail;
1032
1033 opts->conf = conf;
1034 opts->conf_num++;
1035
1036 return (TRUE);
1037
1038 conf_fail:
1039 conf_parse_backtrace(out, data, conf, token);
1040 read_malloc_fail:
1041 conf_parse_free(conf);
1042 conf_malloc_fail:
1043 return (FALSE);
1044 }
1045
httpd_conf_main_parse_file(Vstr_base * out,Httpd_opts * opts,const char * fname)1046 int httpd_conf_main_parse_file(Vstr_base *out,
1047 Httpd_opts *opts, const char *fname)
1048 {
1049 Conf_parse *conf = opts->conf;
1050 Conf_token token[1] = {CONF_TOKEN_INIT};
1051 unsigned int prev_conf_num = 0;
1052 size_t pos = 1;
1053 size_t len = 0;
1054
1055 ASSERT(opts && fname);
1056
1057 if (!conf && !(conf = conf_parse_make(NULL)))
1058 goto conf_malloc_fail;
1059
1060 pos = conf->data->len + 1;
1061 if (!vstr_sc_read_len_file(conf->data, conf->data->len, fname, 0, 0, NULL))
1062 goto read_malloc_fail;
1063 len = vstr_sc_posdiff(pos, conf->data->len);
1064
1065 HTTPD_CONF__BEG_APP();
1066
1067 if (!conf_parse_lex(conf, pos, len))
1068 goto conf_fail;
1069
1070 HTTPD_CONF__END_APP();
1071
1072 while (conf_parse_token(conf, token))
1073 {
1074 if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1))
1075 goto conf_fail;
1076
1077 if (!conf_parse_token(conf, token))
1078 goto conf_fail;
1079
1080 if (OPT_SERV_SYM_EQ("org.and.daemon-conf-1.0"))
1081 {
1082 if (!opt_serv_conf(opts->s, conf, token))
1083 goto conf_fail;
1084 }
1085 else if (OPT_SERV_SYM_EQ("org.and.jhttpd-conf-main-1.0"))
1086 {
1087 if (!httpd_conf_main(opts, conf, token))
1088 goto conf_fail;
1089 }
1090 else
1091 goto conf_fail;
1092
1093 opts->conf_num++;
1094 }
1095
1096 opts->conf = conf;
1097
1098 return (TRUE);
1099
1100 conf_fail:
1101 conf_parse_backtrace(out, fname, conf, token);
1102 errno = 0;
1103 read_malloc_fail:
1104 if (errno && out) /* can't find config. file */
1105 vstr_add_fmt(out, out->len, "open(%s): %m", fname);
1106
1107 conf_parse_free(conf);
1108 conf_malloc_fail:
1109 return (FALSE);
1110 }
1111
httpd_conf_main_free(Httpd_opts * opts)1112 void httpd_conf_main_free(Httpd_opts *opts)
1113 {
1114 Opt_serv_policy_opts *scan = opts->s->def_policy;
1115
1116 while (scan)
1117 {
1118 Httpd_policy_opts *tmp = (Httpd_policy_opts *)scan;
1119 Opt_serv_policy_opts *scan_next = scan->next;
1120
1121 mime_types_exit(tmp->mime_types);
1122
1123 scan = scan_next;
1124 }
1125
1126 opt_policy_sc_all_ref_del(opts->s);
1127 conf_parse_free(opts->conf); opts->conf = NULL;
1128 date_free(opts->date); opts->date = NULL;
1129
1130 opt_serv_conf_free(opts->s);
1131 }
1132
httpd_conf_main_init(Httpd_opts * httpd_opts)1133 int httpd_conf_main_init(Httpd_opts *httpd_opts)
1134 {
1135 Httpd_policy_opts *opts = NULL;
1136
1137 if (!opt_serv_conf_init(httpd_opts->s))
1138 goto opts_init_fail;
1139
1140 opts = (Httpd_policy_opts *)httpd_opts->s->def_policy;
1141
1142 vstr_add_cstr_ptr(opts->server_name, 0, HTTPD_CONF_DEF_SERVER_NAME);
1143 vstr_add_cstr_ptr(opts->dir_filename, 0, HTTPD_CONF_DEF_DIR_FILENAME);
1144 vstr_add_cstr_ptr(opts->mime_types_def_ct, 0, HTTPD_CONF_MIME_TYPE_DEF_CT);
1145 vstr_add_cstr_ptr(opts->mime_types_main, 0, HTTPD_CONF_MIME_TYPE_MAIN);
1146 vstr_add_cstr_ptr(opts->mime_types_xtra, 0, HTTPD_CONF_MIME_TYPE_XTRA);
1147
1148 if (!(httpd_opts->date = date_make()))
1149 goto httpd_init_fail;
1150
1151 if (opts->s->policy_name->conf->malloc_bad)
1152 goto httpd_init_fail;
1153
1154 return (TRUE);
1155
1156 httpd_init_fail:
1157 httpd_conf_main_free(httpd_opts);
1158 opts_init_fail:
1159 return (FALSE);
1160 }
1161