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