1 /* _ _
2 ** _ __ ___ ___ __| | ___ ___| | mod_ssl
3 ** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
4 ** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
5 ** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
6 ** |_____|
7 ** ssl_expr_eval.c
8 ** Expression Evaluation
9 */
10
11 /* ====================================================================
12 * Copyright (c) 1998-2003 Ralf S. Engelschall. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
25 *
26 * 3. All advertising materials mentioning features or use of this
27 * software must display the following acknowledgment:
28 * "This product includes software developed by
29 * Ralf S. Engelschall <rse@engelschall.com> for use in the
30 * mod_ssl project (http://www.modssl.org/)."
31 *
32 * 4. The names "mod_ssl" must not be used to endorse or promote
33 * products derived from this software without prior written
34 * permission. For written permission, please contact
35 * rse@engelschall.com.
36 *
37 * 5. Products derived from this software may not be called "mod_ssl"
38 * nor may "mod_ssl" appear in their names without prior
39 * written permission of Ralf S. Engelschall.
40 *
41 * 6. Redistributions of any form whatsoever must retain the following
42 * acknowledgment:
43 * "This product includes software developed by
44 * Ralf S. Engelschall <rse@engelschall.com> for use in the
45 * mod_ssl project (http://www.modssl.org/)."
46 *
47 * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
48 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
51 * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
58 * OF THE POSSIBILITY OF SUCH DAMAGE.
59 * ====================================================================
60 */
61 /* ``Make love,
62 not software!''
63 -- Unknown */
64 #include "mod_ssl.h"
65
66
67 /* _________________________________________________________________
68 **
69 ** Expression Evaluation
70 ** _________________________________________________________________
71 */
72
73 static BOOL ssl_expr_eval_comp(request_rec *, ssl_expr *);
74 static char *ssl_expr_eval_word(request_rec *, ssl_expr *);
75 static char *ssl_expr_eval_func_file(request_rec *, char *);
76 static int ssl_expr_eval_strcmplex(char *, char *);
77
ssl_expr_eval(request_rec * r,ssl_expr * node)78 BOOL ssl_expr_eval(request_rec *r, ssl_expr *node)
79 {
80 switch (node->node_op) {
81 case op_True: {
82 return TRUE;
83 }
84 case op_False: {
85 return FALSE;
86 }
87 case op_Not: {
88 ssl_expr *e = (ssl_expr *)node->node_arg1;
89 return (!ssl_expr_eval(r, e));
90 }
91 case op_Or: {
92 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
93 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
94 return (ssl_expr_eval(r, e1) || ssl_expr_eval(r, e2));
95 }
96 case op_And: {
97 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
98 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
99 return (ssl_expr_eval(r, e1) && ssl_expr_eval(r, e2));
100 }
101 case op_Comp: {
102 ssl_expr *e = (ssl_expr *)node->node_arg1;
103 return ssl_expr_eval_comp(r, e);
104 }
105 default: {
106 ssl_expr_error = "Internal evaluation error: Unknown expression node";
107 return FALSE;
108 }
109 }
110 }
111
ssl_expr_eval_comp(request_rec * r,ssl_expr * node)112 static BOOL ssl_expr_eval_comp(request_rec *r, ssl_expr *node)
113 {
114 switch (node->node_op) {
115 case op_EQ: {
116 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
117 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
118 return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) == 0);
119 }
120 case op_NE: {
121 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
122 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
123 return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) != 0);
124 }
125 case op_LT: {
126 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
127 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
128 return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) < 0);
129 }
130 case op_LE: {
131 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
132 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
133 return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) <= 0);
134 }
135 case op_GT: {
136 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
137 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
138 return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) > 0);
139 }
140 case op_GE: {
141 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
142 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
143 return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) >= 0);
144 }
145 case op_IN: {
146 ssl_expr *e1 = (ssl_expr *)node->node_arg1;
147 ssl_expr *e2 = (ssl_expr *)node->node_arg2;
148 ssl_expr *e3;
149 char *w1 = ssl_expr_eval_word(r, e1);
150 BOOL found = FALSE;
151 do {
152 e3 = (ssl_expr *)e2->node_arg1;
153 e2 = (ssl_expr *)e2->node_arg2;
154 if (strcmp(w1, ssl_expr_eval_word(r, e3)) == 0) {
155 found = TRUE;
156 break;
157 }
158 } while (e2 != NULL);
159 return found;
160 }
161 case op_REG: {
162 ssl_expr *e1;
163 ssl_expr *e2;
164 char *word;
165 regex_t *regex;
166
167 e1 = (ssl_expr *)node->node_arg1;
168 e2 = (ssl_expr *)node->node_arg2;
169 word = ssl_expr_eval_word(r, e1);
170 regex = (regex_t *)(e2->node_arg1);
171 return (regexec(regex, word, 0, NULL, 0) == 0);
172 }
173 case op_NRE: {
174 ssl_expr *e1;
175 ssl_expr *e2;
176 char *word;
177 regex_t *regex;
178
179 e1 = (ssl_expr *)node->node_arg1;
180 e2 = (ssl_expr *)node->node_arg2;
181 word = ssl_expr_eval_word(r, e1);
182 regex = (regex_t *)(e2->node_arg1);
183 return !(regexec(regex, word, 0, NULL, 0) == 0);
184 }
185 default: {
186 ssl_expr_error = "Internal evaluation error: Unknown expression node";
187 return FALSE;
188 }
189 }
190 }
191
ssl_expr_eval_word(request_rec * r,ssl_expr * node)192 static char *ssl_expr_eval_word(request_rec *r, ssl_expr *node)
193 {
194 switch (node->node_op) {
195 case op_Digit: {
196 char *string = (char *)node->node_arg1;
197 return string;
198 }
199 case op_String: {
200 char *string = (char *)node->node_arg1;
201 return string;
202 }
203 case op_Var: {
204 char *var = (char *)node->node_arg1;
205 char *val = ssl_var_lookup(r->pool, r->server, r->connection, r, var);
206 return (val == NULL ? "" : val);
207 }
208 case op_Func: {
209 char *name = (char *)node->node_arg1;
210 ssl_expr *args = (ssl_expr *)node->node_arg2;
211 if (strEQ(name, "file"))
212 return ssl_expr_eval_func_file(r, (char *)(args->node_arg1));
213 else {
214 ssl_expr_error = "Internal evaluation error: Unknown function name";
215 return "";
216 }
217 }
218 default: {
219 ssl_expr_error = "Internal evaluation error: Unknown expression node";
220 return FALSE;
221 }
222 }
223 }
224
ssl_expr_eval_func_file(request_rec * r,char * filename)225 static char *ssl_expr_eval_func_file(request_rec *r, char *filename)
226 {
227 FILE *fp;
228 char *buf;
229 int len;
230
231 if ((fp = ap_pfopen(r->pool, filename, "r")) == NULL) {
232 ssl_expr_error = "Cannot open file";
233 return "";
234 }
235 fseek(fp, 0, SEEK_END);
236 len = ftell(fp);
237 if (len == 0) {
238 buf = (char *)ap_palloc(r->pool, sizeof(char) * 1);
239 *buf = NUL;
240 }
241 else {
242 if ((buf = (char *)ap_palloc(r->pool, sizeof(char) * (len+1))) == NULL) {
243 ssl_expr_error = "Cannot allocate memory";
244 ap_pfclose(r->pool, fp);
245 return "";
246 }
247 fseek(fp, 0, SEEK_SET);
248 if (fread(buf, len, 1, fp) == 0) {
249 ssl_expr_error = "Cannot read from file";
250 fclose(fp);
251 return ("");
252 }
253 buf[len] = NUL;
254 }
255 ap_pfclose(r->pool, fp);
256 return buf;
257 }
258
259 /* a variant of strcmp(3) which works correctly also for number strings */
ssl_expr_eval_strcmplex(char * cpNum1,char * cpNum2)260 static int ssl_expr_eval_strcmplex(char *cpNum1, char *cpNum2)
261 {
262 int i, n1, n2;
263
264 if (cpNum1 == NULL)
265 return -1;
266 if (cpNum2 == NULL)
267 return +1;
268 n1 = strlen(cpNum1);
269 n2 = strlen(cpNum2);
270 if (n1 > n2)
271 return 1;
272 if (n1 < n2)
273 return -1;
274 for (i = 0; i < n1; i++) {
275 if (cpNum1[i] > cpNum2[i])
276 return 1;
277 if (cpNum1[i] < cpNum2[i])
278 return -1;
279 }
280 return 0;
281 }
282
283