1 :
2 : #include "httpd.h"
3 : #include "httpd_policy.h"
4 :
5 : #define EX_UTILS_NO_FUNCS 1
6 : #include "ex_utils.h"
7 :
8 : #include "mk.h"
9 :
10 : #include "match_con.h"
11 :
12 : #include "base64.h"
13 :
14 : static int httpd__conf_main_policy_http_d1(Httpd_policy_opts *opts,
15 : Conf_parse *conf,
16 : Conf_token *token)
17 98 : {
18 98 : int clist = FALSE;
19 :
20 348 : CONF_SC_MAKE_CLIST_BEG(policy_http_d1, clist);
21 :
22 158 : else if (OPT_SERV_SYM_EQ("authorization") || OPT_SERV_SYM_EQ("auth"))
23 : {
24 12 : unsigned int depth = token->depth_num;
25 :
26 12 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
27 :
28 : if (0) { }
29 :
30 12 : else if (OPT_SERV_SYM_EQ("off"))
31 : {
32 4 : vstr_del(opts->auth_realm, 1, opts->auth_realm->len);
33 4 : vstr_del(opts->auth_token, 1, opts->auth_token->len);
34 : }
35 8 : else if (OPT_SERV_SYM_EQ("basic-encoded"))
36 : { /* echo -n foo:bar | base64
37 : echo -n Zm9vOmJhcg== | base64 -d && echo */
38 18 : CONF_SC_MAKE_CLIST_MID(depth, clist);
39 :
40 8 : else if (OPT_SERV_SYM_EQ("realm"))
41 4 : OPT_SERV_X_VSTR(opts->s->beg, opts->auth_realm);
42 4 : else if (OPT_SERV_SYM_EQ("token"))
43 4 : OPT_SERV_X_VSTR(opts->s->beg, opts->auth_token);
44 :
45 0 : CONF_SC_MAKE_CLIST_END();
46 : }
47 4 : else if (OPT_SERV_SYM_EQ("basic-single"))
48 : {
49 18 : CONF_SC_MAKE_CLIST_MID(depth, clist);
50 :
51 8 : else if (OPT_SERV_SYM_EQ("realm"))
52 4 : OPT_SERV_X_VSTR(opts->s->beg, opts->auth_realm);
53 4 : else if (OPT_SERV_SYM_EQ("token"))
54 4 : OPT_SERV_X_SINGLE_VSTR(conf->tmp);
55 :
56 0 : CONF_SC_MAKE_CLIST_END();
57 :
58 4 : vstr_del(opts->auth_token, 1, opts->auth_token->len);
59 4 : if (!vstr_x_conv_base64_encode(opts->auth_token, 0,
60 : conf->tmp, 1, conf->tmp->len, 0))
61 0 : return (FALSE);
62 : }
63 : else
64 0 : return (FALSE);
65 : }
66 140 : else if (OPT_SERV_SYM_EQ("strictness"))
67 : {
68 86 : CONF_SC_MAKE_CLIST_BEG(http_checks, clist);
69 :
70 47 : else if (OPT_SERV_SYM_EQ("hdrs") || OPT_SERV_SYM_EQ("headers"))
71 : {
72 30 : CONF_SC_MAKE_CLIST_BEG(checks_hdrs, clist);
73 :
74 10 : else if (OPT_SERV_SYM_EQ("allow-dbl") ||
75 : OPT_SERV_SYM_EQ("allow-double") ||
76 : OPT_SERV_SYM_EQ("allow-*2"))
77 0 : OPT_SERV_X_NEG_TOGGLE(opts->use_hdrs_no_x2);
78 10 : else if (OPT_SERV_SYM_EQ("allow-missing-length"))
79 0 : OPT_SERV_X_NEG_TOGGLE(opts->use_hdrs_err_411);
80 10 : else if (OPT_SERV_SYM_EQ("allow-spaces"))
81 10 : OPT_SERV_X_NEG_TOGGLE(opts->use_hdrs_non_spc);
82 :
83 0 : CONF_SC_MAKE_CLIST_END();
84 : }
85 :
86 38 : else if (OPT_SERV_SYM_EQ("host") || OPT_SERV_SYM_EQ("hostname"))
87 : {
88 40 : CONF_SC_MAKE_CLIST_BEG(checks_host, clist);
89 :
90 20 : else if (OPT_SERV_SYM_EQ("canonize") ||
91 : OPT_SERV_SYM_EQ("make-canonical"))
92 4 : OPT_SERV_X_TOGGLE(opts->use_canonize_host);
93 12 : else if (OPT_SERV_SYM_EQ("validation"))
94 : {
95 12 : int use_internal_host_chk = FALSE;
96 12 : int use_host_chk = FALSE;
97 12 : int use_host_err_400 = FALSE;
98 12 : int validation_done = FALSE;
99 :
100 40 : CONF_SC_MAKE_CLIST_BEG(checks_host_valid, clist);
101 :
102 20 : else if (OPT_SERV_SYM_EQ("off") || OPT_SERV_SYM_EQ("false") ||
103 : OPT_SERV_SYM_EQ("OFF") || OPT_SERV_SYM_EQ("FALSE") ||
104 : OPT_SERV_SYM_EQ("no") || OPT_SERV_SYM_EQ("NO") ||
105 : OPT_SERV_SYM_EQ("none") || OPT_SERV_SYM_EQ("NONE") ||
106 : OPT_SERV_SYM_EQ("0"))
107 : {
108 4 : use_internal_host_chk = FALSE;
109 4 : use_host_chk = FALSE;
110 4 : use_host_err_400 = FALSE;
111 4 : validation_done = TRUE;
112 : }
113 16 : else if (OPT_SERV_SYM_EQ("fast") || OPT_SERV_SYM_EQ("internal"))
114 : {
115 4 : use_internal_host_chk = TRUE;
116 4 : validation_done = TRUE;
117 : }
118 8 : else if (OPT_SERV_SYM_EQ("virtual-hosts-default"))
119 : {
120 4 : use_host_chk = TRUE;
121 4 : use_host_err_400 = FALSE;
122 4 : validation_done = TRUE;
123 : }
124 4 : else if (OPT_SERV_SYM_EQ("virtual-hosts-error"))
125 : {
126 4 : use_host_chk = TRUE;
127 4 : use_host_err_400 = TRUE;
128 4 : validation_done = TRUE;
129 : }
130 :
131 0 : CONF_SC_MAKE_CLIST_END();
132 :
133 12 : if (validation_done)
134 : {
135 12 : opts->use_internal_host_chk = use_internal_host_chk;
136 12 : opts->use_host_chk = use_host_chk;
137 12 : opts->use_host_err_400 = use_host_err_400;
138 : }
139 : }
140 :
141 0 : CONF_SC_MAKE_CLIST_END();
142 : }
143 :
144 20 : else if (OPT_SERV_SYM_EQ("allow-HTTP/0.9"))
145 0 : OPT_SERV_X_TOGGLE(opts->allow_http_0_9);
146 24 : else if (OPT_SERV_SYM_EQ("allow-dot-directory") ||
147 : OPT_SERV_SYM_EQ("allow-dot-dir") ||
148 : OPT_SERV_SYM_EQ("allow-.-dir"))
149 4 : OPT_SERV_X_NEG_TOGGLE(opts->chk_dot_dir);
150 20 : else if (OPT_SERV_SYM_EQ("allow-encoded-slash") ||
151 : OPT_SERV_SYM_EQ("allow-enc-/"))
152 4 : OPT_SERV_X_NEG_TOGGLE(opts->chk_encoded_slash);
153 16 : else if (OPT_SERV_SYM_EQ("allow-encoded-dot") ||
154 : OPT_SERV_SYM_EQ("allow-enc-."))
155 4 : OPT_SERV_X_NEG_TOGGLE(opts->chk_encoded_dot);
156 12 : else if (OPT_SERV_SYM_EQ("error-406") ||
157 : OPT_SERV_SYM_EQ("error-not-acceptable") ||
158 : OPT_SERV_SYM_EQ("error-406-not-acceptable"))
159 4 : OPT_SERV_X_TOGGLE(opts->use_err_406);
160 6 : else if (OPT_SERV_SYM_EQ("url") || OPT_SERV_SYM_EQ("URL"))
161 : {
162 16 : CONF_SC_MAKE_CLIST_BEG(checks_host, clist);
163 :
164 8 : else if (OPT_SERV_SYM_EQ("remove-fragment"))
165 4 : OPT_SERV_X_TOGGLE(opts->remove_url_frag);
166 4 : else if (OPT_SERV_SYM_EQ("remove-query"))
167 4 : OPT_SERV_X_TOGGLE(opts->remove_url_query);
168 :
169 0 : CONF_SC_MAKE_CLIST_END();
170 : }
171 :
172 0 : CONF_SC_MAKE_CLIST_END(); /* end of http checks */
173 : }
174 :
175 118 : else if (OPT_SERV_SYM_EQ("text-plain-redirect"))
176 4 : OPT_SERV_X_TOGGLE(opts->use_text_redirect);
177 114 : else if (OPT_SERV_SYM_EQ("ETag:"))
178 : {
179 44 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
180 :
181 : if (0) { }
182 :
183 44 : else if (OPT_SERV_SYM_EQ("auto-dev-inode-size-mtime"))
184 0 : opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_DISM;
185 44 : else if (OPT_SERV_SYM_EQ("auto-inode-size-mtime"))
186 0 : opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_ISM;
187 44 : else if (OPT_SERV_SYM_EQ("auto-size-mtime"))
188 4 : opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_SM;
189 80 : else if (OPT_SERV_SYM_EQ("auto-off") || OPT_SERV_SYM_EQ("auto-false") ||
190 : OPT_SERV_SYM_EQ("auto-no") || OPT_SERV_SYM_EQ("auto-none"))
191 40 : opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_NONE;
192 :
193 : else
194 0 : return (FALSE);
195 : }
196 70 : else if (OPT_SERV_SYM_EQ("encoded-content-replacement")) /* allow gzip */
197 4 : OPT_SERV_X_TOGGLE(opts->use_enc_content_replacement);
198 66 : else if (OPT_SERV_SYM_EQ("keep-alive"))
199 4 : OPT_SERV_X_TOGGLE(opts->use_keep_alive);
200 62 : else if (OPT_SERV_SYM_EQ("keep-alive-1.0"))
201 0 : OPT_SERV_X_TOGGLE(opts->use_keep_alive_1_0);
202 66 : else if (OPT_SERV_SYM_EQ("keep-alive-hdr") ||
203 : OPT_SERV_SYM_EQ("keep-alive-header"))
204 4 : OPT_SERV_X_TOGGLE(opts->output_keep_alive_hdr);
205 58 : else if (OPT_SERV_SYM_EQ("range"))
206 4 : OPT_SERV_X_TOGGLE(opts->use_range);
207 54 : else if (OPT_SERV_SYM_EQ("range-1.0"))
208 0 : OPT_SERV_X_TOGGLE(opts->use_range_1_0);
209 54 : else if (OPT_SERV_SYM_EQ("advertise-range"))
210 4 : OPT_SERV_X_TOGGLE(opts->use_adv_range);
211 54 : else if (OPT_SERV_SYM_EQ("trace-op") || OPT_SERV_SYM_EQ("trace-operation"))
212 4 : OPT_SERV_X_TOGGLE(opts->allow_trace_op);
213 46 : else if (OPT_SERV_SYM_EQ("url-remove-fragment")) /* compat */
214 0 : OPT_SERV_X_TOGGLE(opts->remove_url_frag);
215 46 : else if (OPT_SERV_SYM_EQ("url-remove-query")) /* compat */
216 0 : OPT_SERV_X_TOGGLE(opts->remove_url_query);
217 :
218 46 : else if (OPT_SERV_SYM_EQ("limit"))
219 : {
220 52 : CONF_SC_MAKE_CLIST_BEG(limit, clist);
221 :
222 24 : else if (OPT_SERV_SYM_EQ("header-size") ||
223 : OPT_SERV_SYM_EQ("header-sz"))
224 4 : OPT_SERV_X_UINT(opts->max_header_sz);
225 16 : else if (OPT_SERV_SYM_EQ("requests"))
226 4 : OPT_SERV_X_UINT(opts->max_requests);
227 12 : else if (OPT_SERV_SYM_EQ("nodes"))
228 : {
229 60 : CONF_SC_MAKE_CLIST_BEG(nodes, clist);
230 :
231 36 : else if (OPT_SERV_SYM_EQ("Accept:"))
232 4 : OPT_SERV_X_UINT(opts->max_A_nodes);
233 32 : else if (OPT_SERV_SYM_EQ("Accept-Charset:"))
234 4 : OPT_SERV_X_UINT(opts->max_AC_nodes);
235 28 : else if (OPT_SERV_SYM_EQ("Accept-Encoding:"))
236 4 : OPT_SERV_X_UINT(opts->max_AE_nodes);
237 24 : else if (OPT_SERV_SYM_EQ("Accept-Language:"))
238 4 : OPT_SERV_X_UINT(opts->max_AL_nodes);
239 :
240 20 : else if (OPT_SERV_SYM_EQ("Connection:"))
241 4 : OPT_SERV_X_UINT(opts->max_connection_nodes);
242 16 : else if (OPT_SERV_SYM_EQ("ETag:"))
243 4 : OPT_SERV_X_UINT(opts->max_etag_nodes);
244 12 : else if (OPT_SERV_SYM_EQ("Range:"))
245 : {
246 12 : OPT_SERV_X_UINT(opts->max_range_nodes);
247 12 : if (!opts->max_range_nodes)
248 : {
249 4 : opts->use_range = FALSE;
250 4 : opts->use_range_1_0 = FALSE;
251 : }
252 : }
253 :
254 0 : CONF_SC_MAKE_CLIST_END();
255 : }
256 :
257 0 : CONF_SC_MAKE_CLIST_END();
258 : }
259 42 : else if (OPT_SERV_SYM_EQ("Server:") || OPT_SERV_SYM_EQ("server-name"))
260 30 : OPT_SERV_X_VSTR(opts->s->beg, opts->server_name);
261 :
262 0 : CONF_SC_MAKE_CLIST_END();
263 :
264 98 : return (TRUE);
265 : }
266 :
267 : static int httpd__conf_main_policy_d1(Httpd_policy_opts *opts,
268 : Conf_parse *conf, Conf_token *token,
269 : int clist)
270 560 : {
271 : if (0) { }
272 :
273 560 : else if (OPT_SERV_SYM_EQ("match-init"))
274 12 : OPT_SERV_SC_MATCH_INIT(opts->s->beg,
275 : httpd__conf_main_policy_d1(opts, conf, token,
276 : clist));
277 :
278 548 : else if (OPT_SERV_SYM_EQ("directory-filename"))
279 8 : return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
280 : opts->dir_filename));
281 540 : else if (OPT_SERV_SYM_EQ("document-root") ||
282 : OPT_SERV_SYM_EQ("doc-root"))
283 48 : return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
284 : opts->document_root));
285 492 : else if (OPT_SERV_SYM_EQ("unspecified-hostname"))
286 48 : OPT_SERV_X_VSTR(opts->s->beg, opts->default_hostname);
287 444 : else if (OPT_SERV_SYM_EQ("MIME/types-default-type"))
288 6 : OPT_SERV_X_VSTR(opts->s->beg, opts->mime_types_def_ct);
289 438 : else if (OPT_SERV_SYM_EQ("MIME/types-filename-main"))
290 4 : return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
291 : opts->mime_types_main));
292 434 : else if (OPT_SERV_SYM_EQ("MIME/types-filename-extra") ||
293 : OPT_SERV_SYM_EQ("MIME/types-filename-xtra"))
294 52 : return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
295 : opts->mime_types_xtra));
296 382 : else if (OPT_SERV_SYM_EQ("request-configuration-directory") ||
297 : OPT_SERV_SYM_EQ("req-conf-dir"))
298 52 : return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
299 : opts->req_conf_dir));
300 330 : else if (OPT_SERV_SYM_EQ("request-error-directory") ||
301 : OPT_SERV_SYM_EQ("req-err-dir"))
302 52 : return (opt_serv_sc_make_static_path(opts->s->beg, conf, token,
303 : opts->req_err_dir));
304 278 : else if (OPT_SERV_SYM_EQ("server-name")) /* compat. */
305 4 : OPT_SERV_X_VSTR(opts->s->beg, opts->server_name);
306 :
307 274 : else if (OPT_SERV_SYM_EQ("secure-directory-filename"))
308 28 : OPT_SERV_X_TOGGLE(opts->use_secure_dirs);
309 246 : else if (OPT_SERV_SYM_EQ("redirect-filename-directory"))
310 0 : OPT_SERV_X_TOGGLE(opts->use_friendly_dirs);
311 246 : else if (OPT_SERV_SYM_EQ("mmap"))
312 12 : OPT_SERV_X_TOGGLE(opts->use_mmap);
313 234 : else if (OPT_SERV_SYM_EQ("sendfile"))
314 12 : OPT_SERV_X_TOGGLE(opts->use_sendfile);
315 270 : else if (OPT_SERV_SYM_EQ("virtual-hosts") ||
316 : OPT_SERV_SYM_EQ("vhosts") ||
317 : OPT_SERV_SYM_EQ("virtual-hosts-name") ||
318 : OPT_SERV_SYM_EQ("vhosts-name"))
319 48 : OPT_SERV_X_TOGGLE(opts->use_vhosts_name);
320 174 : else if (OPT_SERV_SYM_EQ("public-only"))
321 4 : OPT_SERV_X_TOGGLE(opts->use_public_only);
322 170 : else if (OPT_SERV_SYM_EQ("posix-fadvise"))
323 0 : OPT_SERV_X_TOGGLE(opts->use_posix_fadvise);
324 170 : else if (OPT_SERV_SYM_EQ("update-atime"))
325 0 : OPT_SERV_X_NEG_TOGGLE(opts->use_noatime);
326 170 : else if (OPT_SERV_SYM_EQ("tcp-cork"))
327 4 : OPT_SERV_X_TOGGLE(opts->use_tcp_cork);
328 166 : else if (OPT_SERV_SYM_EQ("allow-request-configuration"))
329 0 : OPT_SERV_X_TOGGLE(opts->use_req_conf);
330 166 : else if (OPT_SERV_SYM_EQ("allow-header-splitting"))
331 0 : OPT_SERV_X_TOGGLE(opts->allow_hdr_split);
332 166 : else if (OPT_SERV_SYM_EQ("allow-header-NIL"))
333 0 : OPT_SERV_X_TOGGLE(opts->allow_hdr_nil);
334 166 : else if (OPT_SERV_SYM_EQ("unspecified-hostname-append-port"))
335 64 : OPT_SERV_X_TOGGLE(opts->add_def_port);
336 :
337 102 : else if (OPT_SERV_SYM_EQ("limit"))
338 : {
339 16 : CONF_SC_MAKE_CLIST_BEG(limit, clist);
340 :
341 12 : else if (OPT_SERV_SYM_EQ("request-configuration-size") ||
342 : OPT_SERV_SYM_EQ("request-configuration-sz") ||
343 : OPT_SERV_SYM_EQ("req-conf-size") ||
344 : OPT_SERV_SYM_EQ("req-conf-sz"))
345 4 : OPT_SERV_X_UINT(opts->max_req_conf_sz);
346 4 : else if (OPT_SERV_SYM_EQ("nodes"))
347 : { /* this limts how much you can have in the configs., not over HTTP */
348 16 : CONF_SC_MAKE_CLIST_BEG(nodes, clist);
349 :
350 8 : else if (OPT_SERV_SYM_EQ("Accept:"))
351 4 : OPT_SERV_X_UINT(opts->max_neg_A_nodes);
352 4 : else if (OPT_SERV_SYM_EQ("Accept-Language:"))
353 4 : OPT_SERV_X_UINT(opts->max_neg_AL_nodes);
354 :
355 0 : CONF_SC_MAKE_CLIST_END();
356 : }
357 :
358 0 : CONF_SC_MAKE_CLIST_END();
359 : }
360 :
361 98 : else if (OPT_SERV_SYM_EQ("HTTP") || OPT_SERV_SYM_EQ("http"))
362 98 : return (httpd__conf_main_policy_http_d1(opts, conf, token));
363 :
364 : else
365 0 : return (FALSE);
366 :
367 246 : return (TRUE);
368 : }
369 :
370 : static int httpd__conf_main_policy(Httpd_opts *opts,
371 : Conf_parse *conf, Conf_token *token)
372 134 : {
373 134 : Opt_serv_policy_opts *popts = NULL;
374 134 : Conf_token *ntoken = NULL;
375 : unsigned int cur_depth = opt_policy_sc_conf_parse(opts->s, conf, token,
376 134 : &popts, &ntoken);
377 :
378 134 : if (!cur_depth)
379 0 : return (FALSE);
380 :
381 : do
382 : {
383 134 : int clist = FALSE;
384 :
385 822 : CONF_SC_MAKE_CLIST_MID(cur_depth, clist);
386 :
387 554 : else if (httpd__conf_main_policy_d1((Httpd_policy_opts *)popts, conf, token,
388 : clist))
389 : { }
390 :
391 0 : CONF_SC_MAKE_CLIST_END();
392 : } while (ntoken &&
393 : (cur_depth = opt_policy_sc_conf_parse(opts->s, conf, token,
394 134 : &popts, &ntoken)));
395 134 : return (TRUE);
396 : }
397 :
398 : typedef struct Httpd__match_uval
399 : {
400 : Conf_token opt_nxt; /* token first, so we can just use it as that */
401 : void (*s_cb_func)(Vstr_ref *);
402 : Vstr_base *name;
403 : } Httpd__match_uval;
404 :
405 : static int httpd__match_ref_del_eq(Vstr_base *s1, Vstr_ref *ref)
406 92 : {
407 92 : int eq = FALSE;
408 :
409 92 : if (ref)
410 : {
411 92 : Httpd__match_uval *uval = ref->ptr;
412 92 : if (uval->name)
413 20 : eq = vstr_cmp_eq(uval->name, 1, uval->name->len, s1, 1, s1->len);
414 : }
415 :
416 92 : if (eq)
417 12 : vstr_ref_del(ref);
418 :
419 92 : return (eq);
420 : }
421 :
422 : static int httpd__match_find(Conf_parse *conf, Conf_token **token)
423 4 : {
424 4 : Vstr_ref *ref = NULL;
425 4 : unsigned int num = 0;
426 :
427 4 : if (!httpd__match_iter_beg(conf, *token, &ref, &num))
428 0 : return (FALSE);
429 :
430 : do
431 : {
432 44 : if (httpd__match_ref_del_eq(conf->tmp, ref))
433 4 : return (TRUE);
434 40 : } while (httpd__match_iter_nxt(conf, *token, &ref, &num));
435 :
436 0 : return (FALSE);
437 : }
438 :
439 : static int httpd__match_find_before(Conf_parse *conf, Conf_token **token)
440 8 : {
441 8 : Vstr_ref *ref = NULL;
442 8 : unsigned int num = 0;
443 : Conf_token prev[1];
444 :
445 8 : if (!httpd__match_iter_beg(conf, *token, &ref, &num))
446 0 : return (FALSE);
447 :
448 8 : if (httpd__match_ref_del_eq(conf->tmp, ref))
449 : {
450 4 : *token = NULL;
451 4 : return (TRUE);
452 : }
453 :
454 4 : *prev = **token;
455 44 : while (httpd__match_iter_nxt(conf, *token, &ref, &num))
456 : {
457 40 : if (httpd__match_ref_del_eq(conf->tmp, ref))
458 : {
459 4 : **token = *prev;
460 4 : return (TRUE);
461 : }
462 :
463 36 : *prev = **token;
464 : }
465 :
466 0 : return (FALSE);
467 : }
468 :
469 : static void httpd__match_ref_cb(Vstr_ref *ref)
470 350 : {
471 350 : Httpd__match_uval *uval = ref->ptr;
472 :
473 350 : vstr_free_base(uval->name);
474 :
475 350 : (*uval->s_cb_func)(ref);
476 350 : }
477 :
478 : static int httpd__match_make(Conf_parse *conf, Conf_token *token,
479 : unsigned int type,
480 : Conf_token *beg, Conf_token *end)
481 348 : {
482 348 : unsigned int outer_depth = token->depth_num;
483 348 : int ret = FALSE;
484 348 : Vstr_ref *ref = NULL;
485 348 : Conf_token token_srch_tmp = CONF_TOKEN_INIT;
486 348 : Conf_token save = CONF_TOKEN_INIT;
487 348 : Conf_token *add_beg = end;
488 348 : Httpd__match_uval *uval = NULL;
489 348 : int auto_reclaim_ref = FALSE;
490 :
491 174 : ASSERT(beg && end && (!beg->num == !end->num));
492 :
493 348 : if (!conf_token_set_user_value(conf, token, type, NULL, 0))
494 0 : return (FALSE);
495 :
496 348 : if (!(ref = vstr_ref_make_malloc(sizeof(Httpd__match_uval))))
497 0 : return (FALSE);
498 348 : uval = ref->ptr;
499 :
500 348 : uval->name = NULL;
501 348 : uval->s_cb_func = ref->func;
502 348 : ref->func = httpd__match_ref_cb;
503 348 : uval->opt_nxt = save = *token;
504 :
505 348 : ret = conf_token_set_user_value(conf, &save, type, ref, 0);
506 174 : ASSERT(ret);
507 :
508 348 : vstr_ref_del(ref); /* going to use uval/ref later, but that's OK */
509 :
510 348 : CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE);
511 348 : if (token->type != CONF_TOKEN_TYPE_SLIST)
512 : {
513 204 : int clist_name = FALSE;
514 204 : int clist_xtra = FALSE;
515 204 : unsigned int inner_depth = 0;
516 204 : const Vstr_sect_node *pv = NULL;
517 :
518 204 : CONF_SC_TOGGLE_CLIST_VAR(clist_name);
519 :
520 204 : if (token->type == CONF_TOKEN_TYPE_CLIST)
521 8 : goto skip_name;
522 :
523 196 : if (!(pv = conf_token_value(token)))
524 0 : return (FALSE);
525 :
526 196 : if (!(uval->name = vstr_make_base(conf->tmp->conf)))
527 0 : return (FALSE);
528 :
529 196 : if (!vstr_add_vstr(uval->name, 0,
530 : conf->data, pv->pos, pv->len, VSTR_TYPE_ADD_BUF_REF))
531 0 : return (FALSE);
532 :
533 204 : skip_name:
534 204 : inner_depth = token->depth_num;
535 436 : CONF_SC_MAKE_CLIST_MID(inner_depth, clist_xtra);
536 :
537 204 : else if (token->type == CONF_TOKEN_TYPE_SLIST)
538 176 : goto skip_position;
539 30 : else if (OPT_SERV_SYM_EQ("after") && beg->num)
540 : {
541 4 : OPT_SERV_X_SINGLE_VSTR(conf->tmp);
542 4 : token_srch_tmp = *beg;
543 4 : add_beg = &token_srch_tmp;
544 4 : if (!httpd__match_find(conf, &add_beg))
545 0 : return (FALSE);
546 : }
547 28 : else if (OPT_SERV_SYM_EQ("before") && beg->num)
548 : {
549 8 : OPT_SERV_X_SINGLE_VSTR(conf->tmp);
550 8 : token_srch_tmp = *beg;
551 8 : add_beg = &token_srch_tmp;
552 8 : if (!httpd__match_find_before(conf, &add_beg))
553 0 : return (FALSE);
554 : }
555 16 : else if (OPT_SERV_SYM_EQ("end"))
556 8 : add_beg = end;
557 16 : else if (OPT_SERV_SYM_EQ("beg") || OPT_SERV_SYM_EQ("beginning"))
558 8 : add_beg = NULL;
559 0 : else if (OPT_SERV_SYM_EQ("<reclaim-memory>"))
560 0 : OPT_SERV_X_TOGGLE(auto_reclaim_ref);
561 :
562 0 : CONF_SC_MAKE_CLIST_END();
563 :
564 28 : CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(conf, token, outer_depth, FALSE);
565 : }
566 348 : skip_position:
567 348 : if ((token->type != CONF_TOKEN_TYPE_SLIST) ||
568 : (conf_token_at_depth(token) != outer_depth))
569 0 : return (FALSE);
570 :
571 174 : ASSERT(ref);
572 :
573 348 : if (auto_reclaim_ref && !uval->name)
574 0 : ref = NULL;
575 :
576 348 : if (!beg->num)
577 : {
578 42 : ret = conf_token_set_user_value(conf, &save, type, ref, 0);
579 21 : ASSERT(ret);
580 42 : *beg = save;
581 42 : *end = save;
582 : }
583 306 : else if (!add_beg) /* put before beg */
584 : {
585 12 : ret = conf_token_set_user_value(conf, &save, type, ref, beg->num);
586 6 : ASSERT(ret);
587 12 : *beg = save;
588 : }
589 : else
590 : {
591 294 : Vstr_ref *oref = NULL;
592 294 : unsigned int nxt = 0;
593 :
594 147 : ASSERT(add_beg && ((add_beg->type - CONF_TOKEN_TYPE_USER_BEG) == type));
595 147 : ASSERT(add_beg->num != 0);
596 :
597 294 : oref = conf_token_get_user_value(conf, add_beg, &nxt);
598 147 : ASSERT(oref);
599 :
600 294 : ret = conf_token_set_user_value(conf, &save, type, ref, nxt);
601 147 : ASSERT(ret);
602 294 : ret = conf_token_set_user_value(conf, add_beg, type, oref, save.num);
603 147 : ASSERT(ret);
604 :
605 294 : if (!nxt) /* put after end */
606 : {
607 143 : ASSERT(add_beg->num == end->num);
608 286 : *end = save;
609 : }
610 :
611 294 : vstr_ref_del(oref);
612 : }
613 :
614 348 : return (TRUE);
615 : }
616 :
617 : static int httpd__conf_main_d1(Httpd_opts *httpd_opts,
618 : Conf_parse *conf, Conf_token *token, int clist)
619 586 : {
620 586 : if (OPT_SERV_SYM_EQ("org.and.daemon-conf-1.0"))
621 : {
622 60 : if (!opt_serv_conf(httpd_opts->s, conf, token))
623 0 : return (FALSE);
624 : }
625 :
626 526 : else if (OPT_SERV_SYM_EQ("match-init"))
627 40 : OPT_SERV_SC_MATCH_INIT(httpd_opts->s,
628 : httpd__conf_main_d1(httpd_opts, conf, token, clist));
629 :
630 486 : else if (OPT_SERV_SYM_EQ("policy"))
631 : {
632 134 : if (!httpd__conf_main_policy(httpd_opts, conf, token))
633 0 : return (FALSE);
634 : }
635 :
636 352 : else if (OPT_SERV_SYM_EQ("match-connection"))
637 : {
638 96 : if (!httpd__match_make(conf, token, HTTPD_CONF_MAIN_MATCH_CON,
639 : httpd_opts->match_connection,
640 : httpd_opts->tmp_match_connection))
641 0 : return (FALSE);
642 :
643 96 : if (!conf_parse_end_token(conf, token, conf_token_at_depth(token)))
644 0 : return (FALSE);
645 : }
646 256 : else if (OPT_SERV_SYM_EQ("match-request"))
647 : {
648 168 : if (!httpd__match_make(conf, token, HTTPD_CONF_MAIN_MATCH_REQ,
649 : httpd_opts->match_request,
650 : httpd_opts->tmp_match_request))
651 0 : return (FALSE);
652 :
653 168 : if (!conf_parse_end_token(conf, token, conf_token_at_depth(token)))
654 0 : return (FALSE);
655 : }
656 88 : else if (OPT_SERV_SYM_EQ("match-error-response"))
657 : {
658 84 : if (!httpd__match_make(conf, token, HTTPD_CONF_MAIN_MATCH_RESP,
659 : httpd_opts->match_response,
660 : httpd_opts->tmp_match_response))
661 0 : return (FALSE);
662 :
663 84 : if (!conf_parse_end_token(conf, token, conf_token_at_depth(token)))
664 0 : return (FALSE);
665 : }
666 :
667 : else
668 4 : return (FALSE);
669 :
670 582 : return (TRUE);
671 : }
672 :
673 : int httpd_conf_main(Httpd_opts *opts, Conf_parse *conf, Conf_token *token)
674 182 : {
675 182 : unsigned int cur_depth = token->depth_num;
676 182 : int clist = FALSE;
677 :
678 182 : if (!OPT_SERV_SYM_EQ("org.and.httpd-conf-main-1.0") &&
679 : !OPT_SERV_SYM_EQ("org.and.jhttpd-conf-main-1.0"))
680 0 : return (FALSE);
681 :
682 896 : CONF_SC_MAKE_CLIST_MID(cur_depth, clist);
683 :
684 418 : else if (httpd__conf_main_d1(opts, conf, token, clist))
685 : { }
686 :
687 4 : CONF_SC_MAKE_CLIST_END();
688 :
689 : /* And they all live together ... dum dum */
690 178 : if (conf->data->conf->malloc_bad)
691 0 : return (FALSE);
692 :
693 178 : return (TRUE);
694 : }
695 :
696 : #define HTTPD_CONF__BEG_APP() do { \
697 : ASSERT(!opts->conf_num || (conf->state == CONF_PARSE_STATE_END)); \
698 : prev_conf_num = conf->sects->num; \
699 : /* reinit */ \
700 : conf->state = CONF_PARSE_STATE_BEG; \
701 : } while (FALSE)
702 :
703 : /* restore the previous parsing we've done and skip parsing it again */
704 : #define HTTPD_CONF__END_APP() do { \
705 : if (opts->conf_num) \
706 : { \
707 : conf_parse_token(conf, token); \
708 : conf_parse_num_token(conf, token, prev_conf_num); \
709 : } \
710 : } while (FALSE)
711 :
712 :
713 : int httpd_conf_main_parse_cstr(Vstr_base *out,
714 : Httpd_opts *opts, const char *data)
715 46 : {
716 46 : Conf_parse *conf = opts->conf;
717 46 : Conf_token token[1] = {CONF_TOKEN_INIT};
718 46 : unsigned int prev_conf_num = 0;
719 46 : size_t pos = 1;
720 46 : size_t len = 0;
721 :
722 23 : ASSERT(opts && data);
723 :
724 46 : if (!conf && !(conf = conf_parse_make(NULL)))
725 0 : goto conf_malloc_fail;
726 :
727 46 : pos = conf->data->len + 1;
728 46 : if (!vstr_add_cstr_ptr(conf->data, conf->data->len,
729 : "(org.and.httpd-conf-main-1.0 "))
730 0 : goto read_malloc_fail;
731 46 : if (!vstr_add_cstr_ptr(conf->data, conf->data->len, data))
732 0 : goto read_malloc_fail;
733 46 : if (!vstr_add_cstr_ptr(conf->data, conf->data->len,
734 : ")"))
735 0 : goto read_malloc_fail;
736 46 : len = vstr_sc_posdiff(pos, conf->data->len);
737 :
738 46 : HTTPD_CONF__BEG_APP();
739 :
740 46 : if (!conf_parse_lex(conf, pos, len))
741 0 : goto conf_fail;
742 :
743 46 : HTTPD_CONF__END_APP();
744 :
745 46 : if (!conf_parse_token(conf, token))
746 0 : goto conf_fail;
747 :
748 46 : if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1))
749 : goto conf_fail;
750 :
751 46 : if (!conf_parse_token(conf, token))
752 0 : goto conf_fail;
753 :
754 23 : ASSERT(OPT_SERV_SYM_EQ("org.and.httpd-conf-main-1.0"));
755 :
756 46 : if (!httpd_conf_main(opts, conf, token))
757 4 : goto conf_fail;
758 :
759 42 : if (token->num != conf->sects->num)
760 0 : goto conf_fail;
761 :
762 42 : opts->conf = conf;
763 42 : opts->conf_num++;
764 :
765 42 : return (TRUE);
766 :
767 4 : conf_fail:
768 4 : conf_parse_backtrace(out, data, conf, token);
769 4 : read_malloc_fail:
770 4 : conf_parse_free(conf);
771 4 : conf_malloc_fail:
772 4 : return (FALSE);
773 : }
774 :
775 : int httpd_conf_main_parse_file(Vstr_base *out,
776 : Httpd_opts *opts, const char *fname)
777 56 : {
778 56 : Conf_parse *conf = opts->conf;
779 56 : Conf_token token[1] = {CONF_TOKEN_INIT};
780 56 : unsigned int prev_conf_num = 0;
781 56 : size_t pos = 1;
782 56 : size_t len = 0;
783 :
784 28 : ASSERT(opts && fname);
785 :
786 56 : if (!conf && !(conf = conf_parse_make(NULL)))
787 0 : goto conf_malloc_fail;
788 :
789 56 : pos = conf->data->len + 1;
790 56 : if (!vstr_sc_read_len_file(conf->data, conf->data->len, fname, 0, 0, NULL))
791 4 : goto read_malloc_fail;
792 52 : len = vstr_sc_posdiff(pos, conf->data->len);
793 :
794 52 : HTTPD_CONF__BEG_APP();
795 :
796 52 : if (!conf_parse_lex(conf, pos, len))
797 0 : goto conf_fail;
798 :
799 52 : HTTPD_CONF__END_APP();
800 :
801 230 : while (conf_parse_token(conf, token))
802 : {
803 152 : if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1))
804 : goto conf_fail;
805 :
806 152 : if (!conf_parse_token(conf, token))
807 0 : goto conf_fail;
808 :
809 152 : if (OPT_SERV_SYM_EQ("org.and.daemon-conf-1.0"))
810 : {
811 16 : if (!opt_serv_conf(opts->s, conf, token))
812 0 : goto conf_fail;
813 : }
814 136 : else if (OPT_SERV_SYM_EQ("org.and.httpd-conf-main-1.0") ||
815 : OPT_SERV_SYM_EQ("org.and.jhttpd-conf-main-1.0"))
816 : {
817 136 : if (!httpd_conf_main(opts, conf, token))
818 0 : goto conf_fail;
819 : }
820 : else
821 : goto conf_fail;
822 :
823 152 : opts->conf_num++;
824 : }
825 :
826 52 : opts->conf = conf;
827 :
828 52 : return (TRUE);
829 :
830 0 : conf_fail:
831 0 : conf_parse_backtrace(out, fname, conf, token);
832 0 : errno = 0;
833 4 : read_malloc_fail:
834 4 : if (errno && out) /* can't find config. file */
835 4 : vstr_add_fmt(out, out->len, "open(%s): %m", fname);
836 :
837 4 : conf_parse_free(conf);
838 4 : conf_malloc_fail:
839 4 : return (FALSE);
840 : }
841 :
842 : int httpd_sc_conf_main_parse_dir_file(Vstr_base *out, void *opts,
843 : const char *fname)
844 26 : {
845 26 : return (httpd_conf_main_parse_file(out, opts, fname));
846 : }
847 :
848 : void httpd_conf_main_free(Httpd_opts *opts)
849 44 : {
850 44 : Opt_serv_policy_opts *scan = opts->s->def_policy;
851 :
852 232 : while (scan)
853 : {
854 144 : Httpd_policy_opts *tmp = (Httpd_policy_opts *)scan;
855 144 : Opt_serv_policy_opts *scan_next = scan->next;
856 :
857 144 : mime_types_exit(tmp->mime_types);
858 :
859 144 : scan = scan_next;
860 : }
861 :
862 44 : opt_policy_sc_all_ref_del(opts->s);
863 44 : conf_parse_free(opts->conf); opts->conf = NULL;
864 44 : date_free(opts->date); opts->date = NULL;
865 :
866 44 : opt_serv_conf_free_beg(opts->s);
867 44 : opt_serv_conf_free_end(opts->s);
868 44 : }
869 :
870 : int httpd_conf_main_init(Httpd_opts *httpd_opts)
871 64 : {
872 64 : Httpd_policy_opts *opts = NULL;
873 :
874 64 : if (!opt_serv_conf_init(httpd_opts->s))
875 0 : goto opts_init_fail;
876 :
877 64 : opts = (Httpd_policy_opts *)httpd_opts->s->def_policy;
878 :
879 64 : vstr_add_cstr_ptr(opts->server_name, 0, HTTPD_CONF_DEF_SERVER_NAME);
880 64 : vstr_add_cstr_ptr(opts->dir_filename, 0, HTTPD_CONF_DEF_DIR_FILENAME);
881 64 : vstr_add_cstr_ptr(opts->mime_types_def_ct, 0, HTTPD_CONF_MIME_TYPE_DEF_CT);
882 64 : vstr_add_cstr_ptr(opts->mime_types_main, 0, HTTPD_CONF_MIME_TYPE_MAIN);
883 64 : vstr_add_cstr_ptr(opts->mime_types_xtra, 0, HTTPD_CONF_MIME_TYPE_XTRA);
884 :
885 64 : if (!(httpd_opts->date = date_make()))
886 0 : goto httpd_init_fail;
887 :
888 64 : if (opts->s->policy_name->conf->malloc_bad)
889 0 : goto httpd_init_fail;
890 :
891 64 : return (TRUE);
892 :
893 0 : httpd_init_fail:
894 0 : httpd_conf_main_free(httpd_opts);
895 0 : opts_init_fail:
896 0 : return (FALSE);
897 : }
|