Coverage Report

Created: 2023-03-26 06:28

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