#include "httpd.h" #include "httpd_policy.h" #define EX_UTILS_NO_FUNCS 1 #include "ex_utils.h" #include "mk.h" #include "match_con.h" #include "base64.h" static int httpd__conf_main_policy_http_d1(Httpd_policy_opts *opts, Conf_parse *conf, Conf_token *token) { int clist = FALSE; CONF_SC_MAKE_CLIST_BEG(policy_http_d1, clist); else if (OPT_SERV_SYM_EQ("authorization") || OPT_SERV_SYM_EQ("auth")) { unsigned int depth = token->depth_num; CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE); if (0) { } else if (OPT_SERV_SYM_EQ("off")) { vstr_del(opts->auth_realm, 1, opts->auth_realm->len); vstr_del(opts->auth_token, 1, opts->auth_token->len); } else if (OPT_SERV_SYM_EQ("basic-encoded")) { /* echo -n foo:bar | base64 echo -n Zm9vOmJhcg== | base64 -d && echo */ CONF_SC_MAKE_CLIST_MID(depth, clist); else if (OPT_SERV_SYM_EQ("realm")) OPT_SERV_X_VSTR(opts->s->beg, opts->auth_realm); else if (OPT_SERV_SYM_EQ("token")) OPT_SERV_X_VSTR(opts->s->beg, opts->auth_token); CONF_SC_MAKE_CLIST_END(); } else if (OPT_SERV_SYM_EQ("basic-single")) { CONF_SC_MAKE_CLIST_MID(depth, clist); else if (OPT_SERV_SYM_EQ("realm")) OPT_SERV_X_VSTR(opts->s->beg, opts->auth_realm); else if (OPT_SERV_SYM_EQ("token")) OPT_SERV_X_SINGLE_VSTR(conf->tmp); CONF_SC_MAKE_CLIST_END(); vstr_del(opts->auth_token, 1, opts->auth_token->len); if (!vstr_x_conv_base64_encode(opts->auth_token, 0, conf->tmp, 1, conf->tmp->len, 0)) return (FALSE); } else return (FALSE); } else if (OPT_SERV_SYM_EQ("strictness")) { CONF_SC_MAKE_CLIST_BEG(http_checks, clist); else if (OPT_SERV_SYM_EQ("hdrs") || OPT_SERV_SYM_EQ("headers")) { CONF_SC_MAKE_CLIST_BEG(checks_hdrs, clist); else if (OPT_SERV_SYM_EQ("allow-dbl") || OPT_SERV_SYM_EQ("allow-double") || OPT_SERV_SYM_EQ("allow-*2")) OPT_SERV_X_NEG_TOGGLE(opts->use_hdrs_no_x2); else if (OPT_SERV_SYM_EQ("allow-missing-length")) OPT_SERV_X_NEG_TOGGLE(opts->use_hdrs_err_411); else if (OPT_SERV_SYM_EQ("allow-spaces")) OPT_SERV_X_NEG_TOGGLE(opts->use_hdrs_non_spc); CONF_SC_MAKE_CLIST_END(); } else if (OPT_SERV_SYM_EQ("host") || OPT_SERV_SYM_EQ("hostname")) { CONF_SC_MAKE_CLIST_BEG(checks_host, clist); else if (OPT_SERV_SYM_EQ("canonize") || OPT_SERV_SYM_EQ("make-canonical")) OPT_SERV_X_TOGGLE(opts->use_canonize_host); else if (OPT_SERV_SYM_EQ("validation")) { int use_internal_host_chk = FALSE; int use_host_chk = FALSE; int use_host_err_400 = FALSE; int validation_done = FALSE; CONF_SC_MAKE_CLIST_BEG(checks_host_valid, clist); else if (OPT_SERV_SYM_EQ("off") || OPT_SERV_SYM_EQ("false") || OPT_SERV_SYM_EQ("OFF") || OPT_SERV_SYM_EQ("FALSE") || OPT_SERV_SYM_EQ("no") || OPT_SERV_SYM_EQ("NO") || OPT_SERV_SYM_EQ("none") || OPT_SERV_SYM_EQ("NONE") || OPT_SERV_SYM_EQ("0")) { use_internal_host_chk = FALSE; use_host_chk = FALSE; use_host_err_400 = FALSE; validation_done = TRUE; } else if (OPT_SERV_SYM_EQ("fast") || OPT_SERV_SYM_EQ("internal")) { use_internal_host_chk = TRUE; validation_done = TRUE; } else if (OPT_SERV_SYM_EQ("virtual-hosts-default")) { use_host_chk = TRUE; use_host_err_400 = FALSE; validation_done = TRUE; } else if (OPT_SERV_SYM_EQ("virtual-hosts-error")) { use_host_chk = TRUE; use_host_err_400 = TRUE; validation_done = TRUE; } CONF_SC_MAKE_CLIST_END(); if (validation_done) { opts->use_internal_host_chk = use_internal_host_chk; opts->use_host_chk = use_host_chk; opts->use_host_err_400 = use_host_err_400; } } CONF_SC_MAKE_CLIST_END(); } else if (OPT_SERV_SYM_EQ("allow-HTTP/0.9")) OPT_SERV_X_TOGGLE(opts->allow_http_0_9); else if (OPT_SERV_SYM_EQ("allow-dot-directory") || OPT_SERV_SYM_EQ("allow-dot-dir") || OPT_SERV_SYM_EQ("allow-.-dir")) OPT_SERV_X_NEG_TOGGLE(opts->chk_dot_dir); else if (OPT_SERV_SYM_EQ("allow-encoded-slash") || OPT_SERV_SYM_EQ("allow-enc-/")) OPT_SERV_X_NEG_TOGGLE(opts->chk_encoded_slash); else if (OPT_SERV_SYM_EQ("allow-encoded-dot") || OPT_SERV_SYM_EQ("allow-enc-.")) OPT_SERV_X_NEG_TOGGLE(opts->chk_encoded_dot); else if (OPT_SERV_SYM_EQ("error-406") || OPT_SERV_SYM_EQ("error-not-acceptable") || OPT_SERV_SYM_EQ("error-406-not-acceptable")) OPT_SERV_X_TOGGLE(opts->use_err_406); else if (OPT_SERV_SYM_EQ("url") || OPT_SERV_SYM_EQ("URL")) { CONF_SC_MAKE_CLIST_BEG(checks_host, clist); else if (OPT_SERV_SYM_EQ("remove-fragment")) OPT_SERV_X_TOGGLE(opts->remove_url_frag); else if (OPT_SERV_SYM_EQ("remove-query")) OPT_SERV_X_TOGGLE(opts->remove_url_query); CONF_SC_MAKE_CLIST_END(); } CONF_SC_MAKE_CLIST_END(); /* end of http checks */ } else if (OPT_SERV_SYM_EQ("text-plain-redirect")) OPT_SERV_X_TOGGLE(opts->use_text_redirect); else if (OPT_SERV_SYM_EQ("ETag:")) { CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE); if (0) { } else if (OPT_SERV_SYM_EQ("auto-dev-inode-size-mtime")) opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_DISM; else if (OPT_SERV_SYM_EQ("auto-inode-size-mtime")) opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_ISM; else if (OPT_SERV_SYM_EQ("auto-size-mtime")) opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_SM; else if (OPT_SERV_SYM_EQ("auto-off") || OPT_SERV_SYM_EQ("auto-false") || OPT_SERV_SYM_EQ("auto-no") || OPT_SERV_SYM_EQ("auto-none")) opts->etag_auto_type = HTTPD_ETAG_TYPE_AUTO_NONE; else return (FALSE); } else if (OPT_SERV_SYM_EQ("encoded-content-replacement")) /* allow gzip */ OPT_SERV_X_TOGGLE(opts->use_enc_content_replacement); else if (OPT_SERV_SYM_EQ("keep-alive")) OPT_SERV_X_TOGGLE(opts->use_keep_alive); else if (OPT_SERV_SYM_EQ("keep-alive-1.0")) OPT_SERV_X_TOGGLE(opts->use_keep_alive_1_0); else if (OPT_SERV_SYM_EQ("keep-alive-hdr") || OPT_SERV_SYM_EQ("keep-alive-header")) OPT_SERV_X_TOGGLE(opts->output_keep_alive_hdr); else if (OPT_SERV_SYM_EQ("range")) OPT_SERV_X_TOGGLE(opts->use_range); else if (OPT_SERV_SYM_EQ("range-1.0")) OPT_SERV_X_TOGGLE(opts->use_range_1_0); else if (OPT_SERV_SYM_EQ("advertise-range")) OPT_SERV_X_TOGGLE(opts->use_adv_range); else if (OPT_SERV_SYM_EQ("trace-op") || OPT_SERV_SYM_EQ("trace-operation")) OPT_SERV_X_TOGGLE(opts->allow_trace_op); else if (OPT_SERV_SYM_EQ("url-remove-fragment")) /* compat */ OPT_SERV_X_TOGGLE(opts->remove_url_frag); else if (OPT_SERV_SYM_EQ("url-remove-query")) /* compat */ OPT_SERV_X_TOGGLE(opts->remove_url_query); else if (OPT_SERV_SYM_EQ("limit")) { CONF_SC_MAKE_CLIST_BEG(limit, clist); else if (OPT_SERV_SYM_EQ("header-size") || OPT_SERV_SYM_EQ("header-sz")) OPT_SERV_X_UINT(opts->max_header_sz); else if (OPT_SERV_SYM_EQ("requests")) OPT_SERV_X_UINT(opts->max_requests); else if (OPT_SERV_SYM_EQ("nodes")) { CONF_SC_MAKE_CLIST_BEG(nodes, clist); else if (OPT_SERV_SYM_EQ("Accept:")) OPT_SERV_X_UINT(opts->max_A_nodes); else if (OPT_SERV_SYM_EQ("Accept-Charset:")) OPT_SERV_X_UINT(opts->max_AC_nodes); else if (OPT_SERV_SYM_EQ("Accept-Encoding:")) OPT_SERV_X_UINT(opts->max_AE_nodes); else if (OPT_SERV_SYM_EQ("Accept-Language:")) OPT_SERV_X_UINT(opts->max_AL_nodes); else if (OPT_SERV_SYM_EQ("Connection:")) OPT_SERV_X_UINT(opts->max_connection_nodes); else if (OPT_SERV_SYM_EQ("ETag:")) OPT_SERV_X_UINT(opts->max_etag_nodes); else if (OPT_SERV_SYM_EQ("Range:")) { OPT_SERV_X_UINT(opts->max_range_nodes); if (!opts->max_range_nodes) { opts->use_range = FALSE; opts->use_range_1_0 = FALSE; } } CONF_SC_MAKE_CLIST_END(); } CONF_SC_MAKE_CLIST_END(); } else if (OPT_SERV_SYM_EQ("Server:") || OPT_SERV_SYM_EQ("server-name")) OPT_SERV_X_VSTR(opts->s->beg, opts->server_name); CONF_SC_MAKE_CLIST_END(); return (TRUE); } static int httpd__conf_main_policy_d1(Httpd_policy_opts *opts, Conf_parse *conf, Conf_token *token, int clist) { if (0) { } else if (OPT_SERV_SYM_EQ("match-init")) OPT_SERV_SC_MATCH_INIT(opts->s->beg, httpd__conf_main_policy_d1(opts, conf, token, clist)); else if (OPT_SERV_SYM_EQ("directory-filename")) return (opt_serv_sc_make_static_path(opts->s->beg, conf, token, opts->dir_filename)); else if (OPT_SERV_SYM_EQ("document-root") || OPT_SERV_SYM_EQ("doc-root")) return (opt_serv_sc_make_static_path(opts->s->beg, conf, token, opts->document_root)); else if (OPT_SERV_SYM_EQ("unspecified-hostname")) OPT_SERV_X_VSTR(opts->s->beg, opts->default_hostname); else if (OPT_SERV_SYM_EQ("MIME/types-default-type")) OPT_SERV_X_VSTR(opts->s->beg, opts->mime_types_def_ct); else if (OPT_SERV_SYM_EQ("MIME/types-filename-main")) return (opt_serv_sc_make_static_path(opts->s->beg, conf, token, opts->mime_types_main)); else if (OPT_SERV_SYM_EQ("MIME/types-filename-extra") || OPT_SERV_SYM_EQ("MIME/types-filename-xtra")) return (opt_serv_sc_make_static_path(opts->s->beg, conf, token, opts->mime_types_xtra)); else if (OPT_SERV_SYM_EQ("request-configuration-directory") || OPT_SERV_SYM_EQ("req-conf-dir")) return (opt_serv_sc_make_static_path(opts->s->beg, conf, token, opts->req_conf_dir)); else if (OPT_SERV_SYM_EQ("request-error-directory") || OPT_SERV_SYM_EQ("req-err-dir")) return (opt_serv_sc_make_static_path(opts->s->beg, conf, token, opts->req_err_dir)); else if (OPT_SERV_SYM_EQ("server-name")) /* compat. */ OPT_SERV_X_VSTR(opts->s->beg, opts->server_name); else if (OPT_SERV_SYM_EQ("secure-directory-filename")) OPT_SERV_X_TOGGLE(opts->use_secure_dirs); else if (OPT_SERV_SYM_EQ("redirect-filename-directory")) OPT_SERV_X_TOGGLE(opts->use_friendly_dirs); else if (OPT_SERV_SYM_EQ("mmap")) OPT_SERV_X_TOGGLE(opts->use_mmap); else if (OPT_SERV_SYM_EQ("sendfile")) OPT_SERV_X_TOGGLE(opts->use_sendfile); else if (OPT_SERV_SYM_EQ("virtual-hosts") || OPT_SERV_SYM_EQ("vhosts") || OPT_SERV_SYM_EQ("virtual-hosts-name") || OPT_SERV_SYM_EQ("vhosts-name")) OPT_SERV_X_TOGGLE(opts->use_vhosts_name); else if (OPT_SERV_SYM_EQ("public-only")) OPT_SERV_X_TOGGLE(opts->use_public_only); else if (OPT_SERV_SYM_EQ("posix-fadvise")) OPT_SERV_X_TOGGLE(opts->use_posix_fadvise); else if (OPT_SERV_SYM_EQ("update-atime")) OPT_SERV_X_NEG_TOGGLE(opts->use_noatime); else if (OPT_SERV_SYM_EQ("tcp-cork")) OPT_SERV_X_TOGGLE(opts->use_tcp_cork); else if (OPT_SERV_SYM_EQ("allow-request-configuration")) OPT_SERV_X_TOGGLE(opts->use_req_conf); else if (OPT_SERV_SYM_EQ("allow-header-splitting")) OPT_SERV_X_TOGGLE(opts->allow_hdr_split); else if (OPT_SERV_SYM_EQ("allow-header-NIL")) OPT_SERV_X_TOGGLE(opts->allow_hdr_nil); else if (OPT_SERV_SYM_EQ("unspecified-hostname-append-port")) OPT_SERV_X_TOGGLE(opts->add_def_port); else if (OPT_SERV_SYM_EQ("limit")) { CONF_SC_MAKE_CLIST_BEG(limit, clist); else if (OPT_SERV_SYM_EQ("request-configuration-size") || OPT_SERV_SYM_EQ("request-configuration-sz") || OPT_SERV_SYM_EQ("req-conf-size") || OPT_SERV_SYM_EQ("req-conf-sz")) OPT_SERV_X_UINT(opts->max_req_conf_sz); else if (OPT_SERV_SYM_EQ("nodes")) { /* this limts how much you can have in the configs., not over HTTP */ CONF_SC_MAKE_CLIST_BEG(nodes, clist); else if (OPT_SERV_SYM_EQ("Accept:")) OPT_SERV_X_UINT(opts->max_neg_A_nodes); else if (OPT_SERV_SYM_EQ("Accept-Language:")) OPT_SERV_X_UINT(opts->max_neg_AL_nodes); CONF_SC_MAKE_CLIST_END(); } CONF_SC_MAKE_CLIST_END(); } else if (OPT_SERV_SYM_EQ("HTTP") || OPT_SERV_SYM_EQ("http")) return (httpd__conf_main_policy_http_d1(opts, conf, token)); else return (FALSE); return (TRUE); } static int httpd__conf_main_policy(Httpd_opts *opts, Conf_parse *conf, Conf_token *token) { Opt_serv_policy_opts *popts = NULL; Conf_token *ntoken = NULL; unsigned int cur_depth = opt_policy_sc_conf_parse(opts->s, conf, token, &popts, &ntoken); if (!cur_depth) return (FALSE); do { int clist = FALSE; CONF_SC_MAKE_CLIST_MID(cur_depth, clist); else if (httpd__conf_main_policy_d1((Httpd_policy_opts *)popts, conf, token, clist)) { } CONF_SC_MAKE_CLIST_END(); } while (ntoken && (cur_depth = opt_policy_sc_conf_parse(opts->s, conf, token, &popts, &ntoken))); return (TRUE); } typedef struct Httpd__match_uval { Conf_token opt_nxt; /* token first, so we can just use it as that */ void (*s_cb_func)(Vstr_ref *); Vstr_base *name; } Httpd__match_uval; static int httpd__match_ref_del_eq(Vstr_base *s1, Vstr_ref *ref) { int eq = FALSE; if (ref) { Httpd__match_uval *uval = ref->ptr; if (uval->name) eq = vstr_cmp_eq(uval->name, 1, uval->name->len, s1, 1, s1->len); } if (eq) vstr_ref_del(ref); return (eq); } static int httpd__match_find(Conf_parse *conf, Conf_token **token) { Vstr_ref *ref = NULL; unsigned int num = 0; if (!httpd__match_iter_beg(conf, *token, &ref, &num)) return (FALSE); do { if (httpd__match_ref_del_eq(conf->tmp, ref)) return (TRUE); } while (httpd__match_iter_nxt(conf, *token, &ref, &num)); return (FALSE); } static int httpd__match_find_before(Conf_parse *conf, Conf_token **token) { Vstr_ref *ref = NULL; unsigned int num = 0; Conf_token prev[1]; if (!httpd__match_iter_beg(conf, *token, &ref, &num)) return (FALSE); if (httpd__match_ref_del_eq(conf->tmp, ref)) { *token = NULL; return (TRUE); } *prev = **token; while (httpd__match_iter_nxt(conf, *token, &ref, &num)) { if (httpd__match_ref_del_eq(conf->tmp, ref)) { **token = *prev; return (TRUE); } *prev = **token; } return (FALSE); } static void httpd__match_ref_cb(Vstr_ref *ref) { Httpd__match_uval *uval = ref->ptr; vstr_free_base(uval->name); (*uval->s_cb_func)(ref); } static int httpd__match_make(Conf_parse *conf, Conf_token *token, unsigned int type, Conf_token *beg, Conf_token *end) { unsigned int outer_depth = token->depth_num; int ret = FALSE; Vstr_ref *ref = NULL; Conf_token token_srch_tmp = CONF_TOKEN_INIT; Conf_token save = CONF_TOKEN_INIT; Conf_token *add_beg = end; Httpd__match_uval *uval = NULL; int auto_reclaim_ref = FALSE; ASSERT(beg && end && (!beg->num == !end->num)); if (!conf_token_set_user_value(conf, token, type, NULL, 0)) return (FALSE); if (!(ref = vstr_ref_make_malloc(sizeof(Httpd__match_uval)))) return (FALSE); uval = ref->ptr; uval->name = NULL; uval->s_cb_func = ref->func; ref->func = httpd__match_ref_cb; uval->opt_nxt = save = *token; ret = conf_token_set_user_value(conf, &save, type, ref, 0); ASSERT(ret); vstr_ref_del(ref); /* going to use uval/ref later, but that's OK */ CONF_SC_PARSE_TOP_TOKEN_RET(conf, token, FALSE); if (token->type != CONF_TOKEN_TYPE_SLIST) { int clist_name = FALSE; int clist_xtra = FALSE; unsigned int inner_depth = 0; const Vstr_sect_node *pv = NULL; CONF_SC_TOGGLE_CLIST_VAR(clist_name); if (token->type == CONF_TOKEN_TYPE_CLIST) goto skip_name; if (!(pv = conf_token_value(token))) return (FALSE); if (!(uval->name = vstr_make_base(conf->tmp->conf))) return (FALSE); if (!vstr_add_vstr(uval->name, 0, conf->data, pv->pos, pv->len, VSTR_TYPE_ADD_BUF_REF)) return (FALSE); skip_name: inner_depth = token->depth_num; CONF_SC_MAKE_CLIST_MID(inner_depth, clist_xtra); else if (token->type == CONF_TOKEN_TYPE_SLIST) goto skip_position; else if (OPT_SERV_SYM_EQ("after") && beg->num) { OPT_SERV_X_SINGLE_VSTR(conf->tmp); token_srch_tmp = *beg; add_beg = &token_srch_tmp; if (!httpd__match_find(conf, &add_beg)) return (FALSE); } else if (OPT_SERV_SYM_EQ("before") && beg->num) { OPT_SERV_X_SINGLE_VSTR(conf->tmp); token_srch_tmp = *beg; add_beg = &token_srch_tmp; if (!httpd__match_find_before(conf, &add_beg)) return (FALSE); } else if (OPT_SERV_SYM_EQ("end")) add_beg = end; else if (OPT_SERV_SYM_EQ("beg") || OPT_SERV_SYM_EQ("beginning")) add_beg = NULL; else if (OPT_SERV_SYM_EQ("")) OPT_SERV_X_TOGGLE(auto_reclaim_ref); CONF_SC_MAKE_CLIST_END(); CONF_SC_PARSE_SLIST_DEPTH_TOKEN_RET(conf, token, outer_depth, FALSE); } skip_position: if ((token->type != CONF_TOKEN_TYPE_SLIST) || (conf_token_at_depth(token) != outer_depth)) return (FALSE); ASSERT(ref); if (auto_reclaim_ref && !uval->name) ref = NULL; if (!beg->num) { ret = conf_token_set_user_value(conf, &save, type, ref, 0); ASSERT(ret); *beg = save; *end = save; } else if (!add_beg) /* put before beg */ { ret = conf_token_set_user_value(conf, &save, type, ref, beg->num); ASSERT(ret); *beg = save; } else { Vstr_ref *oref = NULL; unsigned int nxt = 0; ASSERT(add_beg && ((add_beg->type - CONF_TOKEN_TYPE_USER_BEG) == type)); ASSERT(add_beg->num != 0); oref = conf_token_get_user_value(conf, add_beg, &nxt); ASSERT(oref); ret = conf_token_set_user_value(conf, &save, type, ref, nxt); ASSERT(ret); ret = conf_token_set_user_value(conf, add_beg, type, oref, save.num); ASSERT(ret); if (!nxt) /* put after end */ { ASSERT(add_beg->num == end->num); *end = save; } vstr_ref_del(oref); } return (TRUE); } static int httpd__conf_main_d1(Httpd_opts *httpd_opts, Conf_parse *conf, Conf_token *token, int clist) { if (OPT_SERV_SYM_EQ("org.and.daemon-conf-1.0")) { if (!opt_serv_conf(httpd_opts->s, conf, token)) return (FALSE); } else if (OPT_SERV_SYM_EQ("match-init")) OPT_SERV_SC_MATCH_INIT(httpd_opts->s, httpd__conf_main_d1(httpd_opts, conf, token, clist)); else if (OPT_SERV_SYM_EQ("policy")) { if (!httpd__conf_main_policy(httpd_opts, conf, token)) return (FALSE); } else if (OPT_SERV_SYM_EQ("match-connection")) { if (!httpd__match_make(conf, token, HTTPD_CONF_MAIN_MATCH_CON, httpd_opts->match_connection, httpd_opts->tmp_match_connection)) return (FALSE); if (!conf_parse_end_token(conf, token, conf_token_at_depth(token))) return (FALSE); } else if (OPT_SERV_SYM_EQ("match-request")) { if (!httpd__match_make(conf, token, HTTPD_CONF_MAIN_MATCH_REQ, httpd_opts->match_request, httpd_opts->tmp_match_request)) return (FALSE); if (!conf_parse_end_token(conf, token, conf_token_at_depth(token))) return (FALSE); } else if (OPT_SERV_SYM_EQ("match-error-response")) { if (!httpd__match_make(conf, token, HTTPD_CONF_MAIN_MATCH_RESP, httpd_opts->match_response, httpd_opts->tmp_match_response)) return (FALSE); if (!conf_parse_end_token(conf, token, conf_token_at_depth(token))) return (FALSE); } else return (FALSE); return (TRUE); } int httpd_conf_main(Httpd_opts *opts, Conf_parse *conf, Conf_token *token) { unsigned int cur_depth = token->depth_num; int clist = FALSE; if (!OPT_SERV_SYM_EQ("org.and.httpd-conf-main-1.0") && !OPT_SERV_SYM_EQ("org.and.jhttpd-conf-main-1.0")) return (FALSE); CONF_SC_MAKE_CLIST_MID(cur_depth, clist); else if (httpd__conf_main_d1(opts, conf, token, clist)) { } CONF_SC_MAKE_CLIST_END(); /* And they all live together ... dum dum */ if (conf->data->conf->malloc_bad) return (FALSE); return (TRUE); } #define HTTPD_CONF__BEG_APP() do { \ ASSERT(!opts->conf_num || (conf->state == CONF_PARSE_STATE_END)); \ prev_conf_num = conf->sects->num; \ /* reinit */ \ conf->state = CONF_PARSE_STATE_BEG; \ } while (FALSE) /* restore the previous parsing we've done and skip parsing it again */ #define HTTPD_CONF__END_APP() do { \ if (opts->conf_num) \ { \ conf_parse_token(conf, token); \ conf_parse_num_token(conf, token, prev_conf_num); \ } \ } while (FALSE) int httpd_conf_main_parse_cstr(Vstr_base *out, Httpd_opts *opts, const char *data) { Conf_parse *conf = opts->conf; Conf_token token[1] = {CONF_TOKEN_INIT}; unsigned int prev_conf_num = 0; size_t pos = 1; size_t len = 0; ASSERT(opts && data); if (!conf && !(conf = conf_parse_make(NULL))) goto conf_malloc_fail; pos = conf->data->len + 1; if (!vstr_add_cstr_ptr(conf->data, conf->data->len, "(org.and.httpd-conf-main-1.0 ")) goto read_malloc_fail; if (!vstr_add_cstr_ptr(conf->data, conf->data->len, data)) goto read_malloc_fail; if (!vstr_add_cstr_ptr(conf->data, conf->data->len, ")")) goto read_malloc_fail; len = vstr_sc_posdiff(pos, conf->data->len); HTTPD_CONF__BEG_APP(); if (!conf_parse_lex(conf, pos, len)) goto conf_fail; HTTPD_CONF__END_APP(); if (!conf_parse_token(conf, token)) goto conf_fail; if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1)) goto conf_fail; if (!conf_parse_token(conf, token)) goto conf_fail; ASSERT(OPT_SERV_SYM_EQ("org.and.httpd-conf-main-1.0")); if (!httpd_conf_main(opts, conf, token)) goto conf_fail; if (token->num != conf->sects->num) goto conf_fail; opts->conf = conf; opts->conf_num++; return (TRUE); conf_fail: conf_parse_backtrace(out, data, conf, token); read_malloc_fail: conf_parse_free(conf); conf_malloc_fail: return (FALSE); } int httpd_conf_main_parse_file(Vstr_base *out, Httpd_opts *opts, const char *fname) { Conf_parse *conf = opts->conf; Conf_token token[1] = {CONF_TOKEN_INIT}; unsigned int prev_conf_num = 0; size_t pos = 1; size_t len = 0; ASSERT(opts && fname); if (!conf && !(conf = conf_parse_make(NULL))) goto conf_malloc_fail; pos = conf->data->len + 1; if (!vstr_sc_read_len_file(conf->data, conf->data->len, fname, 0, 0, NULL)) goto read_malloc_fail; len = vstr_sc_posdiff(pos, conf->data->len); HTTPD_CONF__BEG_APP(); if (!conf_parse_lex(conf, pos, len)) goto conf_fail; HTTPD_CONF__END_APP(); while (conf_parse_token(conf, token)) { if ((token->type != CONF_TOKEN_TYPE_CLIST) || (token->depth_num != 1)) goto conf_fail; if (!conf_parse_token(conf, token)) goto conf_fail; if (OPT_SERV_SYM_EQ("org.and.daemon-conf-1.0")) { if (!opt_serv_conf(opts->s, conf, token)) goto conf_fail; } else if (OPT_SERV_SYM_EQ("org.and.httpd-conf-main-1.0") || OPT_SERV_SYM_EQ("org.and.jhttpd-conf-main-1.0")) { if (!httpd_conf_main(opts, conf, token)) goto conf_fail; } else goto conf_fail; opts->conf_num++; } opts->conf = conf; return (TRUE); conf_fail: conf_parse_backtrace(out, fname, conf, token); errno = 0; read_malloc_fail: if (errno && out) /* can't find config. file */ vstr_add_fmt(out, out->len, "open(%s): %m", fname); conf_parse_free(conf); conf_malloc_fail: return (FALSE); } int httpd_sc_conf_main_parse_dir_file(Vstr_base *out, void *opts, const char *fname) { return (httpd_conf_main_parse_file(out, opts, fname)); } void httpd_conf_main_free(Httpd_opts *opts) { Opt_serv_policy_opts *scan = opts->s->def_policy; while (scan) { Httpd_policy_opts *tmp = (Httpd_policy_opts *)scan; Opt_serv_policy_opts *scan_next = scan->next; mime_types_exit(tmp->mime_types); scan = scan_next; } opt_policy_sc_all_ref_del(opts->s); conf_parse_free(opts->conf); opts->conf = NULL; date_free(opts->date); opts->date = NULL; opt_serv_conf_free_beg(opts->s); opt_serv_conf_free_end(opts->s); } int httpd_conf_main_init(Httpd_opts *httpd_opts) { Httpd_policy_opts *opts = NULL; if (!opt_serv_conf_init(httpd_opts->s)) goto opts_init_fail; opts = (Httpd_policy_opts *)httpd_opts->s->def_policy; vstr_add_cstr_ptr(opts->server_name, 0, HTTPD_CONF_DEF_SERVER_NAME); vstr_add_cstr_ptr(opts->dir_filename, 0, HTTPD_CONF_DEF_DIR_FILENAME); vstr_add_cstr_ptr(opts->mime_types_def_ct, 0, HTTPD_CONF_MIME_TYPE_DEF_CT); vstr_add_cstr_ptr(opts->mime_types_main, 0, HTTPD_CONF_MIME_TYPE_MAIN); vstr_add_cstr_ptr(opts->mime_types_xtra, 0, HTTPD_CONF_MIME_TYPE_XTRA); if (!(httpd_opts->date = date_make())) goto httpd_init_fail; if (opts->s->policy_name->conf->malloc_bad) goto httpd_init_fail; return (TRUE); httpd_init_fail: httpd_conf_main_free(httpd_opts); opts_init_fail: return (FALSE); }