1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*                      _             _
18  *  ap_expr_eval.c, based on ssl_expr_eval.c from mod_ssl
19  */
20 
21 #include "httpd.h"
22 #include "http_log.h"
23 #include "http_core.h"
24 #include "http_protocol.h"
25 #include "http_request.h"
26 #include "http_ssl.h"
27 #include "ap_provider.h"
28 #include "util_expr_private.h"
29 #include "util_md5.h"
30 
31 #include "apr_lib.h"
32 #include "apr_fnmatch.h"
33 #include "apr_base64.h"
34 #include "apr_sha1.h"
35 #include "apr_version.h"
36 #if APR_VERSION_AT_LEAST(1,5,0)
37 #include "apr_escape.h"
38 #endif
39 
40 #include <limits.h>     /* for INT_MAX */
41 
42 /* we know core's module_index is 0 */
43 #undef APLOG_MODULE_INDEX
44 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
45 
46 APR_HOOK_STRUCT(
47     APR_HOOK_LINK(expr_lookup)
48 )
49 
50 AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_expr_lookup_parms *parms),
51                             (parms), DECLINED)
52 
53 #define  LOG_MARK(info)  __FILE__, __LINE__, (info)->module_index
54 
55 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
56                                             const ap_expr_t *info,
57                                             const ap_expr_t *args);
58 static const char *ap_expr_eval_re_backref(ap_expr_eval_ctx_t *ctx,
59                                            unsigned int n);
60 static const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
61                                     ap_expr_var_func_t *func,
62                                     const void *data);
63 
64 /* define AP_EXPR_DEBUG to log the parse tree when parsing an expression */
65 #ifdef AP_EXPR_DEBUG
66 static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
67                            int loglevel, int indent);
68 #endif
69 
70 /*
71  * To reduce counting overhead, we only count calls to
72  * ap_expr_eval_word() and ap_expr_eval(). The max number of
73  * stack frames is larger by some factor.
74  */
75 #define AP_EXPR_MAX_RECURSION   20
inc_rec(ap_expr_eval_ctx_t * ctx)76 static int inc_rec(ap_expr_eval_ctx_t *ctx)
77 {
78     if (ctx->reclvl < AP_EXPR_MAX_RECURSION) {
79         ctx->reclvl++;
80         return 0;
81     }
82     *ctx->err = "Recursion limit reached";
83     /* short circuit further evaluation */
84     ctx->reclvl = INT_MAX;
85     return 1;
86 }
87 
ap_expr_eval_word(ap_expr_eval_ctx_t * ctx,const ap_expr_t * node)88 static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
89                                      const ap_expr_t *node)
90 {
91     const char *result = "";
92     if (inc_rec(ctx))
93         return result;
94     switch (node->node_op) {
95     case op_Digit:
96     case op_String:
97         result = node->node_arg1;
98         break;
99     case op_Var:
100         result = ap_expr_eval_var(ctx, (ap_expr_var_func_t *)node->node_arg1,
101                                   node->node_arg2);
102         break;
103     case op_Concat:
104         if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat &&
105             ((ap_expr_t *)node->node_arg1)->node_op != op_Concat) {
106             const char *s1 = ap_expr_eval_word(ctx, node->node_arg1);
107             const char *s2 = ap_expr_eval_word(ctx, node->node_arg2);
108             if (!*s1)
109                 result = s2;
110             else if (!*s2)
111                 result = s1;
112             else
113                 result = apr_pstrcat(ctx->p, s1, s2, NULL);
114         }
115         else if (((ap_expr_t *)node->node_arg1)->node_op == op_Concat) {
116             const ap_expr_t *nodep = node;
117             int n;
118             int i = 1;
119             struct iovec *vec;
120             do {
121                 nodep = nodep->node_arg1;
122                 i++;
123             } while (nodep->node_op == op_Concat);
124             vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
125             n = i;
126             nodep = node;
127             i--;
128             do {
129                 vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
130                                                             nodep->node_arg2);
131                 vec[i].iov_len = strlen(vec[i].iov_base);
132                 i--;
133                 nodep = nodep->node_arg1;
134             } while (nodep->node_op == op_Concat);
135             vec[i].iov_base = (void *)ap_expr_eval_word(ctx, nodep);
136             vec[i].iov_len = strlen(vec[i].iov_base);
137             result = apr_pstrcatv(ctx->p, vec, n, NULL);
138         }
139         else {
140             const ap_expr_t *nodep = node;
141             int i = 1;
142             struct iovec *vec;
143             do {
144                 nodep = nodep->node_arg2;
145                 i++;
146             } while (nodep->node_op == op_Concat);
147             vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
148             nodep = node;
149             i = 0;
150             do {
151                 vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
152                                                             nodep->node_arg1);
153                 vec[i].iov_len = strlen(vec[i].iov_base);
154                 i++;
155                 nodep = nodep->node_arg2;
156             } while (nodep->node_op == op_Concat);
157             vec[i].iov_base = (void *)ap_expr_eval_word(ctx, nodep);
158             vec[i].iov_len = strlen(vec[i].iov_base);
159             i++;
160             result = apr_pstrcatv(ctx->p, vec, i, NULL);
161         }
162         break;
163     case op_StringFuncCall: {
164         const ap_expr_t *info = node->node_arg1;
165         const ap_expr_t *args = node->node_arg2;
166         result = ap_expr_eval_string_func(ctx, info, args);
167         break;
168     }
169     case op_RegexBackref: {
170         const unsigned int *np = node->node_arg1;
171         result = ap_expr_eval_re_backref(ctx, *np);
172         break;
173     }
174     default:
175         *ctx->err = "Internal evaluation error: Unknown word expression node";
176         break;
177     }
178     if (!result)
179         result = "";
180     ctx->reclvl--;
181     return result;
182 }
183 
ap_expr_eval_var(ap_expr_eval_ctx_t * ctx,ap_expr_var_func_t * func,const void * data)184 static const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
185                                     ap_expr_var_func_t *func,
186                                     const void *data)
187 {
188     AP_DEBUG_ASSERT(func != NULL);
189     AP_DEBUG_ASSERT(data != NULL);
190     return (*func)(ctx, data);
191 }
192 
ap_expr_eval_re_backref(ap_expr_eval_ctx_t * ctx,unsigned int n)193 static const char *ap_expr_eval_re_backref(ap_expr_eval_ctx_t *ctx, unsigned int n)
194 {
195     int len;
196 
197     if (!ctx->re_pmatch || !ctx->re_source || !*ctx->re_source
198         || **ctx->re_source == '\0' || ctx->re_nmatch < n + 1)
199         return "";
200 
201     len = ctx->re_pmatch[n].rm_eo - ctx->re_pmatch[n].rm_so;
202     if (len == 0)
203         return "";
204 
205     return apr_pstrndup(ctx->p, *ctx->re_source + ctx->re_pmatch[n].rm_so, len);
206 }
207 
ap_expr_eval_string_func(ap_expr_eval_ctx_t * ctx,const ap_expr_t * info,const ap_expr_t * arg)208 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
209                                             const ap_expr_t *info,
210                                             const ap_expr_t *arg)
211 {
212     ap_expr_string_func_t *func = (ap_expr_string_func_t *)info->node_arg1;
213     const void *data = info->node_arg2;
214 
215     AP_DEBUG_ASSERT(info->node_op == op_StringFuncInfo);
216     AP_DEBUG_ASSERT(func != NULL);
217     AP_DEBUG_ASSERT(data != NULL);
218     return (*func)(ctx, data, ap_expr_eval_word(ctx, arg));
219 }
220 
intstrcmp(const char * s1,const char * s2)221 static int intstrcmp(const char *s1, const char *s2)
222 {
223     apr_int64_t i1 = apr_atoi64(s1);
224     apr_int64_t i2 = apr_atoi64(s2);
225 
226     if (i1 < i2)
227         return -1;
228     else if (i1 == i2)
229         return 0;
230     else
231         return 1;
232 }
233 
ap_expr_eval_comp(ap_expr_eval_ctx_t * ctx,const ap_expr_t * node)234 static int ap_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
235 {
236     const ap_expr_t *e1 = node->node_arg1;
237     const ap_expr_t *e2 = node->node_arg2;
238     switch (node->node_op) {
239     case op_EQ:
240         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
241     case op_NE:
242         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
243     case op_LT:
244         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
245     case op_LE:
246         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
247     case op_GT:
248         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
249     case op_GE:
250         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
251     case op_STR_EQ:
252         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
253     case op_STR_NE:
254         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
255     case op_STR_LT:
256         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
257     case op_STR_LE:
258         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
259     case op_STR_GT:
260         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
261     case op_STR_GE:
262         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
263     case op_IN: {
264             const char *needle = ap_expr_eval_word(ctx, e1);
265             if (e2->node_op == op_ListElement) {
266                 do {
267                     const ap_expr_t *val = e2->node_arg1;
268                     AP_DEBUG_ASSERT(e2->node_op == op_ListElement);
269                     if (strcmp(needle, ap_expr_eval_word(ctx, val)) == 0)
270                         return 1;
271                     e2 = e2->node_arg2;
272                 } while (e2 != NULL);
273             }
274             else if (e2->node_op == op_ListFuncCall) {
275                 const ap_expr_t *info = e2->node_arg1;
276                 const ap_expr_t *arg = e2->node_arg2;
277                 ap_expr_list_func_t *func = (ap_expr_list_func_t *)info->node_arg1;
278                 apr_array_header_t *haystack;
279 
280                 AP_DEBUG_ASSERT(func != NULL);
281                 AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo);
282                 haystack = (*func)(ctx, info->node_arg2, ap_expr_eval_word(ctx, arg));
283                 if (haystack == NULL) {
284                     return 0;
285                 }
286                 if (ap_array_str_contains(haystack, needle)) {
287                     return 1;
288                 }
289             }
290             return 0;
291         }
292     case op_REG:
293     case op_NRE: {
294             const char *word = ap_expr_eval_word(ctx, e1);
295             const ap_regex_t *regex = e2->node_arg1;
296             int result;
297 
298             /*
299              * $0 ... $9 may contain stuff the user wants to keep. Therefore
300              * we only set them if there are capturing parens in the regex.
301              */
302             if (regex->re_nsub > 0) {
303                 result = (0 == ap_regexec(regex, word, ctx->re_nmatch,
304                                           ctx->re_pmatch, 0));
305                 *ctx->re_source = result ? word : NULL;
306             }
307             else {
308                 result = (0 == ap_regexec(regex, word, 0, NULL, 0));
309             }
310 
311             if (node->node_op == op_REG)
312                 return result;
313             else
314                 return !result;
315         }
316     default:
317         *ctx->err = "Internal evaluation error: Unknown comp expression node";
318         return -1;
319     }
320 }
321 
322 /* combined string/int comparison for compatibility with ssl_expr */
strcmplex(const char * str1,const char * str2)323 static int strcmplex(const char *str1, const char *str2)
324 {
325     apr_size_t i, n1, n2;
326 
327     if (str1 == NULL)
328         return -1;
329     if (str2 == NULL)
330         return +1;
331     n1 = strlen(str1);
332     n2 = strlen(str2);
333     if (n1 > n2)
334         return 1;
335     if (n1 < n2)
336         return -1;
337     for (i = 0; i < n1; i++) {
338         if (str1[i] > str2[i])
339             return 1;
340         if (str1[i] < str2[i])
341             return -1;
342     }
343     return 0;
344 }
345 
ssl_expr_eval_comp(ap_expr_eval_ctx_t * ctx,const ap_expr_t * node)346 static int ssl_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
347 {
348     const ap_expr_t *e1 = node->node_arg1;
349     const ap_expr_t *e2 = node->node_arg2;
350     switch (node->node_op) {
351     case op_EQ:
352     case op_STR_EQ:
353         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
354     case op_NE:
355     case op_STR_NE:
356         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
357     case op_LT:
358     case op_STR_LT:
359         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
360     case op_LE:
361     case op_STR_LE:
362         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
363     case op_GT:
364     case op_STR_GT:
365         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
366     case op_GE:
367     case op_STR_GE:
368         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
369     default:
370         return ap_expr_eval_comp(ctx, node);
371     }
372 }
373 
ap_expr_lookup_default(ap_expr_lookup_parms * parms)374 AP_DECLARE_NONSTD(int) ap_expr_lookup_default(ap_expr_lookup_parms *parms)
375 {
376     return ap_run_expr_lookup(parms);
377 }
378 
ap_expr_parse(apr_pool_t * pool,apr_pool_t * ptemp,ap_expr_info_t * info,const char * expr,ap_expr_lookup_fn_t * lookup_fn)379 AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp,
380                                        ap_expr_info_t *info, const char *expr,
381                                        ap_expr_lookup_fn_t *lookup_fn)
382 {
383     ap_expr_parse_ctx_t ctx;
384     int rc;
385 
386     ctx.pool     = pool;
387     ctx.ptemp    = ptemp;
388     ctx.inputbuf = expr;
389     ctx.inputlen = strlen(expr);
390     ctx.inputptr = ctx.inputbuf;
391     ctx.expr     = NULL;
392     ctx.error    = NULL;        /* generic bison error message (XXX: usually not very useful, should be axed) */
393     ctx.error2   = NULL;        /* additional error message */
394     ctx.flags    = info->flags;
395     ctx.scan_del    = '\0';
396     ctx.scan_buf[0] = '\0';
397     ctx.scan_ptr    = ctx.scan_buf;
398     ctx.lookup_fn   = lookup_fn ? lookup_fn : ap_expr_lookup_default;
399     ctx.at_start    = 1;
400 
401     ap_expr_yylex_init(&ctx.scanner);
402     ap_expr_yyset_extra(&ctx, ctx.scanner);
403     rc = ap_expr_yyparse(&ctx);
404     ap_expr_yylex_destroy(ctx.scanner);
405     if (ctx.error) {
406         if (ctx.error2)
407             return apr_psprintf(pool, "%s: %s", ctx.error, ctx.error2);
408         else
409             return ctx.error;
410     }
411     else if (ctx.error2) {
412         return ctx.error2;
413     }
414 
415     if (rc) /* XXX can this happen? */
416         return "syntax error";
417 
418 #ifdef AP_EXPR_DEBUG
419     if (ctx.expr)
420         expr_dump_tree(ctx.expr, NULL, APLOG_NOTICE, 2);
421 #endif
422 
423     info->root_node = ctx.expr;
424 
425     return NULL;
426 }
427 
ap_expr_parse_cmd_mi(const cmd_parms * cmd,const char * expr,unsigned int flags,const char ** err,ap_expr_lookup_fn_t * lookup_fn,int module_index)428 AP_DECLARE(ap_expr_info_t*) ap_expr_parse_cmd_mi(const cmd_parms *cmd,
429                                                  const char *expr,
430                                                  unsigned int flags,
431                                                  const char **err,
432                                                  ap_expr_lookup_fn_t *lookup_fn,
433                                                  int module_index)
434 {
435     ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t));
436     info->filename = cmd->directive->filename;
437     info->line_number = cmd->directive->line_num;
438     info->flags = flags;
439     info->module_index = module_index;
440     *err = ap_expr_parse(cmd->pool, cmd->temp_pool, info, expr, lookup_fn);
441 
442     if (*err)
443         return NULL;
444 
445     return info;
446 }
447 
ap_expr_make(ap_expr_node_op_e op,const void * a1,const void * a2,ap_expr_parse_ctx_t * ctx)448 ap_expr_t *ap_expr_make(ap_expr_node_op_e op, const void *a1, const void *a2,
449                       ap_expr_parse_ctx_t *ctx)
450 {
451     ap_expr_t *node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
452     node->node_op   = op;
453     node->node_arg1 = a1;
454     node->node_arg2 = a2;
455     return node;
456 }
457 
ap_expr_info_make(int type,const char * name,ap_expr_parse_ctx_t * ctx,const ap_expr_t * arg)458 static ap_expr_t *ap_expr_info_make(int type, const char *name,
459                                   ap_expr_parse_ctx_t *ctx,
460                                   const ap_expr_t *arg)
461 {
462     ap_expr_t *info = apr_palloc(ctx->pool, sizeof(ap_expr_t));
463     ap_expr_lookup_parms parms;
464     parms.type  = type;
465     parms.flags = ctx->flags;
466     parms.pool  = ctx->pool;
467     parms.ptemp = ctx->ptemp;
468     parms.name  = name;
469     parms.func  = &info->node_arg1;
470     parms.data  = &info->node_arg2;
471     parms.err   = &ctx->error2;
472     parms.arg   = (arg && arg->node_op == op_String) ? arg->node_arg1 : NULL;
473     if (ctx->lookup_fn(&parms) != OK)
474         return NULL;
475     return info;
476 }
477 
ap_expr_str_func_make(const char * name,const ap_expr_t * arg,ap_expr_parse_ctx_t * ctx)478 ap_expr_t *ap_expr_str_func_make(const char *name, const ap_expr_t *arg,
479                                ap_expr_parse_ctx_t *ctx)
480 {
481     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_STRING, name, ctx, arg);
482     if (!info)
483         return NULL;
484 
485     info->node_op = op_StringFuncInfo;
486     return ap_expr_make(op_StringFuncCall, info, arg, ctx);
487 }
488 
ap_expr_list_func_make(const char * name,const ap_expr_t * arg,ap_expr_parse_ctx_t * ctx)489 ap_expr_t *ap_expr_list_func_make(const char *name, const ap_expr_t *arg,
490                                 ap_expr_parse_ctx_t *ctx)
491 {
492     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_LIST, name, ctx, arg);
493     if (!info)
494         return NULL;
495 
496     info->node_op = op_ListFuncInfo;
497     return ap_expr_make(op_ListFuncCall, info, arg, ctx);
498 }
499 
ap_expr_unary_op_make(const char * name,const ap_expr_t * arg,ap_expr_parse_ctx_t * ctx)500 ap_expr_t *ap_expr_unary_op_make(const char *name, const ap_expr_t *arg,
501                                ap_expr_parse_ctx_t *ctx)
502 {
503     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_OP_UNARY, name, ctx, arg);
504     if (!info)
505         return NULL;
506 
507     info->node_op = op_UnaryOpInfo;
508     return ap_expr_make(op_UnaryOpCall, info, arg, ctx);
509 }
510 
ap_expr_binary_op_make(const char * name,const ap_expr_t * arg1,const ap_expr_t * arg2,ap_expr_parse_ctx_t * ctx)511 ap_expr_t *ap_expr_binary_op_make(const char *name, const ap_expr_t *arg1,
512                                 const ap_expr_t *arg2, ap_expr_parse_ctx_t *ctx)
513 {
514     ap_expr_t *args;
515     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_OP_BINARY, name, ctx,
516                                         arg2);
517     if (!info)
518         return NULL;
519 
520     info->node_op = op_BinaryOpInfo;
521     args = ap_expr_make(op_BinaryOpArgs, arg1, arg2, ctx);
522     return ap_expr_make(op_BinaryOpCall, info, args, ctx);
523 }
524 
525 
ap_expr_var_make(const char * name,ap_expr_parse_ctx_t * ctx)526 ap_expr_t *ap_expr_var_make(const char *name, ap_expr_parse_ctx_t *ctx)
527 {
528     ap_expr_t *node = ap_expr_info_make(AP_EXPR_FUNC_VAR, name, ctx, NULL);
529     if (!node)
530         return NULL;
531 
532     node->node_op = op_Var;
533     return node;
534 }
535 
536 #ifdef AP_EXPR_DEBUG
537 
538 #define MARK                        APLOG_MARK,loglevel,0,s
539 #define DUMP_E_E(op, e1, e2)                                                \
540     do { ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, e1, e2);      \
541          if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);               \
542          if (e2) expr_dump_tree(e2, s, loglevel, indent + 2);               \
543     } while (0)
544 #define DUMP_S_E(op, s1, e1)                                                    \
545     do { ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, e1); \
546          if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);                   \
547     } while (0)
548 #define DUMP_S_P(op, s1, p1)                                                \
549     ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, p1);
550 #define DUMP_P_P(op, p1, p2)                                                \
551     ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, p1, p2);
552 #define DUMP_S_S(op, s1, s2)                                                       \
553     ap_log_error(MARK,"%*s%s: '%s' '%s'", indent, " ", op, (char *)s1, (char *)s2)
554 #define DUMP_P(op, p1)                                                      \
555     ap_log_error(MARK,"%*s%s: %pp", indent, " ", op, p1);
556 #define DUMP_IP(op, p1)                                                     \
557     ap_log_error(MARK,"%*s%s: %d", indent, " ", op, *(int *)p1);
558 #define DUMP_S(op, s1)                                                      \
559     ap_log_error(MARK,"%*s%s: '%s'", indent, " ", op, (char *)s1)
560 
561 #define CASE_OP(op)                  case op: name = #op ; break;
562 
expr_dump_tree(const ap_expr_t * e,const server_rec * s,int loglevel,int indent)563 static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
564                            int loglevel, int indent)
565 {
566     switch (e->node_op) {
567     /* no arg */
568     case op_NOP:
569     case op_True:
570     case op_False:
571         {
572             char *name;
573             switch (e->node_op) {
574             CASE_OP(op_NOP);
575             CASE_OP(op_True);
576             CASE_OP(op_False);
577             default:
578                 ap_assert(0);
579             }
580             ap_log_error(MARK, "%*s%s", indent, " ", name);
581         }
582         break;
583 
584     /* arg1: string, arg2: expr */
585     case op_UnaryOpCall:
586     case op_BinaryOpCall:
587     case op_BinaryOpArgs:
588         {
589             char *name;
590             switch (e->node_op) {
591             CASE_OP(op_BinaryOpCall);
592             CASE_OP(op_UnaryOpCall);
593             CASE_OP(op_BinaryOpArgs);
594             default:
595                 ap_assert(0);
596             }
597             DUMP_S_E(name, e->node_arg1, e->node_arg2);
598         }
599         break;
600 
601     /* arg1: expr, arg2: expr */
602     case op_Comp:
603     case op_Not:
604     case op_Or:
605     case op_And:
606     case op_EQ:
607     case op_NE:
608     case op_LT:
609     case op_LE:
610     case op_GT:
611     case op_GE:
612     case op_STR_EQ:
613     case op_STR_NE:
614     case op_STR_LT:
615     case op_STR_LE:
616     case op_STR_GT:
617     case op_STR_GE:
618     case op_IN:
619     case op_REG:
620     case op_NRE:
621     case op_Concat:
622     case op_StringFuncCall:
623     case op_ListFuncCall:
624     case op_ListElement:
625         {
626             char *name;
627             switch (e->node_op) {
628             CASE_OP(op_Comp);
629             CASE_OP(op_Not);
630             CASE_OP(op_Or);
631             CASE_OP(op_And);
632             CASE_OP(op_EQ);
633             CASE_OP(op_NE);
634             CASE_OP(op_LT);
635             CASE_OP(op_LE);
636             CASE_OP(op_GT);
637             CASE_OP(op_GE);
638             CASE_OP(op_STR_EQ);
639             CASE_OP(op_STR_NE);
640             CASE_OP(op_STR_LT);
641             CASE_OP(op_STR_LE);
642             CASE_OP(op_STR_GT);
643             CASE_OP(op_STR_GE);
644             CASE_OP(op_IN);
645             CASE_OP(op_REG);
646             CASE_OP(op_NRE);
647             CASE_OP(op_Concat);
648             CASE_OP(op_StringFuncCall);
649             CASE_OP(op_ListFuncCall);
650             CASE_OP(op_ListElement);
651             default:
652                 ap_assert(0);
653             }
654             DUMP_E_E(name, e->node_arg1, e->node_arg2);
655         }
656         break;
657     /* arg1: string */
658     case op_Digit:
659     case op_String:
660         {
661             char *name;
662             switch (e->node_op) {
663             CASE_OP(op_Digit);
664             CASE_OP(op_String);
665             default:
666                 ap_assert(0);
667             }
668             DUMP_S(name, e->node_arg1);
669         }
670         break;
671     /* arg1: pointer, arg2: pointer */
672     case op_Var:
673     case op_StringFuncInfo:
674     case op_UnaryOpInfo:
675     case op_BinaryOpInfo:
676     case op_ListFuncInfo:
677         {
678             char *name;
679             switch (e->node_op) {
680             CASE_OP(op_Var);
681             CASE_OP(op_StringFuncInfo);
682             CASE_OP(op_UnaryOpInfo);
683             CASE_OP(op_BinaryOpInfo);
684             CASE_OP(op_ListFuncInfo);
685             default:
686                 ap_assert(0);
687             }
688             DUMP_P_P(name, e->node_arg1, e->node_arg2);
689         }
690         break;
691     /* arg1: pointer */
692     case op_Regex:
693         DUMP_P("op_Regex", e->node_arg1);
694         break;
695     /* arg1: pointer to int */
696     case op_RegexBackref:
697         DUMP_IP("op_RegexBackref", e->node_arg1);
698         break;
699     default:
700         ap_log_error(MARK, "%*sERROR: INVALID OP %d", indent, " ", e->node_op);
701         break;
702     }
703 }
704 #endif /* AP_EXPR_DEBUG */
705 
ap_expr_eval_unary_op(ap_expr_eval_ctx_t * ctx,const ap_expr_t * info,const ap_expr_t * arg)706 static int ap_expr_eval_unary_op(ap_expr_eval_ctx_t *ctx, const ap_expr_t *info,
707                                  const ap_expr_t *arg)
708 {
709     ap_expr_op_unary_t *op_func = (ap_expr_op_unary_t *)info->node_arg1;
710     const void *data = info->node_arg2;
711 
712     AP_DEBUG_ASSERT(info->node_op == op_UnaryOpInfo);
713     AP_DEBUG_ASSERT(op_func != NULL);
714     AP_DEBUG_ASSERT(data != NULL);
715     return (*op_func)(ctx, data, ap_expr_eval_word(ctx, arg));
716 }
717 
ap_expr_eval_binary_op(ap_expr_eval_ctx_t * ctx,const ap_expr_t * info,const ap_expr_t * args)718 static int ap_expr_eval_binary_op(ap_expr_eval_ctx_t *ctx,
719                                   const ap_expr_t *info,
720                                   const ap_expr_t *args)
721 {
722     ap_expr_op_binary_t *op_func = (ap_expr_op_binary_t *)info->node_arg1;
723     const void *data = info->node_arg2;
724     const ap_expr_t *a1 = args->node_arg1;
725     const ap_expr_t *a2 = args->node_arg2;
726 
727     AP_DEBUG_ASSERT(info->node_op == op_BinaryOpInfo);
728     AP_DEBUG_ASSERT(args->node_op == op_BinaryOpArgs);
729     AP_DEBUG_ASSERT(op_func != NULL);
730     AP_DEBUG_ASSERT(data != NULL);
731     return (*op_func)(ctx, data, ap_expr_eval_word(ctx, a1),
732                       ap_expr_eval_word(ctx, a2));
733 }
734 
735 
ap_expr_eval(ap_expr_eval_ctx_t * ctx,const ap_expr_t * node)736 static int ap_expr_eval(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
737 {
738     const ap_expr_t *e1 = node->node_arg1;
739     const ap_expr_t *e2 = node->node_arg2;
740     int result = FALSE;
741     if (inc_rec(ctx))
742         return result;
743     while (1) {
744         switch (node->node_op) {
745         case op_True:
746             result ^= TRUE;
747             goto out;
748         case op_False:
749             result ^= FALSE;
750             goto out;
751         case op_Not:
752             result = !result;
753             node = e1;
754             break;
755         case op_Or:
756             do {
757                 if (e1->node_op == op_Not) {
758                     if (!ap_expr_eval(ctx, e1->node_arg1)) {
759                         result ^= TRUE;
760                         goto out;
761                     }
762                 }
763                 else {
764                     if (ap_expr_eval(ctx, e1)) {
765                         result ^= TRUE;
766                         goto out;
767                     }
768                 }
769                 node = node->node_arg2;
770                 e1 = node->node_arg1;
771             } while (node->node_op == op_Or);
772             break;
773         case op_And:
774             do {
775                 if (e1->node_op == op_Not) {
776                     if (ap_expr_eval(ctx, e1->node_arg1)) {
777                         result ^= FALSE;
778                         goto out;
779                     }
780                 }
781                 else {
782                     if (!ap_expr_eval(ctx, e1)) {
783                         result ^= FALSE;
784                         goto out;
785                     }
786                 }
787                 node = node->node_arg2;
788                 e1 = node->node_arg1;
789             } while (node->node_op == op_And);
790             break;
791         case op_UnaryOpCall:
792             result ^= ap_expr_eval_unary_op(ctx, e1, e2);
793             goto out;
794         case op_BinaryOpCall:
795             result ^= ap_expr_eval_binary_op(ctx, e1, e2);
796             goto out;
797         case op_Comp:
798             if (ctx->info->flags & AP_EXPR_FLAG_SSL_EXPR_COMPAT)
799                 result ^= ssl_expr_eval_comp(ctx, e1);
800             else
801                 result ^= ap_expr_eval_comp(ctx, e1);
802             goto out;
803         default:
804             *ctx->err = "Internal evaluation error: Unknown expression node";
805             goto out;
806         }
807         e1 = node->node_arg1;
808         e2 = node->node_arg2;
809     }
810 out:
811     ctx->reclvl--;
812     return result;
813 }
814 
ap_expr_exec(request_rec * r,const ap_expr_info_t * info,const char ** err)815 AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *info,
816                              const char **err)
817 {
818     return ap_expr_exec_re(r, info, 0, NULL, NULL, err);
819 }
820 
ap_expr_exec_ctx(ap_expr_eval_ctx_t * ctx)821 AP_DECLARE(int) ap_expr_exec_ctx(ap_expr_eval_ctx_t *ctx)
822 {
823     int rc;
824 
825     AP_DEBUG_ASSERT(ctx->p != NULL);
826     /* XXX: allow r, c == NULL */
827     AP_DEBUG_ASSERT(ctx->r != NULL);
828     AP_DEBUG_ASSERT(ctx->c != NULL);
829     AP_DEBUG_ASSERT(ctx->s != NULL);
830     AP_DEBUG_ASSERT(ctx->err != NULL);
831     AP_DEBUG_ASSERT(ctx->info != NULL);
832     if (ctx->re_pmatch) {
833         AP_DEBUG_ASSERT(ctx->re_source != NULL);
834         AP_DEBUG_ASSERT(ctx->re_nmatch > 0);
835     }
836     ctx->reclvl = 0;
837 
838     *ctx->err = NULL;
839     if (ctx->info->flags & AP_EXPR_FLAG_STRING_RESULT) {
840         *ctx->result_string = ap_expr_eval_word(ctx, ctx->info->root_node);
841         if (*ctx->err != NULL) {
842             ap_log_rerror(LOG_MARK(ctx->info), APLOG_ERR, 0, ctx->r,
843                           "Evaluation of expression from %s:%d failed: %s",
844                           ctx->info->filename, ctx->info->line_number, *ctx->err);
845             return -1;
846         } else {
847             ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE4, 0, ctx->r,
848                           "Evaluation of string expression from %s:%d gave: %s",
849                           ctx->info->filename, ctx->info->line_number,
850                           *ctx->result_string);
851             return 1;
852         }
853     }
854     else {
855         rc = ap_expr_eval(ctx, ctx->info->root_node);
856         if (*ctx->err != NULL) {
857             ap_log_rerror(LOG_MARK(ctx->info), APLOG_ERR, 0, ctx->r,
858                           "Evaluation of expression from %s:%d failed: %s",
859                           ctx->info->filename, ctx->info->line_number, *ctx->err);
860             return -1;
861         } else {
862             rc = rc ? 1 : 0;
863             ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE4, 0, ctx->r,
864                           "Evaluation of expression from %s:%d gave: %d",
865                           ctx->info->filename, ctx->info->line_number, rc);
866 
867             if (ctx->vary_this && *ctx->vary_this)
868                 apr_table_merge(ctx->r->headers_out, "Vary", *ctx->vary_this);
869 
870             return rc;
871         }
872     }
873 }
874 
ap_expr_exec_re(request_rec * r,const ap_expr_info_t * info,apr_size_t nmatch,ap_regmatch_t * pmatch,const char ** source,const char ** err)875 AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
876                                 apr_size_t nmatch, ap_regmatch_t *pmatch,
877                                 const char **source, const char **err)
878 {
879     ap_expr_eval_ctx_t ctx;
880     int dont_vary = (info->flags & AP_EXPR_FLAG_DONT_VARY);
881     const char *tmp_source = NULL, *vary_this = NULL;
882     ap_regmatch_t tmp_pmatch[AP_MAX_REG_MATCH];
883 
884     AP_DEBUG_ASSERT((info->flags & AP_EXPR_FLAG_STRING_RESULT) == 0);
885 
886     ctx.r = r;
887     ctx.c = r->connection;
888     ctx.s = r->server;
889     ctx.p = r->pool;
890     ctx.err  = err;
891     ctx.info = info;
892     ctx.re_nmatch = nmatch;
893     ctx.re_pmatch = pmatch;
894     ctx.re_source = source;
895     ctx.vary_this = dont_vary ? NULL : &vary_this;
896     ctx.data = NULL;
897 
898     if (!pmatch) {
899         ctx.re_nmatch = AP_MAX_REG_MATCH;
900         ctx.re_pmatch = tmp_pmatch;
901         ctx.re_source = &tmp_source;
902     }
903 
904     return ap_expr_exec_ctx(&ctx);
905 }
906 
ap_expr_str_exec_re(request_rec * r,const ap_expr_info_t * info,apr_size_t nmatch,ap_regmatch_t * pmatch,const char ** source,const char ** err)907 AP_DECLARE(const char *) ap_expr_str_exec_re(request_rec *r,
908                                              const ap_expr_info_t *info,
909                                              apr_size_t nmatch,
910                                              ap_regmatch_t *pmatch,
911                                              const char **source,
912                                              const char **err)
913 {
914     ap_expr_eval_ctx_t ctx;
915     int dont_vary, rc;
916     const char *tmp_source, *vary_this;
917     ap_regmatch_t tmp_pmatch[AP_MAX_REG_MATCH];
918     const char *result;
919 
920     AP_DEBUG_ASSERT(info->flags & AP_EXPR_FLAG_STRING_RESULT);
921 
922     if (info->root_node->node_op == op_String) {
923         /* short-cut for constant strings */
924         *err = NULL;
925         return (const char *)info->root_node->node_arg1;
926     }
927 
928     tmp_source = NULL;
929     vary_this = NULL;
930 
931     dont_vary = (info->flags & AP_EXPR_FLAG_DONT_VARY);
932 
933     ctx.r = r;
934     ctx.c = r->connection;
935     ctx.s = r->server;
936     ctx.p = r->pool;
937     ctx.err  = err;
938     ctx.info = info;
939     ctx.re_nmatch = nmatch;
940     ctx.re_pmatch = pmatch;
941     ctx.re_source = source;
942     ctx.vary_this = dont_vary ? NULL : &vary_this;
943     ctx.data = NULL;
944     ctx.result_string = &result;
945 
946     if (!pmatch) {
947         ctx.re_nmatch = AP_MAX_REG_MATCH;
948         ctx.re_pmatch = tmp_pmatch;
949         ctx.re_source = &tmp_source;
950     }
951 
952     rc = ap_expr_exec_ctx(&ctx);
953     if (rc > 0)
954         return result;
955     else if (rc < 0)
956         return NULL;
957     else
958         ap_assert(0);
959     /* Not reached */
960     return NULL;
961 }
962 
ap_expr_str_exec(request_rec * r,const ap_expr_info_t * info,const char ** err)963 AP_DECLARE(const char *) ap_expr_str_exec(request_rec *r,
964                                           const ap_expr_info_t *info,
965                                           const char **err)
966 {
967     return ap_expr_str_exec_re(r, info, 0, NULL, NULL, err);
968 }
969 
970 
add_vary(ap_expr_eval_ctx_t * ctx,const char * name)971 static void add_vary(ap_expr_eval_ctx_t *ctx, const char *name)
972 {
973     if (!ctx->vary_this)
974         return;
975 
976     if (*ctx->vary_this) {
977         *ctx->vary_this = apr_pstrcat(ctx->p, *ctx->vary_this, ", ", name,
978                                       NULL);
979     }
980     else {
981         *ctx->vary_this = name;
982     }
983 }
984 
req_table_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)985 static const char *req_table_func(ap_expr_eval_ctx_t *ctx, const void *data,
986                                   const char *arg)
987 {
988     const char *name = (const char *)data;
989     apr_table_t *t;
990     if (!ctx->r)
991         return "";
992 
993     if (name[2] == 's') {           /* resp */
994         /* Try r->headers_out first, fall back on err_headers_out. */
995         const char *v = apr_table_get(ctx->r->headers_out, arg);
996         if (v) {
997             return v;
998         }
999         t = ctx->r->err_headers_out;
1000     }
1001     else if (name[0] == 'n')        /* notes */
1002         t = ctx->r->notes;
1003     else if (name[3] == 'e')        /* reqenv */
1004         t = ctx->r->subprocess_env;
1005     else if (name[3] == '_')        /* req_novary */
1006         t = ctx->r->headers_in;
1007     else {                          /* req, http */
1008         t = ctx->r->headers_in;
1009         /* Skip the 'Vary: Host' header combination
1010          * as indicated in rfc7231 section-7.1.4
1011          */
1012         if (strcasecmp(arg, "Host")){
1013             add_vary(ctx, arg);
1014         }
1015     }
1016     return apr_table_get(t, arg);
1017 }
1018 
env_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1019 static const char *env_func(ap_expr_eval_ctx_t *ctx, const void *data,
1020                             const char *arg)
1021 {
1022     const char *res;
1023     /* this order is for ssl_expr compatibility */
1024     if (ctx->r) {
1025         if ((res = apr_table_get(ctx->r->notes, arg)) != NULL)
1026             return res;
1027         else if ((res = apr_table_get(ctx->r->subprocess_env, arg)) != NULL)
1028             return res;
1029     }
1030     return getenv(arg);
1031 }
1032 
osenv_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1033 static const char *osenv_func(ap_expr_eval_ctx_t *ctx, const void *data,
1034                               const char *arg)
1035 {
1036     return getenv(arg);
1037 }
1038 
tolower_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1039 static const char *tolower_func(ap_expr_eval_ctx_t *ctx, const void *data,
1040                                 const char *arg)
1041 {
1042     char *result = apr_pstrdup(ctx->p, arg);
1043     ap_str_tolower(result);
1044     return result;
1045 }
1046 
toupper_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1047 static const char *toupper_func(ap_expr_eval_ctx_t *ctx, const void *data,
1048                                 const char *arg)
1049 {
1050     char *result = apr_pstrdup(ctx->p, arg);
1051     ap_str_toupper(result);
1052     return result;
1053 }
1054 
escape_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1055 static const char *escape_func(ap_expr_eval_ctx_t *ctx, const void *data,
1056                                const char *arg)
1057 {
1058     return ap_escape_uri(ctx->p, arg);
1059 }
1060 
base64_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1061 static const char *base64_func(ap_expr_eval_ctx_t *ctx, const void *data,
1062                                const char *arg)
1063 {
1064     return ap_pbase64encode(ctx->p, (char *)arg);
1065 }
1066 
unbase64_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1067 static const char *unbase64_func(ap_expr_eval_ctx_t *ctx, const void *data,
1068                                const char *arg)
1069 {
1070     return ap_pbase64decode(ctx->p, arg);
1071 }
1072 
sha1_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1073 static const char *sha1_func(ap_expr_eval_ctx_t *ctx, const void *data,
1074                                const char *arg)
1075 {
1076     apr_sha1_ctx_t context;
1077     apr_byte_t sha1[APR_SHA1_DIGESTSIZE];
1078     char *out;
1079 
1080     out = apr_palloc(ctx->p, APR_SHA1_DIGESTSIZE*2+1);
1081 
1082     apr_sha1_init(&context);
1083     apr_sha1_update(&context, arg, (unsigned int)strlen(arg));
1084     apr_sha1_final(sha1, &context);
1085 
1086     ap_bin2hex(sha1, APR_SHA1_DIGESTSIZE, out);
1087 
1088     return out;
1089 }
1090 
md5_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1091 static const char *md5_func(ap_expr_eval_ctx_t *ctx, const void *data,
1092                                const char *arg)
1093 {
1094     return ap_md5(ctx->p, (const unsigned char *)arg);
1095 }
1096 
1097 #if APR_VERSION_AT_LEAST(1,6,0)
ldap_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1098 static const char *ldap_func(ap_expr_eval_ctx_t *ctx, const void *data,
1099                                const char *arg)
1100 {
1101     return apr_pescape_ldap(ctx->p, arg, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_ALL);
1102 }
1103 #endif
1104 
1105 #define MAX_FILE_SIZE 10*1024*1024
file_func(ap_expr_eval_ctx_t * ctx,const void * data,char * arg)1106 static const char *file_func(ap_expr_eval_ctx_t *ctx, const void *data,
1107                              char *arg)
1108 {
1109     apr_file_t *fp;
1110     char *buf;
1111     apr_off_t offset;
1112     apr_size_t len;
1113     apr_finfo_t finfo;
1114 
1115     if (apr_file_open(&fp, arg, APR_READ|APR_BUFFERED,
1116                       APR_OS_DEFAULT, ctx->p) != APR_SUCCESS) {
1117         *ctx->err = apr_psprintf(ctx->p, "Cannot open file %s", arg);
1118         return "";
1119     }
1120     apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
1121     if (finfo.size > MAX_FILE_SIZE) {
1122         *ctx->err = apr_psprintf(ctx->p, "File %s too large", arg);
1123         apr_file_close(fp);
1124         return "";
1125     }
1126     len = (apr_size_t)finfo.size;
1127     if (len == 0) {
1128         apr_file_close(fp);
1129         return "";
1130     }
1131     else {
1132         if ((buf = (char *)apr_palloc(ctx->p, sizeof(char)*(len+1))) == NULL) {
1133             *ctx->err = "Cannot allocate memory";
1134             apr_file_close(fp);
1135             return "";
1136         }
1137         offset = 0;
1138         apr_file_seek(fp, APR_SET, &offset);
1139         if (apr_file_read(fp, buf, &len) != APR_SUCCESS) {
1140             *ctx->err = apr_psprintf(ctx->p, "Cannot read from file %s", arg);
1141             apr_file_close(fp);
1142             return "";
1143         }
1144         buf[len] = '\0';
1145     }
1146     apr_file_close(fp);
1147     return buf;
1148 }
1149 
filesize_func(ap_expr_eval_ctx_t * ctx,const void * data,char * arg)1150 static const char *filesize_func(ap_expr_eval_ctx_t *ctx, const void *data,
1151                                   char *arg)
1152 {
1153     apr_finfo_t sb;
1154     if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) == APR_SUCCESS
1155         && sb.filetype == APR_REG && sb.size > 0)
1156         return apr_psprintf(ctx->p, "%" APR_OFF_T_FMT, sb.size);
1157     else
1158         return "0";
1159 }
1160 
unescape_func(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1161 static const char *unescape_func(ap_expr_eval_ctx_t *ctx, const void *data,
1162                                  const char *arg)
1163 {
1164     char *result = apr_pstrdup(ctx->p, arg);
1165     int ret = ap_unescape_url_keep2f(result, 0);
1166     if (ret == OK)
1167         return result;
1168     ap_log_rerror(LOG_MARK(ctx->info), APLOG_DEBUG, 0, ctx->r, APLOGNO(00538)
1169                   "%s %% escape in unescape('%s') at %s:%d",
1170                   ret == HTTP_BAD_REQUEST ? "Bad" : "Forbidden", arg,
1171                   ctx->info->filename, ctx->info->line_number);
1172     return "";
1173 }
1174 
op_nz(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1175 static int op_nz(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1176 {
1177     const char *name = (const char *)data;
1178     if (name[0] == 'z')
1179         return (arg[0] == '\0');
1180     else
1181         return (arg[0] != '\0');
1182 }
1183 
op_file_min(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1184 static int op_file_min(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1185 {
1186     apr_finfo_t sb;
1187     const char *name = (const char *)data;
1188     if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) != APR_SUCCESS)
1189         return FALSE;
1190     switch (name[0]) {
1191     case 'd':
1192         return (sb.filetype == APR_DIR);
1193     case 'e':
1194         return TRUE;
1195     case 'f':
1196         return (sb.filetype == APR_REG);
1197     case 's':
1198         return (sb.filetype == APR_REG && sb.size > 0);
1199     default:
1200         ap_assert(0);
1201     }
1202     return FALSE;
1203 }
1204 
op_file_link(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1205 static int op_file_link(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1206 {
1207 #if !defined(OS2)
1208     apr_finfo_t sb;
1209     if (apr_stat(&sb, arg, APR_FINFO_MIN | APR_FINFO_LINK, ctx->p) == APR_SUCCESS
1210         && sb.filetype == APR_LNK) {
1211         return TRUE;
1212     }
1213 #endif
1214     return FALSE;
1215 }
1216 
op_file_xbit(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1217 static int op_file_xbit(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1218 {
1219     apr_finfo_t sb;
1220     if (apr_stat(&sb, arg, APR_FINFO_PROT| APR_FINFO_LINK, ctx->p) == APR_SUCCESS
1221         && (sb.protection & (APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE))) {
1222         return TRUE;
1223     }
1224     return FALSE;
1225 }
1226 
op_url_subr(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1227 static int op_url_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1228 {
1229     int rc = FALSE;
1230     request_rec  *rsub, *r = ctx->r;
1231     if (!r)
1232         return FALSE;
1233     /* avoid some infinite recursions */
1234     if (r->main && r->main->uri && r->uri && strcmp(r->main->uri, r->uri) == 0)
1235         return FALSE;
1236 
1237     rsub = ap_sub_req_lookup_uri(arg, r, NULL);
1238     if (rsub->status < 400) {
1239             rc = TRUE;
1240     }
1241     ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE5, 0, r,
1242                   "Subrequest for -U %s at %s:%d gave status: %d",
1243                   arg, ctx->info->filename, ctx->info->line_number,
1244                   rsub->status);
1245     ap_destroy_sub_req(rsub);
1246     return rc;
1247 }
1248 
op_file_subr(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1249 static int op_file_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1250 {
1251     int rc = FALSE;
1252     apr_finfo_t sb;
1253     request_rec *rsub, *r = ctx->r;
1254     if (!r)
1255         return FALSE;
1256     rsub = ap_sub_req_lookup_file(arg, r, NULL);
1257     if (rsub->status < 300 &&
1258         /* double-check that file exists since default result is 200 */
1259         apr_stat(&sb, rsub->filename, APR_FINFO_MIN, ctx->p) == APR_SUCCESS) {
1260         rc = TRUE;
1261     }
1262     ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE5, 0, r,
1263                   "Subrequest for -F %s at %s:%d gave status: %d",
1264                   arg, ctx->info->filename, ctx->info->line_number,
1265                   rsub->status);
1266     ap_destroy_sub_req(rsub);
1267     return rc;
1268 }
1269 
1270 
1271 APR_DECLARE_OPTIONAL_FN(int, http2_is_h2, (conn_rec *));
1272 static APR_OPTIONAL_FN_TYPE(http2_is_h2) *is_http2 = NULL;
1273 
1274 static const char *conn_var_names[] = {
1275     "HTTPS",                    /*  0 */
1276     "IPV6",                     /*  1 */
1277     "CONN_LOG_ID",              /*  2 */
1278     "CONN_REMOTE_ADDR",         /*  3 */
1279     "HTTP2",                    /*  4 */
1280     NULL
1281 };
1282 
conn_var_fn(ap_expr_eval_ctx_t * ctx,const void * data)1283 static const char *conn_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1284 {
1285     int index = ((const char **)data - conn_var_names);
1286     conn_rec *c = ctx->c;
1287     if (!c)
1288         return "";
1289 
1290     switch (index) {
1291     case 0:
1292         if (ap_ssl_conn_is_ssl(c))
1293             return "on";
1294         else
1295             return "off";
1296     case 1:
1297 #if APR_HAVE_IPV6
1298         {
1299             apr_sockaddr_t *addr = c->client_addr;
1300             if (addr->family == AF_INET6
1301                 && !IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr))
1302                 return "on";
1303             else
1304                 return "off";
1305         }
1306 #else
1307         return "off";
1308 #endif
1309     case 2:
1310         return c->log_id;
1311     case 3:
1312         return c->client_ip;
1313     case 4:
1314         if (is_http2 && is_http2(c))
1315             return "on";
1316         else
1317             return "off";
1318     default:
1319         ap_assert(0);
1320         return NULL;
1321     }
1322 }
1323 
1324 static const char *request_var_names[] = {
1325     "REQUEST_METHOD",           /*  0 */
1326     "REQUEST_SCHEME",           /*  1 */
1327     "REQUEST_URI",              /*  2 */
1328     "REQUEST_FILENAME",         /*  3 */
1329     "REMOTE_HOST",              /*  4 */
1330     "REMOTE_IDENT",             /*  5 */
1331     "REMOTE_USER",              /*  6 */
1332     "SERVER_ADMIN",             /*  7 */
1333     "SERVER_NAME",              /*  8 */
1334     "SERVER_PORT",              /*  9 */
1335     "SERVER_PROTOCOL",          /* 10 */
1336     "SCRIPT_FILENAME",          /* 11 */
1337     "PATH_INFO",                /* 12 */
1338     "QUERY_STRING",             /* 13 */
1339     "IS_SUBREQ",                /* 14 */
1340     "DOCUMENT_ROOT",            /* 15 */
1341     "AUTH_TYPE",                /* 16 */
1342     "THE_REQUEST",              /* 17 */
1343     "CONTENT_TYPE",             /* 18 */
1344     "HANDLER",                  /* 19 */
1345     "REQUEST_LOG_ID",           /* 20 */
1346     "SCRIPT_USER",              /* 21 */
1347     "SCRIPT_GROUP",             /* 22 */
1348     "DOCUMENT_URI",             /* 23 */
1349     "LAST_MODIFIED",            /* 24 */
1350     "CONTEXT_PREFIX",           /* 25 */
1351     "CONTEXT_DOCUMENT_ROOT",    /* 26 */
1352     "REQUEST_STATUS",           /* 27 */
1353     "REMOTE_ADDR",              /* 28 */
1354     "REMOTE_PORT",              /* 29 */
1355     NULL
1356 };
1357 
request_var_fn(ap_expr_eval_ctx_t * ctx,const void * data)1358 static const char *request_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1359 {
1360     int index = ((const char **)data - request_var_names);
1361     request_rec *r = ctx->r;
1362     if (!r)
1363         return "";
1364 
1365     switch (index) {
1366     case 0:
1367         return r->method;
1368     case 1:
1369         return ap_http_scheme(r);
1370     case 2:
1371         return r->uri;
1372     case 3:
1373         return r->filename;
1374     case 4:
1375         return ap_get_useragent_host(r, REMOTE_NAME, NULL);
1376     case 5:
1377         return ap_get_remote_logname(r);
1378     case 6:
1379         return r->user;
1380     case 7:
1381         return r->server->server_admin;
1382     case 8:
1383         return ap_get_server_name_for_url(r);
1384     case 9:
1385         return apr_psprintf(ctx->p, "%u", ap_get_server_port(r));
1386     case 10:
1387         return r->protocol;
1388     case 11:
1389         return r->filename;
1390     case 12:
1391         return r->path_info;
1392     case 13:
1393         return r->args;
1394     case 14:
1395         return (r->main != NULL ? "true" : "false");
1396     case 15:
1397         return ap_document_root(r);
1398     case 16:
1399         return r->ap_auth_type;
1400     case 17:
1401         return r->the_request;
1402     case 18:
1403         return r->content_type;
1404     case 19:
1405         return r->handler;
1406     case 20:
1407         return r->log_id;
1408     case 21:
1409         {
1410             char *result = "";
1411             if (r->finfo.valid & APR_FINFO_USER)
1412                 apr_uid_name_get(&result, r->finfo.user, ctx->p);
1413             return result;
1414         }
1415     case 22:
1416         {
1417             char *result = "";
1418             if (r->finfo.valid & APR_FINFO_USER)
1419                 apr_gid_name_get(&result, r->finfo.group, ctx->p);
1420             return result;
1421         }
1422     case 23:
1423         {
1424             const char *uri = apr_table_get(r->subprocess_env, "DOCUMENT_URI");
1425             return uri ? uri : r->uri;
1426         }
1427     case 24:
1428         {
1429             apr_time_exp_t tm;
1430             apr_time_exp_lt(&tm, r->mtime);
1431             return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
1432                                 (tm.tm_year / 100) + 19, (tm.tm_year % 100),
1433                                 tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
1434                                 tm.tm_sec);
1435         }
1436     case 25:
1437         return ap_context_prefix(r);
1438     case 26:
1439         return ap_context_document_root(r);
1440     case 27:
1441         return r->status ? apr_psprintf(ctx->p, "%d", r->status) : "";
1442     case 28:
1443         return r->useragent_ip;
1444     case 29:
1445         return apr_psprintf(ctx->p, "%u", ctx->c->client_addr->port);
1446     default:
1447         ap_assert(0);
1448         return NULL;
1449     }
1450 }
1451 
1452 static const char *req_header_var_names[] = {
1453     "HTTP_USER_AGENT",       /* 0 */
1454     "HTTP_PROXY_CONNECTION", /* 1 */
1455     "HTTP_REFERER",          /* 2 */
1456     "HTTP_COOKIE",           /* 3 */
1457     "HTTP_FORWARDED",        /* 4 */
1458     "HTTP_HOST",             /* 5 */
1459     "HTTP_ACCEPT",           /* 6 */
1460     NULL
1461 };
1462 
1463 static const char *req_header_header_names[] = {
1464     "User-Agent",
1465     "Proxy-Connection",
1466     "Referer",
1467     "Cookie",
1468     "Forwarded",
1469     "Host",
1470     "Accept"
1471 };
1472 
req_header_var_fn(ap_expr_eval_ctx_t * ctx,const void * data)1473 static const char *req_header_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1474 {
1475     const char **varname = (const char **)data;
1476     int index = (varname - req_header_var_names);
1477     const char *name;
1478 
1479     AP_DEBUG_ASSERT(index < 7);
1480     if (!ctx->r)
1481         return "";
1482 
1483     name = req_header_header_names[index];
1484     /* Skip the 'Vary: Host' header combination
1485      * as indicated in rfc7231 section-7.1.4
1486      */
1487     if (strcasecmp(name, "Host")){
1488         add_vary(ctx, name);
1489     }
1490     return apr_table_get(ctx->r->headers_in, name);
1491 }
1492 
1493 static const char *misc_var_names[] = {
1494     "TIME_YEAR",        /* 0 */
1495     "TIME_MON",         /* 1 */
1496     "TIME_DAY",         /* 2 */
1497     "TIME_HOUR",        /* 3 */
1498     "TIME_MIN",         /* 4 */
1499     "TIME_SEC",         /* 5 */
1500     "TIME_WDAY",        /* 6 */
1501     "TIME",             /* 7 */
1502     "SERVER_SOFTWARE",  /* 8 */
1503     "API_VERSION",      /* 9 */
1504     NULL
1505 };
1506 
misc_var_fn(ap_expr_eval_ctx_t * ctx,const void * data)1507 static const char *misc_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1508 {
1509     apr_time_exp_t tm;
1510     int index = ((const char **)data - misc_var_names);
1511     apr_time_exp_lt(&tm, apr_time_now());
1512 
1513     switch (index) {
1514     case 0:
1515         return apr_psprintf(ctx->p, "%02d%02d", (tm.tm_year / 100) + 19,
1516                             tm.tm_year % 100);
1517     case 1:
1518         return apr_psprintf(ctx->p, "%02d", tm.tm_mon+1);
1519     case 2:
1520         return apr_psprintf(ctx->p, "%02d", tm.tm_mday);
1521     case 3:
1522         return apr_psprintf(ctx->p, "%02d", tm.tm_hour);
1523     case 4:
1524         return apr_psprintf(ctx->p, "%02d", tm.tm_min);
1525     case 5:
1526         return apr_psprintf(ctx->p, "%02d", tm.tm_sec);
1527     case 6:
1528         return apr_psprintf(ctx->p, "%d", tm.tm_wday);
1529     case 7:
1530         return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
1531                             (tm.tm_year / 100) + 19, (tm.tm_year % 100),
1532                             tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
1533                             tm.tm_sec);
1534     case 8:
1535         return ap_get_server_banner();
1536     case 9:
1537         return apr_itoa(ctx->p, MODULE_MAGIC_NUMBER_MAJOR);
1538     default:
1539         ap_assert(0);
1540     }
1541 
1542     return NULL;
1543 }
1544 
subnet_parse_arg(ap_expr_lookup_parms * parms)1545 static int subnet_parse_arg(ap_expr_lookup_parms *parms)
1546 {
1547     apr_ipsubnet_t *subnet;
1548     const char *addr = parms->arg;
1549     const char *mask;
1550     apr_status_t ret;
1551 
1552     if (!parms->arg) {
1553         *parms->err = apr_psprintf(parms->ptemp,
1554                                    "-%s requires subnet/netmask as constant argument",
1555                                    parms->name);
1556         return !OK;
1557     }
1558 
1559     mask = ap_strchr_c(addr, '/');
1560     if (mask) {
1561         addr = apr_pstrmemdup(parms->ptemp, addr, mask - addr);
1562         mask++;
1563     }
1564 
1565     ret = apr_ipsubnet_create(&subnet, addr, mask, parms->pool);
1566     if (ret != APR_SUCCESS) {
1567         *parms->err = "parsing of subnet/netmask failed";
1568         return !OK;
1569     }
1570 
1571     *parms->data = subnet;
1572     return OK;
1573 }
1574 
op_ipmatch(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg1,const char * arg2)1575 static int op_ipmatch(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg1,
1576                 const char *arg2)
1577 {
1578     apr_ipsubnet_t *subnet = (apr_ipsubnet_t *)data;
1579     apr_sockaddr_t *saddr;
1580 
1581     AP_DEBUG_ASSERT(subnet != NULL);
1582 
1583     /* maybe log an error if this goes wrong? */
1584     if (apr_sockaddr_info_get(&saddr, arg1, APR_UNSPEC, 0, 0, ctx->p) != APR_SUCCESS)
1585         return FALSE;
1586 
1587     return apr_ipsubnet_test(subnet, saddr);
1588 }
1589 
op_R(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg1)1590 static int op_R(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg1)
1591 {
1592     apr_ipsubnet_t *subnet = (apr_ipsubnet_t *)data;
1593 
1594     AP_DEBUG_ASSERT(subnet != NULL);
1595 
1596     if (!ctx->r)
1597         return FALSE;
1598 
1599     return apr_ipsubnet_test(subnet, ctx->r->useragent_addr);
1600 }
1601 
op_T(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg)1602 static int op_T(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1603 {
1604     switch (arg[0]) {
1605     case '\0':
1606         return FALSE;
1607     case 'o':
1608     case 'O':
1609         return strcasecmp(arg, "off") == 0 ? FALSE : TRUE;
1610     case 'n':
1611     case 'N':
1612         return strcasecmp(arg, "no") == 0 ? FALSE : TRUE;
1613     case 'f':
1614     case 'F':
1615         return strcasecmp(arg, "false") == 0 ? FALSE : TRUE;
1616     case '0':
1617         return arg[1] == '\0' ? FALSE : TRUE;
1618     default:
1619         return TRUE;
1620     }
1621 }
1622 
op_fnmatch(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg1,const char * arg2)1623 static int op_fnmatch(ap_expr_eval_ctx_t *ctx, const void *data,
1624                       const char *arg1, const char *arg2)
1625 {
1626     return (APR_SUCCESS == apr_fnmatch(arg2, arg1, APR_FNM_PATHNAME));
1627 }
1628 
op_strmatch(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg1,const char * arg2)1629 static int op_strmatch(ap_expr_eval_ctx_t *ctx, const void *data,
1630                        const char *arg1, const char *arg2)
1631 {
1632     return (APR_SUCCESS == apr_fnmatch(arg2, arg1, 0));
1633 }
1634 
op_strcmatch(ap_expr_eval_ctx_t * ctx,const void * data,const char * arg1,const char * arg2)1635 static int op_strcmatch(ap_expr_eval_ctx_t *ctx, const void *data,
1636                         const char *arg1, const char *arg2)
1637 {
1638     return (APR_SUCCESS == apr_fnmatch(arg2, arg1, APR_FNM_CASE_BLIND));
1639 }
1640 
1641 struct expr_provider_single {
1642     const void *func;
1643     const char *name;
1644     ap_expr_lookup_fn_t *arg_parsing_func;
1645     int restricted;
1646 };
1647 
1648 struct expr_provider_multi {
1649     const void *func;
1650     const char **names;
1651 };
1652 
1653 static const struct expr_provider_multi var_providers[] = {
1654     { misc_var_fn, misc_var_names },
1655     { req_header_var_fn, req_header_var_names },
1656     { request_var_fn, request_var_names },
1657     { conn_var_fn, conn_var_names },
1658     { NULL, NULL }
1659 };
1660 
1661 static const struct expr_provider_single string_func_providers[] = {
1662     { osenv_func,           "osenv",          NULL, 0 },
1663     { env_func,             "env",            NULL, 0 },
1664     { req_table_func,       "resp",           NULL, 0 },
1665     { req_table_func,       "req",            NULL, 0 },
1666     /* 'http' as alias for 'req' for compatibility with ssl_expr */
1667     { req_table_func,       "http",           NULL, 0 },
1668     { req_table_func,       "note",           NULL, 0 },
1669     { req_table_func,       "reqenv",         NULL, 0 },
1670     { req_table_func,       "req_novary",     NULL, 0 },
1671     { tolower_func,         "tolower",        NULL, 0 },
1672     { toupper_func,         "toupper",        NULL, 0 },
1673     { escape_func,          "escape",         NULL, 0 },
1674     { unescape_func,        "unescape",       NULL, 0 },
1675     { file_func,            "file",           NULL, 1 },
1676     { filesize_func,        "filesize",       NULL, 1 },
1677     { base64_func,          "base64",         NULL, 0 },
1678     { unbase64_func,        "unbase64",       NULL, 0 },
1679     { sha1_func,            "sha1",           NULL, 0 },
1680     { md5_func,             "md5",            NULL, 0 },
1681 #if APR_VERSION_AT_LEAST(1,6,0)
1682     { ldap_func,            "ldap",           NULL, 0 },
1683 #endif
1684     { NULL, NULL, NULL}
1685 };
1686 
1687 static const struct expr_provider_single unary_op_providers[] = {
1688     { op_nz,        "n", NULL,             0 },
1689     { op_nz,        "z", NULL,             0 },
1690     { op_R,         "R", subnet_parse_arg, 0 },
1691     { op_T,         "T", NULL,             0 },
1692     { op_file_min,  "d", NULL,             1 },
1693     { op_file_min,  "e", NULL,             1 },
1694     { op_file_min,  "f", NULL,             1 },
1695     { op_file_min,  "s", NULL,             1 },
1696     { op_file_link, "L", NULL,             1 },
1697     { op_file_link, "h", NULL,             1 },
1698     { op_file_xbit, "x", NULL,             1 },
1699     { op_file_subr, "F", NULL,             0 },
1700     { op_url_subr,  "U", NULL,             0 },
1701     { op_url_subr,  "A", NULL,             0 },
1702     { NULL, NULL, NULL }
1703 };
1704 
1705 static const struct expr_provider_single binary_op_providers[] = {
1706     { op_ipmatch,   "ipmatch",      subnet_parse_arg, 0 },
1707     { op_fnmatch,   "fnmatch",      NULL,             0 },
1708     { op_strmatch,  "strmatch",     NULL,             0 },
1709     { op_strcmatch, "strcmatch",    NULL,             0 },
1710     { NULL, NULL, NULL }
1711 };
1712 
core_expr_lookup(ap_expr_lookup_parms * parms)1713 static int core_expr_lookup(ap_expr_lookup_parms *parms)
1714 {
1715     switch (parms->type) {
1716     case AP_EXPR_FUNC_VAR: {
1717             const struct expr_provider_multi *prov = var_providers;
1718             while (prov->func) {
1719                 const char **name = prov->names;
1720                 while (*name) {
1721                     if (ap_cstr_casecmp(*name, parms->name) == 0) {
1722                         *parms->func = prov->func;
1723                         *parms->data = name;
1724                         return OK;
1725                     }
1726                     name++;
1727                 }
1728                 prov++;
1729             }
1730         }
1731         break;
1732     case AP_EXPR_FUNC_STRING:
1733     case AP_EXPR_FUNC_OP_UNARY:
1734     case AP_EXPR_FUNC_OP_BINARY: {
1735             const struct expr_provider_single *prov = NULL;
1736             switch (parms->type) {
1737             case AP_EXPR_FUNC_STRING:
1738                 prov = string_func_providers;
1739                 break;
1740             case AP_EXPR_FUNC_OP_UNARY:
1741                 prov = unary_op_providers;
1742                 break;
1743             case AP_EXPR_FUNC_OP_BINARY:
1744                 prov = binary_op_providers;
1745                 break;
1746             default:
1747                 ap_assert(0);
1748             }
1749             while (prov && prov->func) {
1750                 int match;
1751                 if (parms->type == AP_EXPR_FUNC_OP_UNARY)
1752                     match = !strcmp(prov->name, parms->name);
1753                 else
1754                     match = !ap_cstr_casecmp(prov->name, parms->name);
1755                 if (match) {
1756                     if ((parms->flags & AP_EXPR_FLAG_RESTRICTED)
1757                         && prov->restricted) {
1758                         *parms->err =
1759                             apr_psprintf(parms->ptemp,
1760                                          "%s%s not available in restricted context",
1761                                          (parms->type == AP_EXPR_FUNC_STRING) ? "" : "-",
1762                                          prov->name);
1763                         return !OK;
1764                     }
1765                     *parms->func = prov->func;
1766                     if (prov->arg_parsing_func) {
1767                         return prov->arg_parsing_func(parms);
1768                     }
1769                     else {
1770                         *parms->data = prov->name;
1771                         return OK;
1772                     }
1773                 }
1774                 prov++;
1775             }
1776         }
1777         break;
1778     default:
1779         break;
1780     }
1781     return DECLINED;
1782 }
1783 
expr_lookup_not_found(ap_expr_lookup_parms * parms)1784 static int expr_lookup_not_found(ap_expr_lookup_parms *parms)
1785 {
1786     const char *type;
1787     const char *prefix = "";
1788 
1789     switch (parms->type) {
1790     case AP_EXPR_FUNC_VAR:
1791         type = "Variable";
1792         break;
1793     case AP_EXPR_FUNC_STRING:
1794         type = "Function";
1795         break;
1796     case AP_EXPR_FUNC_LIST:
1797         type = "List-returning function";
1798         break;
1799     case AP_EXPR_FUNC_OP_UNARY:
1800         type = "Unary operator";
1801         break;
1802     case AP_EXPR_FUNC_OP_BINARY:
1803         type = "Binary operator";
1804         break;
1805     default:
1806         *parms->err = "Invalid expression type in expr_lookup";
1807         return !OK;
1808     }
1809     if (   parms->type == AP_EXPR_FUNC_OP_UNARY
1810         || parms->type == AP_EXPR_FUNC_OP_BINARY) {
1811         prefix = "-";
1812     }
1813     *parms->err = apr_psprintf(parms->ptemp, "%s '%s%s' does not exist", type,
1814                                prefix, parms->name);
1815     return !OK;
1816 }
1817 
ap_expr_post_config(apr_pool_t * pconf,apr_pool_t * plog,apr_pool_t * ptemp,server_rec * s)1818 static int ap_expr_post_config(apr_pool_t *pconf, apr_pool_t *plog,
1819                                apr_pool_t *ptemp, server_rec *s)
1820 {
1821     is_http2 = APR_RETRIEVE_OPTIONAL_FN(http2_is_h2);
1822     return OK;
1823 }
1824 
ap_expr_init(apr_pool_t * p)1825 void ap_expr_init(apr_pool_t *p)
1826 {
1827     ap_hook_expr_lookup(core_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE);
1828     ap_hook_expr_lookup(expr_lookup_not_found, NULL, NULL, APR_HOOK_REALLY_LAST);
1829     ap_hook_post_config(ap_expr_post_config, NULL, NULL, APR_HOOK_MIDDLE);
1830 }
1831 
1832