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_req.h"
11 :
12 : /* fwd reference */
13 : static int httpd_match_response_tst_d1(struct Con *, Httpd_req_data *,
14 : Conf_parse *, Conf_token *, int *, int);
15 :
16 : static int httpd__match_response_tst_op_d1(Conf_parse *conf, Conf_token *token,
17 : int *matches, int prev_match,
18 : void *passed_data)
19 18112 : {
20 18112 : struct Httpd__policy_req_tst_data *data = passed_data;
21 18112 : struct Con *con = data->con;
22 18112 : Httpd_req_data *req = data->req;
23 :
24 18112 : return (httpd_match_response_tst_d1(con, req, conf, token,
25 : matches, prev_match));
26 : }
27 :
28 : static int httpd_match_response_tst_d1(struct Con *con, Httpd_req_data *req,
29 : Conf_parse *conf, Conf_token *token,
30 : int *matches, int prev_match)
31 140916 : {
32 140916 : int clist = FALSE;
33 : struct Httpd__policy_req_tst_data data[1];
34 :
35 70458 : ASSERT(con && req);
36 70458 : ASSERT(matches);
37 :
38 140916 : CONF_SC_TOGGLE_CLIST_VAR(clist); /* note this doesn't get passed to reqeust */
39 :
40 140916 : data->con = con;
41 140916 : data->req = req;
42 :
43 140916 : if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
44 : {
45 26408 : unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
46 26408 : unsigned int nxt = 0;
47 26408 : Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
48 :
49 : switch (type)
50 : {
51 : /* all handled by match_req atm. */
52 : default:
53 26408 : vstr_ref_del(ref);
54 26408 : return (httpd_match_request_tst_d1(con, req, conf, token,
55 : matches, prev_match,
56 : httpd__match_response_tst_op_d1,
57 : data));
58 : }
59 :
60 : vstr_ref_del(ref);
61 : if (nxt)
62 : return (conf_parse_num_token(conf, token, nxt));
63 : }
64 :
65 168656 : else if (OPT_SERV_SYM_EQ("error-response-code-eq") ||
66 : OPT_SERV_SYM_EQ("error-response-code=="))
67 : {
68 54148 : unsigned int tmp = 0;
69 :
70 54148 : OPT_SERV_X_SYM_UINT_BEG(tmp); /* only ones allowed via. match-response */
71 10328 : else if (OPT_SERV_SYM_EQ("<bad>")) tmp = 400;
72 9592 : else if (OPT_SERV_SYM_EQ("<bad-request>")) tmp = 400;
73 : /* else if (OPT_SERV_SYM_EQ("<unauthorized>")) tmp = 401; */
74 9592 : else if (OPT_SERV_SYM_EQ("<forbidden>")) tmp = 403;
75 9496 : else if (OPT_SERV_SYM_EQ("<not-found>")) tmp = 404;
76 : /* else if (OPT_SERV_SYM_EQ("<Method-Not-Allowed>")) tmp = 405; */
77 0 : else if (OPT_SERV_SYM_EQ("<not-acceptable>")) tmp = 406;
78 0 : else if (OPT_SERV_SYM_EQ("<gone>")) tmp = 410;
79 0 : OPT_SERV_X_SYM_NUM_END();
80 :
81 54148 : *matches = tmp == req->req_error_code;
82 : }
83 60424 : else if (OPT_SERV_SYM_EQ("error-response-detail-eq") ||
84 : OPT_SERV_SYM_EQ("error-response-detail=="))
85 128 : OPT_SERV_X_CSTR_EQ(req->req_error_xmsg);
86 61000 : else if (OPT_SERV_SYM_EQ("error-user-initiated-eq") ||
87 : OPT_SERV_SYM_EQ("error-user-initiated=="))
88 : {
89 768 : unsigned int tmp = 0;
90 :
91 768 : OPT_SERV_X_TOGGLE(tmp);
92 :
93 768 : *matches = tmp == req->req_user_return_error_code;
94 : }
95 : else
96 59464 : return (httpd_match_request_tst_d1(con, req, conf, token,
97 : matches, prev_match,
98 : httpd__match_response_tst_op_d1, data));
99 :
100 55044 : return (TRUE);
101 : }
102 :
103 : static int httpd__policy_response_d0(struct Con *con, struct Httpd_req_data *req,
104 : Conf_parse *conf, Conf_token *token,
105 : int *stop)
106 96572 : {
107 : static int prev_match = TRUE;
108 96572 : unsigned int depth = token->depth_num;
109 96572 : int matches = TRUE;
110 :
111 96572 : if (token->type != CONF_TOKEN_TYPE_SLIST)
112 0 : return (FALSE);
113 :
114 171762 : while (conf_token_list_num(token, depth))
115 : {
116 122804 : CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
117 :
118 122804 : if (!httpd_match_response_tst_d1(con, req, conf, token,
119 : &matches, prev_match))
120 0 : return (FALSE);
121 :
122 122804 : if (!matches)
123 : {
124 95900 : prev_match = FALSE;
125 95900 : return (TRUE);
126 : }
127 : }
128 672 : --depth;
129 :
130 672 : prev_match = TRUE;
131 :
132 1344 : while (conf_token_list_num(token, depth))
133 : {
134 672 : CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
135 :
136 : /* request and response can/should be able to do the same things */
137 672 : if (!httpd__policy_request_d1(con, req, conf, token, stop))
138 672 : return (FALSE);
139 0 : if (*stop || con->evnt->flag_q_closed) /* don't do anything else */
140 0 : return (TRUE);
141 : }
142 :
143 0 : return (TRUE);
144 : }
145 :
146 : int httpd_policy_response(struct Con *con, struct Httpd_req_data *req,
147 : Conf_parse *conf, const Conf_token *beg_token)
148 8504 : {
149 : Conf_token token[1];
150 8504 : Vstr_ref *ref = NULL;
151 8504 : unsigned int num = 0;
152 :
153 8504 : if (!beg_token->num) /* not been parsed */
154 3564 : return (TRUE);
155 :
156 4940 : *token = *beg_token;
157 4940 : if (!httpd__match_iter_beg(conf, token, &ref, &num))
158 0 : return (TRUE);
159 :
160 : do
161 : {
162 96572 : int stop = FALSE;
163 :
164 96572 : conf_parse_num_token(conf, token, token->num);
165 48286 : assert(token->type == (CONF_TOKEN_TYPE_USER_BEG +
166 : HTTPD_CONF_MAIN_MATCH_RESP));
167 :
168 338002 : while (token->type != CONF_TOKEN_TYPE_SLIST)
169 193144 : conf_parse_token(conf, token);
170 :
171 96572 : if (!httpd__policy_response_d0(con, req, conf, token, &stop))
172 672 : goto conf_fail;
173 95900 : if (stop || con->evnt->flag_q_closed) /* don't do anything else */
174 : break;
175 95900 : } while (httpd__match_iter_nxt(conf, token, &ref, &num));
176 :
177 4268 : vstr_ref_del(ref);
178 4268 : vstr_del(conf->tmp, 1, conf->tmp->len);
179 4268 : return (TRUE);
180 :
181 672 : conf_fail:
182 672 : vstr_ref_del(ref);
183 672 : vstr_del(conf->tmp, 1, conf->tmp->len);
184 672 : if (!req->user_return_error_code)
185 : {
186 0 : conf_parse_backtrace(conf->tmp, "<policy-response>", conf, token);
187 0 : HTTPD_ERR(req, 503); /* do this, or not ? */
188 : }
189 672 : return (FALSE);
190 : }
191 :
|