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 :
13 :
14 : static int httpd__policy_connection_tst_d1(struct Con *,
15 : Conf_parse *, Conf_token *,
16 : int *, int);
17 :
18 : static int httpd__policy_connection_tst_op_d1(Conf_parse *conf,
19 : Conf_token *token,
20 : int *matches, int prev_match,
21 : void *con)
22 18072 : {
23 18072 : return (httpd__policy_connection_tst_d1(con, conf, token,
24 : matches, prev_match));
25 : }
26 :
27 :
28 : static int httpd__policy_connection_tst_d1(struct Con *con,
29 : Conf_parse *conf, Conf_token *token,
30 : int *matches, int prev_match)
31 155640 : {
32 155640 : int clist = FALSE;
33 :
34 77820 : ASSERT(con);
35 77820 : ASSERT(matches);
36 :
37 155640 : CONF_SC_TOGGLE_CLIST_VAR(clist);
38 :
39 155640 : if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
40 : {
41 38830 : unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
42 38830 : unsigned int nxt = 0;
43 38830 : Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
44 :
45 38830 : switch (type)
46 : {
47 : case HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ:
48 : {
49 0 : struct sockaddr *sa = CON_CEVNT_SA(con);
50 0 : *matches = httpd_policy_ipv4_cidr_eq(con, NULL, ref->ptr, sa);
51 : }
52 0 : break;
53 :
54 : case HTTPD_POLICY_SERVER_IPV4_CIDR_EQ:
55 : {
56 38830 : struct sockaddr *sa = CON_SEVNT_SA(con);
57 38830 : *matches = httpd_policy_ipv4_cidr_eq(con, NULL, ref->ptr, sa);
58 : }
59 38830 : break;
60 :
61 : default:
62 0 : vstr_ref_del(ref);
63 0 : return (FALSE);
64 : }
65 :
66 38830 : vstr_ref_del(ref);
67 38830 : if (nxt)
68 38830 : return (conf_parse_num_token(conf, token, nxt));
69 : }
70 :
71 157874 : else if (OPT_SERV_SYM_EQ("policy-eq") || OPT_SERV_SYM_EQ("policy=="))
72 82128 : OPT_SERV_X_EQ(con->policy->s->policy_name);
73 45476 : else if (OPT_SERV_SYM_EQ("tag-eq") || OPT_SERV_SYM_EQ("tag=="))
74 21588 : OPT_SERV_X_EQ(con->tag);
75 13094 : else if (OPT_SERV_SYM_EQ("client-ipv4-cidr-eq") ||
76 : OPT_SERV_SYM_EQ("client-ipv4-cidr=="))
77 0 : return (httpd_policy_ipv4_make(con, NULL, conf, token,
78 : HTTPD_POLICY_CLIENT_IPV4_CIDR_EQ,
79 : CON_CEVNT_SA(con), matches));
80 13094 : else if (OPT_SERV_SYM_EQ("server-ipv4-cidr-eq") ||
81 : OPT_SERV_SYM_EQ("server-ipv4-cidr=="))
82 86 : return (httpd_policy_ipv4_make(con, NULL, conf, token,
83 : HTTPD_POLICY_SERVER_IPV4_CIDR_EQ,
84 : CON_SEVNT_SA(con), matches));
85 13008 : else if (OPT_SERV_SYM_EQ("server-ipv4-port-eq") ||
86 : OPT_SERV_SYM_EQ("server-ipv4-port=="))
87 : {
88 0 : struct sockaddr *sa = CON_SEVNT_SA(con);
89 0 : unsigned int tst_port = 0;
90 :
91 0 : OPT_SERV_X_SINGLE_UINT(tst_port);
92 :
93 0 : if (sa->sa_family != AF_INET)
94 0 : *matches = FALSE;
95 : else
96 : {
97 0 : struct sockaddr_in *sin = CON_SEVNT_SA_IN4(con);
98 0 : *matches = tst_port == ntohs(sin->sin_port);
99 : }
100 : }
101 :
102 : else
103 13008 : return (opt_serv_sc_tst(conf, token, matches, prev_match,
104 : httpd__policy_connection_tst_op_d1, con));
105 :
106 103716 : return (TRUE);
107 : }
108 :
109 : static int httpd__policy_connection_d1(struct Con *con,
110 : Conf_parse *conf, Conf_token *token,
111 : int *stop)
112 8936 : {
113 8936 : int clist = FALSE;
114 :
115 8936 : CONF_SC_TOGGLE_CLIST_VAR(clist);
116 :
117 8936 : if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
118 : {
119 7926 : unsigned int type = token->type - CONF_TOKEN_TYPE_USER_BEG;
120 7926 : unsigned int nxt = 0;
121 7926 : Vstr_ref *ref = conf_token_get_user_value(conf, token, &nxt);
122 :
123 7926 : switch (type)
124 : {
125 : case HTTPD_POLICY_CON_POLICY:
126 7926 : httpd_policy_change_con(con, ref->ptr);
127 : break;
128 :
129 : default:
130 0 : vstr_ref_del(ref);
131 0 : return (FALSE);
132 : }
133 :
134 7926 : vstr_ref_del(ref);
135 7926 : if (nxt)
136 7926 : return (conf_parse_num_token(conf, token, nxt));
137 : }
138 :
139 1010 : else if (OPT_SERV_SYM_EQ("<close>"))
140 : {
141 0 : evnt_close(con->evnt);
142 0 : return (TRUE);
143 : }
144 1010 : else if (OPT_SERV_SYM_EQ("<stop>"))
145 : {
146 0 : *stop = TRUE;
147 0 : return (TRUE);
148 : }
149 1010 : else if (OPT_SERV_SYM_EQ("policy"))
150 : {
151 50 : const Httpd_policy_opts *policy = NULL;
152 :
153 50 : if (!(policy = httpd__policy_build(con, conf, token,
154 : HTTPD_POLICY_CON_POLICY)))
155 0 : return (FALSE);
156 50 : httpd_policy_change_con(con, policy);
157 : }
158 960 : else if (OPT_SERV_SYM_EQ("tag"))
159 960 : OPT_SERV_X_VSTR(con->policy->s->beg, con->tag);
160 0 : else if (OPT_SERV_SYM_EQ("Vary:_*"))
161 0 : OPT_SERV_X_TOGGLE(con->vary_star);
162 :
163 : else
164 0 : return (FALSE);
165 :
166 1010 : return (TRUE);
167 : }
168 :
169 : static int httpd__policy_connection_d0(struct Con *con,
170 : Conf_parse *conf, Conf_token *token,
171 : int *stop)
172 112204 : {
173 : static int prev_match = TRUE;
174 112204 : unsigned int depth = token->depth_num;
175 112204 : int matches = TRUE;
176 :
177 112204 : if (token->type != CONF_TOKEN_TYPE_SLIST)
178 0 : return (FALSE);
179 :
180 202542 : while (conf_token_list_num(token, depth))
181 : {
182 137568 : CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
183 :
184 137568 : if (!httpd__policy_connection_tst_d1(con, conf, token,
185 : &matches, prev_match))
186 0 : return (FALSE);
187 :
188 137568 : if (!matches)
189 : {
190 103332 : prev_match = FALSE;
191 103332 : return (TRUE);
192 : }
193 : }
194 8872 : --depth;
195 :
196 8872 : prev_match = TRUE;
197 :
198 26680 : while (conf_token_list_num(token, depth))
199 : {
200 8936 : CONF_SC_PARSE_DEPTH_TOKEN_RET(conf, token, depth, FALSE);
201 :
202 8936 : if (!httpd__policy_connection_d1(con, conf, token, stop))
203 0 : return (FALSE);
204 8936 : if (*stop || con->evnt->flag_q_closed) /* don't do anything else */
205 0 : return (TRUE);
206 : }
207 :
208 8872 : return (TRUE);
209 : }
210 :
211 : int httpd_policy_connection(struct Con *con,
212 : Conf_parse *conf, const Conf_token *beg_token)
213 12052 : {
214 : Conf_token token[1];
215 12052 : Vstr_ref *ref = NULL;
216 12052 : unsigned int num = 0;
217 :
218 12052 : if (!beg_token->num) /* not been parsed */
219 3868 : return (TRUE);
220 :
221 8184 : *token = *beg_token;
222 8184 : if (!httpd__match_iter_beg(conf, token, &ref, &num))
223 0 : return (TRUE);
224 :
225 : do
226 : {
227 112204 : int stop = FALSE;
228 :
229 112204 : conf_parse_num_token(conf, token, token->num);
230 56102 : assert(token->type == (CONF_TOKEN_TYPE_USER_BEG+HTTPD_CONF_MAIN_MATCH_CON));
231 :
232 365070 : while (token->type != CONF_TOKEN_TYPE_SLIST)
233 196764 : conf_parse_token(conf, token);
234 :
235 112204 : if (!httpd__policy_connection_d0(con, conf, token, &stop))
236 0 : goto conf_fail;
237 112204 : if (stop || con->evnt->flag_q_closed) /* don't do anything else */
238 : break;
239 112204 : } while (httpd__match_iter_nxt(conf, token, &ref, &num));
240 :
241 8184 : vstr_ref_del(ref);
242 8184 : vstr_del(conf->tmp, 1, conf->tmp->len);
243 8184 : return (TRUE);
244 :
245 0 : conf_fail:
246 0 : vstr_ref_del(ref);
247 0 : vstr_del(conf->tmp, 1, conf->tmp->len);
248 0 : conf_parse_backtrace(conf->tmp, "<policy-connection>", conf, token);
249 0 : return (FALSE);
250 : }
|