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