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