Coverage Report

Created: 2023-11-19 07:10

/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.50k
{
582
1.50k
    ap_expr_parse_ctx_t ctx;
583
1.50k
    int rc;
584
585
1.50k
    memset(&ctx, 0, sizeof ctx);
586
1.50k
    ctx.pool     = pool;
587
1.50k
    ctx.ptemp    = ptemp;
588
1.50k
    ctx.inputbuf = expr;
589
1.50k
    ctx.inputlen = strlen(expr);
590
1.50k
    ctx.inputptr = ctx.inputbuf;
591
1.50k
    ctx.flags    = info->flags;
592
1.50k
    ctx.lookup_fn   = lookup_fn ? lookup_fn : ap_expr_lookup_default;
593
1.50k
    ctx.at_start    = 1;
594
595
1.50k
    rc = ap_expr_yylex_init(&ctx.scanner);
596
1.50k
    if (rc)
597
0
        return "ap_expr_yylex_init error";
598
599
1.50k
    ap_expr_yyset_extra(&ctx, ctx.scanner);
600
1.50k
    rc = ap_expr_yyparse(&ctx);
601
1.50k
    ap_expr_yylex_destroy(ctx.scanner);
602
603
    /* ctx.error: the generic bison error message
604
     *            (XXX: usually not very useful, should be axed)
605
     * ctx.error2: an additional error message
606
     */
607
1.50k
    if (ctx.error) {
608
9
        if (ctx.error2)
609
9
            return apr_psprintf(pool, "%s: %s", ctx.error, ctx.error2);
610
0
        else
611
0
            return ctx.error;
612
9
    }
613
1.49k
    else if (ctx.error2) {
614
173
        return ctx.error2;
615
173
    }
616
617
1.32k
    if (rc) /* XXX can this happen? */
618
0
        return "syntax error";
619
620
#ifdef AP_EXPR_DEBUG
621
    if (ctx.expr)
622
        expr_dump_tree(ctx.expr, NULL, APLOG_NOTICE, 2);
623
#endif
624
625
1.32k
    info->root_node = ctx.expr;
626
627
1.32k
    return NULL;
628
1.32k
}
629
630
AP_DECLARE(ap_expr_info_t*) ap_expr_parse_cmd_mi(const cmd_parms *cmd,
631
                                                 const char *expr,
632
                                                 unsigned int flags,
633
                                                 const char **err,
634
                                                 ap_expr_lookup_fn_t *lookup_fn,
635
                                                 int module_index)
636
0
{
637
0
    ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t));
638
0
    info->filename = cmd->directive->filename;
639
0
    info->line_number = cmd->directive->line_num;
640
0
    info->flags = flags;
641
0
    info->module_index = module_index;
642
0
    *err = ap_expr_parse(cmd->pool, cmd->temp_pool, info, expr, lookup_fn);
643
644
0
    if (*err)
645
0
        return NULL;
646
647
0
    return info;
648
0
}
649
650
ap_expr_t *ap_expr_make(ap_expr_node_op_e op, const void *a1, const void *a2,
651
                        ap_expr_parse_ctx_t *ctx)
652
121k
{
653
121k
    ap_expr_t *node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
654
121k
    node->node_op   = op;
655
121k
    node->node_arg1 = a1;
656
121k
    node->node_arg2 = a2;
657
121k
    return node;
658
121k
}
659
660
ap_expr_t *ap_expr_concat_make(const void *a1, const void *a2,
661
                               ap_expr_parse_ctx_t *ctx)
662
60.0k
{
663
60.0k
    const ap_expr_t *node;
664
665
    /* Optimize out empty string(s) concatenation */
666
60.0k
    if ((node = a1)
667
60.0k
            && node->node_op == op_String
668
60.0k
            && !*(const char *)node->node_arg1) {
669
0
        return (ap_expr_t *)a2;
670
0
    }
671
60.0k
    if ((node = a2)
672
60.0k
            && node->node_op == op_String
673
60.0k
            && !*(const char *)node->node_arg1) {
674
95
        return (ap_expr_t *)a1;
675
95
    }
676
677
59.9k
    return ap_expr_make(op_Concat, a1, a2, ctx);
678
60.0k
}
679
680
ap_expr_t *ap_expr_regex_make(const char *pattern, const ap_expr_t *subst,
681
                              const char *flags, ap_expr_parse_ctx_t *ctx)
682
0
{
683
0
    ap_expr_t *node = NULL;
684
0
    ap_expr_regctx_t *regctx;
685
0
    ap_regex_t *regex;
686
687
0
    regctx = apr_pcalloc(ctx->pool, sizeof *regctx);
688
0
    regctx->subst = subst;
689
0
    if (flags) {
690
0
        for (; *flags; ++flags) {
691
0
            switch (*flags) {
692
0
            case 'i':
693
0
                regctx->flags |= AP_REG_ICASE;
694
0
                break;
695
0
            case 'm':
696
0
                regctx->flags |= AP_REG_NEWLINE;
697
0
                break;
698
0
            case 's':
699
0
                regctx->flags |= AP_REG_DOTALL;
700
0
                break;
701
0
            case 'g':
702
0
                regctx->flags |= AP_REG_MULTI;
703
0
                break;
704
0
            }
705
0
        }
706
0
    }
707
0
    regex = ap_pregcomp(ctx->pool, pattern, regctx->flags);
708
0
    if (!regex) {
709
0
        return NULL;
710
0
    }
711
712
0
    node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
713
0
    node->node_op   = op_Regex;
714
0
    node->node_arg1 = regex;
715
0
    node->node_arg2 = regctx;
716
0
    return node;
717
0
}
718
719
static ap_expr_t *ap_expr_info_make(int type, const char *name,
720
                                  ap_expr_parse_ctx_t *ctx,
721
                                  const ap_expr_t *arg)
722
0
{
723
0
    ap_expr_t *info = apr_palloc(ctx->pool, sizeof(ap_expr_t));
724
0
    ap_expr_lookup_parms parms;
725
0
    parms.type  = type;
726
0
    parms.flags = ctx->flags;
727
0
    parms.pool  = ctx->pool;
728
0
    parms.ptemp = ctx->ptemp;
729
0
    parms.name  = name;
730
0
    parms.func  = &info->node_arg1;
731
0
    parms.data  = &info->node_arg2;
732
0
    parms.err   = &ctx->error2;
733
0
    parms.arg   = NULL;
734
0
    if (arg) {
735
0
        switch(arg->node_op) {
736
0
            case op_String:
737
0
                parms.arg = arg->node_arg1;
738
0
                break;
739
0
            case op_ListElement:
740
                /* save the first literal/simple string argument */
741
0
                do {
742
0
                    const ap_expr_t *val = arg->node_arg1;
743
0
                    if (val && val->node_op == op_String) {
744
0
                        parms.arg = val->node_arg1;
745
0
                        break;
746
0
                    }
747
0
                    arg = arg->node_arg2;
748
0
                } while (arg != NULL);
749
0
                break;
750
0
            default:
751
0
                break;
752
0
        }
753
0
    }
754
0
    if (ctx->lookup_fn(&parms) != OK)
755
0
        return NULL;
756
0
    return info;
757
0
}
758
759
ap_expr_t *ap_expr_str_func_make(const char *name, const ap_expr_t *arg,
760
                               ap_expr_parse_ctx_t *ctx)
761
0
{
762
0
    ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_STRING, name, ctx, arg);
763
0
    if (!info)
764
0
        return NULL;
765
766
0
    info->node_op = op_StringFuncInfo;
767
0
    return ap_expr_make(op_StringFuncCall, info, arg, ctx);
768
0
}
769
770
ap_expr_t *ap_expr_list_func_make(const char *name, const ap_expr_t *arg,
771
                                ap_expr_parse_ctx_t *ctx)
772
0
{
773
0
    ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_LIST, name, ctx, arg);
774
0
    if (!info)
775
0
        return NULL;
776
777
0
    info->node_op = op_ListFuncInfo;
778
0
    return ap_expr_make(op_ListFuncCall, info, arg, ctx);
779
0
}
780
781
ap_expr_t *ap_expr_unary_op_make(const char *name, const ap_expr_t *arg,
782
                               ap_expr_parse_ctx_t *ctx)
783
0
{
784
0
    ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_OP_UNARY, name, ctx, arg);
785
0
    if (!info)
786
0
        return NULL;
787
788
0
    info->node_op = op_UnaryOpInfo;
789
0
    return ap_expr_make(op_UnaryOpCall, info, arg, ctx);
790
0
}
791
792
ap_expr_t *ap_expr_binary_op_make(const char *name, const ap_expr_t *arg1,
793
                                const ap_expr_t *arg2, ap_expr_parse_ctx_t *ctx)
794
0
{
795
0
    ap_expr_t *args;
796
0
    ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_OP_BINARY, name, ctx,
797
0
                                        arg2);
798
0
    if (!info)
799
0
        return NULL;
800
801
0
    info->node_op = op_BinaryOpInfo;
802
0
    args = ap_expr_make(op_BinaryOpArgs, arg1, arg2, ctx);
803
0
    return ap_expr_make(op_BinaryOpCall, info, args, ctx);
804
0
}
805
806
807
ap_expr_t *ap_expr_var_make(const char *name, ap_expr_parse_ctx_t *ctx)
808
0
{
809
0
    ap_expr_t *node = ap_expr_info_make(AP_EXPR_FUNC_VAR, name, ctx, NULL);
810
0
    if (!node)
811
0
        return NULL;
812
813
0
    node->node_op = op_Var;
814
0
    return node;
815
0
}
816
817
ap_expr_t *ap_expr_backref_make(int num, ap_expr_parse_ctx_t *ctx)
818
32.4k
{
819
32.4k
    int *n = apr_pmemdup(ctx->pool, &num, sizeof(num));
820
32.4k
    return ap_expr_make(op_Backref, n, NULL, ctx);
821
32.4k
}
822
823
#ifdef AP_EXPR_DEBUG
824
825
#define MARK                        APLOG_MARK,loglevel,0,s
826
#define DUMP_E_E(op, e1, e2)                                                \
827
    do { ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, e1, e2);      \
828
         if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);               \
829
         if (e2) expr_dump_tree(e2, s, loglevel, indent + 2);               \
830
    } while (0)
831
#define DUMP_S_E(op, s1, e1)                                                    \
832
    do { ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, e1); \
833
         if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);                   \
834
    } while (0)
835
#define DUMP_S_P(op, s1, p1)                                                \
836
    ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, p1);
837
#define DUMP_P_P(op, p1, p2)                                                \
838
    ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, p1, p2);
839
#define DUMP_S_S(op, s1, s2)                                                       \
840
    ap_log_error(MARK,"%*s%s: '%s' '%s'", indent, " ", op, (char *)s1, (char *)s2)
841
#define DUMP_P(op, p1)                                                      \
842
    ap_log_error(MARK,"%*s%s: %pp", indent, " ", op, p1);
843
#define DUMP_IP(op, p1)                                                     \
844
    ap_log_error(MARK,"%*s%s: %d", indent, " ", op, *(int *)p1);
845
#define DUMP_S(op, s1)                                                      \
846
    ap_log_error(MARK,"%*s%s: '%s'", indent, " ", op, (char *)s1)
847
848
#define CASE_OP(op)                  case op: name = #op ; break;
849
850
static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
851
                           int loglevel, int indent)
852
{
853
    switch (e->node_op) {
854
    /* no arg */
855
    case op_NOP:
856
    case op_True:
857
    case op_False:
858
        {
859
            char *name;
860
            switch (e->node_op) {
861
            CASE_OP(op_NOP);
862
            CASE_OP(op_True);
863
            CASE_OP(op_False);
864
            default:
865
                ap_assert(0);
866
            }
867
            ap_log_error(MARK, "%*s%s", indent, " ", name);
868
        }
869
        break;
870
871
    /* arg1: string, arg2: expr */
872
    case op_UnaryOpCall:
873
    case op_BinaryOpCall:
874
    case op_BinaryOpArgs:
875
        {
876
            char *name;
877
            switch (e->node_op) {
878
            CASE_OP(op_BinaryOpCall);
879
            CASE_OP(op_UnaryOpCall);
880
            CASE_OP(op_BinaryOpArgs);
881
            default:
882
                ap_assert(0);
883
            }
884
            DUMP_S_E(name, e->node_arg1, e->node_arg2);
885
        }
886
        break;
887
888
    /* arg1: expr, arg2: expr */
889
    case op_Comp:
890
    case op_Not:
891
    case op_Or:
892
    case op_And:
893
    case op_EQ:
894
    case op_NE:
895
    case op_LT:
896
    case op_LE:
897
    case op_GT:
898
    case op_GE:
899
    case op_STR_EQ:
900
    case op_STR_NE:
901
    case op_STR_LT:
902
    case op_STR_LE:
903
    case op_STR_GT:
904
    case op_STR_GE:
905
    case op_IN:
906
    case op_REG:
907
    case op_NRE:
908
    case op_Word:
909
    case op_Bool:
910
    case op_Sub:
911
    case op_Join:
912
    case op_Split:
913
    case op_Concat:
914
    case op_StringFuncCall:
915
    case op_ListFuncCall:
916
    case op_ListElement:
917
        {
918
            char *name;
919
            switch (e->node_op) {
920
            CASE_OP(op_Comp);
921
            CASE_OP(op_Not);
922
            CASE_OP(op_Or);
923
            CASE_OP(op_And);
924
            CASE_OP(op_EQ);
925
            CASE_OP(op_NE);
926
            CASE_OP(op_LT);
927
            CASE_OP(op_LE);
928
            CASE_OP(op_GT);
929
            CASE_OP(op_GE);
930
            CASE_OP(op_STR_EQ);
931
            CASE_OP(op_STR_NE);
932
            CASE_OP(op_STR_LT);
933
            CASE_OP(op_STR_LE);
934
            CASE_OP(op_STR_GT);
935
            CASE_OP(op_STR_GE);
936
            CASE_OP(op_IN);
937
            CASE_OP(op_REG);
938
            CASE_OP(op_NRE);
939
            CASE_OP(op_Word);
940
            CASE_OP(op_Bool);
941
            CASE_OP(op_Sub);
942
            CASE_OP(op_Join);
943
            CASE_OP(op_Split);
944
            CASE_OP(op_Concat);
945
            CASE_OP(op_StringFuncCall);
946
            CASE_OP(op_ListFuncCall);
947
            CASE_OP(op_ListElement);
948
            default:
949
                ap_assert(0);
950
            }
951
            DUMP_E_E(name, e->node_arg1, e->node_arg2);
952
        }
953
        break;
954
    /* arg1: string */
955
    case op_Digit:
956
    case op_String:
957
        {
958
            char *name;
959
            switch (e->node_op) {
960
            CASE_OP(op_Digit);
961
            CASE_OP(op_String);
962
            default:
963
                ap_assert(0);
964
            }
965
            DUMP_S(name, e->node_arg1);
966
        }
967
        break;
968
    /* arg1: pointer, arg2: pointer */
969
    case op_Var:
970
    case op_StringFuncInfo:
971
    case op_UnaryOpInfo:
972
    case op_BinaryOpInfo:
973
    case op_ListFuncInfo:
974
        {
975
            char *name;
976
            switch (e->node_op) {
977
            CASE_OP(op_Var);
978
            CASE_OP(op_StringFuncInfo);
979
            CASE_OP(op_UnaryOpInfo);
980
            CASE_OP(op_BinaryOpInfo);
981
            CASE_OP(op_ListFuncInfo);
982
            default:
983
                ap_assert(0);
984
            }
985
            DUMP_P_P(name, e->node_arg1, e->node_arg2);
986
        }
987
        break;
988
    /* arg1: pointer */
989
    case op_Regex:
990
        DUMP_P("op_Regex", e->node_arg1);
991
        break;
992
    /* arg1: pointer to int */
993
    case op_Backref:
994
        DUMP_IP("op_Backref", e->node_arg1);
995
        break;
996
    default:
997
        ap_log_error(MARK, "%*sERROR: INVALID OP %d", indent, " ", e->node_op);
998
        break;
999
    }
1000
}
1001
#endif /* AP_EXPR_DEBUG */
1002
1003
0
#define expr_eval_log(ctx, level, ...) do { \
1004
0
    ap_expr_eval_ctx_t *x = (ctx); \
1005
0
    if (x->r) { \
1006
0
        ap_log_rerror(LOG_MARK(x->info), (level), 0, x->r, __VA_ARGS__); \
1007
0
    } \
1008
0
    else if (x->c) { \
1009
0
        ap_log_cerror(LOG_MARK(x->info), (level), 0, x->c, __VA_ARGS__); \
1010
0
    } \
1011
0
    else { \
1012
0
        ap_log_error(LOG_MARK(x->info), (level), 0, x->s, __VA_ARGS__); \
1013
0
    } \
1014
0
} while (0)
1015
1016
static int ap_expr_eval_unary_op(ap_expr_eval_ctx_t *ctx, const ap_expr_t *info,
1017
                                 const ap_expr_t *arg)
1018
0
{
1019
0
    ap_expr_op_unary_t *op_func = (ap_expr_op_unary_t *)info->node_arg1;
1020
0
    const void *data = info->node_arg2;
1021
1022
0
    AP_DEBUG_ASSERT(info->node_op == op_UnaryOpInfo);
1023
0
    AP_DEBUG_ASSERT(op_func != NULL);
1024
0
    AP_DEBUG_ASSERT(data != NULL);
1025
0
    return (*op_func)(ctx, data, ap_expr_eval_word(ctx, arg));
1026
0
}
1027
1028
static int ap_expr_eval_binary_op(ap_expr_eval_ctx_t *ctx,
1029
                                  const ap_expr_t *info,
1030
                                  const ap_expr_t *args)
1031
0
{
1032
0
    ap_expr_op_binary_t *op_func = (ap_expr_op_binary_t *)info->node_arg1;
1033
0
    const void *data = info->node_arg2;
1034
0
    const ap_expr_t *a1 = args->node_arg1;
1035
0
    const ap_expr_t *a2 = args->node_arg2;
1036
1037
0
    AP_DEBUG_ASSERT(info->node_op == op_BinaryOpInfo);
1038
0
    AP_DEBUG_ASSERT(args->node_op == op_BinaryOpArgs);
1039
0
    AP_DEBUG_ASSERT(op_func != NULL);
1040
0
    AP_DEBUG_ASSERT(data != NULL);
1041
0
    return (*op_func)(ctx, data, ap_expr_eval_word(ctx, a1),
1042
0
                      ap_expr_eval_word(ctx, a2));
1043
0
}
1044
1045
1046
static int ap_expr_eval_cond(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
1047
0
{
1048
0
    const ap_expr_t *e1 = node->node_arg1;
1049
0
    const ap_expr_t *e2 = node->node_arg2;
1050
0
    int result = FALSE;
1051
0
    if (inc_rec(ctx))
1052
0
        return result;
1053
0
    while (1) {
1054
0
        switch (node->node_op) {
1055
0
        case op_True:
1056
0
            result ^= TRUE;
1057
0
            goto out;
1058
0
        case op_False:
1059
0
            result ^= FALSE;
1060
0
            goto out;
1061
0
        case op_Not:
1062
0
            result = !result;
1063
0
            node = e1;
1064
0
            break;
1065
0
        case op_Or:
1066
0
            do {
1067
0
                if (e1->node_op == op_Not) {
1068
0
                    if (!ap_expr_eval_cond(ctx, e1->node_arg1)) {
1069
0
                        result ^= TRUE;
1070
0
                        goto out;
1071
0
                    }
1072
0
                }
1073
0
                else {
1074
0
                    if (ap_expr_eval_cond(ctx, e1)) {
1075
0
                        result ^= TRUE;
1076
0
                        goto out;
1077
0
                    }
1078
0
                }
1079
0
                node = node->node_arg2;
1080
0
                e1 = node->node_arg1;
1081
0
            } while (node->node_op == op_Or);
1082
0
            break;
1083
0
        case op_And:
1084
0
            do {
1085
0
                if (e1->node_op == op_Not) {
1086
0
                    if (ap_expr_eval_cond(ctx, e1->node_arg1)) {
1087
0
                        result ^= FALSE;
1088
0
                        goto out;
1089
0
                    }
1090
0
                }
1091
0
                else {
1092
0
                    if (!ap_expr_eval_cond(ctx, e1)) {
1093
0
                        result ^= FALSE;
1094
0
                        goto out;
1095
0
                    }
1096
0
                }
1097
0
                node = node->node_arg2;
1098
0
                e1 = node->node_arg1;
1099
0
            } while (node->node_op == op_And);
1100
0
            break;
1101
0
        case op_UnaryOpCall:
1102
0
            result ^= ap_expr_eval_unary_op(ctx, e1, e2);
1103
0
            goto out;
1104
0
        case op_BinaryOpCall:
1105
0
            result ^= ap_expr_eval_binary_op(ctx, e1, e2);
1106
0
            goto out;
1107
0
        case op_Comp:
1108
0
            if (ctx->info->flags & AP_EXPR_FLAG_SSL_EXPR_COMPAT)
1109
0
                result ^= ssl_expr_eval_comp(ctx, e1);
1110
0
            else
1111
0
                result ^= ap_expr_eval_comp(ctx, e1);
1112
0
            goto out;
1113
0
        default:
1114
0
            *ctx->err = "Internal evaluation error: Unknown expression node";
1115
0
            goto out;
1116
0
        }
1117
0
        e1 = node->node_arg1;
1118
0
        e2 = node->node_arg2;
1119
0
    }
1120
0
out:
1121
0
    ctx->reclvl--;
1122
0
    return result;
1123
0
}
1124
1125
AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *info,
1126
                             const char **err)
1127
0
{
1128
0
    return ap_expr_exec_re(r, info, 0, NULL, NULL, err);
1129
0
}
1130
1131
AP_DECLARE(int) ap_expr_exec_ctx(ap_expr_eval_ctx_t *ctx)
1132
0
{
1133
0
    int rc;
1134
1135
0
    AP_DEBUG_ASSERT(ctx->p != NULL);
1136
0
    AP_DEBUG_ASSERT(ctx->err != NULL);
1137
0
    AP_DEBUG_ASSERT(ctx->info != NULL);
1138
0
    if (ctx->re_pmatch) {
1139
0
        AP_DEBUG_ASSERT(ctx->re_source != NULL);
1140
0
        AP_DEBUG_ASSERT(ctx->re_nmatch > 0);
1141
0
    }
1142
0
    if (!ctx->s) {
1143
0
        if (ctx->r) {
1144
0
            ctx->s = ctx->r->server;
1145
0
        }
1146
0
        else if (ctx->c) {
1147
0
            ctx->s = ctx->c->base_server;
1148
0
        }
1149
0
    }
1150
0
    if (!ctx->c) {
1151
0
        if (ctx->r) {
1152
0
            ctx->c = ctx->r->connection;
1153
0
        }
1154
0
    }
1155
0
    AP_DEBUG_ASSERT(ctx->s != NULL);
1156
1157
0
    ctx->reclvl = 0;
1158
0
    *ctx->err = NULL;
1159
0
    if (ctx->info->flags & AP_EXPR_FLAG_STRING_RESULT) {
1160
0
        *ctx->result_string = ap_expr_eval_word(ctx, ctx->info->root_node);
1161
0
        if (*ctx->err != NULL) {
1162
0
            expr_eval_log(ctx, APLOG_ERR, APLOGNO(03298)
1163
0
                          "Evaluation of string expression from %s:%d failed: %s",
1164
0
                          ctx->info->filename, ctx->info->line_number, *ctx->err);
1165
0
            return -1;
1166
0
        } else {
1167
0
            expr_eval_log(ctx, APLOG_TRACE4,
1168
0
                          "Evaluation of string expression from %s:%d gave: %s",
1169
0
                          ctx->info->filename, ctx->info->line_number,
1170
0
                          *ctx->result_string);
1171
0
            return 1;
1172
0
        }
1173
0
    }
1174
0
    else {
1175
0
        rc = ap_expr_eval_cond(ctx, ctx->info->root_node);
1176
0
        if (*ctx->err != NULL) {
1177
0
            expr_eval_log(ctx, APLOG_ERR, APLOGNO(03299)
1178
0
                          "Evaluation of expression from %s:%d failed: %s",
1179
0
                          ctx->info->filename, ctx->info->line_number, *ctx->err);
1180
0
            return -1;
1181
0
        } else {
1182
0
            rc = rc ? 1 : 0;
1183
0
            expr_eval_log(ctx, APLOG_TRACE4,
1184
0
                          "Evaluation of expression from %s:%d gave: %d",
1185
0
                          ctx->info->filename, ctx->info->line_number, rc);
1186
1187
0
            if (ctx->r && ctx->vary_this && *ctx->vary_this)
1188
0
                apr_table_merge(ctx->r->headers_out, "Vary", *ctx->vary_this);
1189
1190
0
            return rc;
1191
0
        }
1192
0
    }
1193
0
}
1194
1195
AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
1196
                                apr_size_t nmatch, ap_regmatch_t *pmatch,
1197
                                const char **source, const char **err)
1198
0
{
1199
0
    ap_expr_eval_ctx_t ctx;
1200
0
    int dont_vary = (info->flags & AP_EXPR_FLAG_DONT_VARY);
1201
0
    const char *tmp_source = NULL, *vary_this = NULL;
1202
0
    ap_regmatch_t tmp_pmatch[AP_MAX_REG_MATCH];
1203
1204
0
    AP_DEBUG_ASSERT((info->flags & AP_EXPR_FLAG_STRING_RESULT) == 0);
1205
1206
0
    ctx.r = r;
1207
0
    ctx.c = r->connection;
1208
0
    ctx.s = r->server;
1209
0
    ctx.p = r->pool;
1210
0
    ctx.err  = err;
1211
0
    ctx.info = info;
1212
0
    ctx.re_nmatch = nmatch;
1213
0
    ctx.re_pmatch = pmatch;
1214
0
    ctx.re_source = source;
1215
0
    ctx.vary_this = dont_vary ? NULL : &vary_this;
1216
0
    ctx.data = NULL;
1217
1218
0
    if (!pmatch) {
1219
0
        ctx.re_nmatch = AP_MAX_REG_MATCH;
1220
0
        ctx.re_pmatch = tmp_pmatch;
1221
0
        ctx.re_source = &tmp_source;
1222
0
    }
1223
1224
0
    return ap_expr_exec_ctx(&ctx);
1225
0
}
1226
1227
AP_DECLARE(const char *) ap_expr_str_exec_re(request_rec *r,
1228
                                             const ap_expr_info_t *info,
1229
                                             apr_size_t nmatch,
1230
                                             ap_regmatch_t *pmatch,
1231
                                             const char **source,
1232
                                             const char **err)
1233
0
{
1234
0
    ap_expr_eval_ctx_t ctx;
1235
0
    int dont_vary, rc;
1236
0
    const char *tmp_source, *vary_this;
1237
0
    ap_regmatch_t tmp_pmatch[AP_MAX_REG_MATCH];
1238
0
    const char *result;
1239
1240
0
    AP_DEBUG_ASSERT(info->flags & AP_EXPR_FLAG_STRING_RESULT);
1241
1242
0
    if (info->root_node->node_op == op_String) {
1243
        /* short-cut for constant strings */
1244
0
        *err = NULL;
1245
0
        return (const char *)info->root_node->node_arg1;
1246
0
    }
1247
1248
0
    tmp_source = NULL;
1249
0
    vary_this = NULL;
1250
1251
0
    dont_vary = (info->flags & AP_EXPR_FLAG_DONT_VARY);
1252
1253
0
    ctx.r = r;
1254
0
    ctx.c = r->connection;
1255
0
    ctx.s = r->server;
1256
0
    ctx.p = r->pool;
1257
0
    ctx.err  = err;
1258
0
    ctx.info = info;
1259
0
    ctx.re_nmatch = nmatch;
1260
0
    ctx.re_pmatch = pmatch;
1261
0
    ctx.re_source = source;
1262
0
    ctx.vary_this = dont_vary ? NULL : &vary_this;
1263
0
    ctx.data = NULL;
1264
0
    ctx.result_string = &result;
1265
1266
0
    if (!pmatch) {
1267
0
        ctx.re_nmatch = AP_MAX_REG_MATCH;
1268
0
        ctx.re_pmatch = tmp_pmatch;
1269
0
        ctx.re_source = &tmp_source;
1270
0
    }
1271
1272
0
    rc = ap_expr_exec_ctx(&ctx);
1273
0
    if (rc > 0)
1274
0
        return result;
1275
0
    else if (rc < 0)
1276
0
        return NULL;
1277
0
    else
1278
0
        ap_assert(0);
1279
    /* Not reached */
1280
0
    return NULL;
1281
0
}
1282
1283
AP_DECLARE(const char *) ap_expr_str_exec(request_rec *r,
1284
                                          const ap_expr_info_t *info,
1285
                                          const char **err)
1286
0
{
1287
0
    return ap_expr_str_exec_re(r, info, 0, NULL, NULL, err);
1288
0
}
1289
1290
1291
static void add_vary(ap_expr_eval_ctx_t *ctx, const char *name)
1292
0
{
1293
0
    if (!ctx->vary_this)
1294
0
        return;
1295
1296
0
    if (*ctx->vary_this) {
1297
0
        *ctx->vary_this = apr_pstrcat(ctx->p, *ctx->vary_this, ", ", name,
1298
0
                                      NULL);
1299
0
    }
1300
0
    else {
1301
0
        *ctx->vary_this = name;
1302
0
    }
1303
0
}
1304
1305
static const char *req_table_func(ap_expr_eval_ctx_t *ctx, const void *data,
1306
                                  const char *arg)
1307
0
{
1308
0
    const char *name = (const char *)data;
1309
0
    apr_table_t *t;
1310
0
    if (!ctx->r)
1311
0
        return "";
1312
1313
0
    if (name[2] == 's') {           /* resp */
1314
        /* Try r->headers_out first, fall back on err_headers_out. */
1315
0
        const char *v = apr_table_get(ctx->r->headers_out, arg);
1316
0
        if (v) {
1317
0
            return v;
1318
0
        }
1319
0
        t = ctx->r->err_headers_out;
1320
0
    }
1321
0
    else if (name[0] == 'n')        /* notes */
1322
0
        t = ctx->r->notes;
1323
0
    else if (name[3] == 'e')        /* reqenv */
1324
0
        t = ctx->r->subprocess_env;
1325
0
    else if (name[3] == '_')        /* req_novary */
1326
0
        t = ctx->r->headers_in;
1327
0
    else {                          /* req, http */
1328
0
        t = ctx->r->headers_in;
1329
        /* Skip the 'Vary: Host' header combination
1330
         * as indicated in rfc7231 section-7.1.4
1331
         */
1332
0
        if (strcasecmp(arg, "Host")){
1333
0
            add_vary(ctx, arg);
1334
0
        }
1335
0
    }
1336
0
    return apr_table_get(t, arg);
1337
0
}
1338
1339
static const char *env_func(ap_expr_eval_ctx_t *ctx, const void *data,
1340
                            const char *arg)
1341
0
{
1342
0
    const char *res;
1343
    /* this order is for ssl_expr compatibility */
1344
0
    if (ctx->r) {
1345
0
        if ((res = apr_table_get(ctx->r->notes, arg)) != NULL)
1346
0
            return res;
1347
0
        else if ((res = apr_table_get(ctx->r->subprocess_env, arg)) != NULL)
1348
0
            return res;
1349
0
    }
1350
0
    return getenv(arg);
1351
0
}
1352
1353
static const char *osenv_func(ap_expr_eval_ctx_t *ctx, const void *data,
1354
                              const char *arg)
1355
0
{
1356
0
    return getenv(arg);
1357
0
}
1358
1359
static const char *tolower_func(ap_expr_eval_ctx_t *ctx, const void *data,
1360
                                const char *arg)
1361
0
{
1362
0
    char *result = apr_pstrdup(ctx->p, arg);
1363
0
    ap_str_tolower(result);
1364
0
    return result;
1365
0
}
1366
1367
static const char *toupper_func(ap_expr_eval_ctx_t *ctx, const void *data,
1368
                                const char *arg)
1369
0
{
1370
0
    char *result = apr_pstrdup(ctx->p, arg);
1371
0
    ap_str_toupper(result);
1372
0
    return result;
1373
0
}
1374
1375
static const char *escape_func(ap_expr_eval_ctx_t *ctx, const void *data,
1376
                               const char *arg)
1377
0
{
1378
0
    return ap_escape_uri(ctx->p, arg);
1379
0
}
1380
1381
static const char *base64_func(ap_expr_eval_ctx_t *ctx, const void *data,
1382
                               const char *arg)
1383
0
{
1384
0
    return ap_pbase64encode(ctx->p, (char *)arg);
1385
0
}
1386
1387
static const char *unbase64_func(ap_expr_eval_ctx_t *ctx, const void *data,
1388
                               const char *arg)
1389
0
{
1390
0
    return ap_pbase64decode(ctx->p, arg);
1391
0
}
1392
1393
static const char *sha1_func(ap_expr_eval_ctx_t *ctx, const void *data,
1394
                               const char *arg)
1395
0
{
1396
0
    apr_sha1_ctx_t context;
1397
0
    apr_byte_t sha1[APR_SHA1_DIGESTSIZE];
1398
0
    char *out;
1399
1400
0
    out = apr_palloc(ctx->p, APR_SHA1_DIGESTSIZE*2+1);
1401
1402
0
    apr_sha1_init(&context);
1403
0
    apr_sha1_update(&context, arg, (unsigned int)strlen(arg));
1404
0
    apr_sha1_final(sha1, &context);
1405
1406
0
    ap_bin2hex(sha1, APR_SHA1_DIGESTSIZE, out);
1407
1408
0
    return out;
1409
0
}
1410
1411
static const char *md5_func(ap_expr_eval_ctx_t *ctx, const void *data,
1412
                               const char *arg)
1413
0
{
1414
0
    return ap_md5(ctx->p, (const unsigned char *)arg);
1415
0
}
1416
1417
#if APR_VERSION_AT_LEAST(1,6,0)
1418
static const char *ldap_func(ap_expr_eval_ctx_t *ctx, const void *data,
1419
                               const char *arg)
1420
0
{
1421
0
    return apr_pescape_ldap(ctx->p, arg, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_ALL);
1422
0
}
1423
#endif
1424
1425
static int replace_func_parse_arg(ap_expr_lookup_parms *parms)
1426
0
{
1427
0
    const char *original = parms->arg;
1428
0
    const apr_strmatch_pattern *pattern;
1429
1430
0
    if (!parms->arg) {
1431
0
        *parms->err = apr_psprintf(parms->ptemp, "replace() function needs an argument");
1432
0
        return !OK;
1433
0
    }
1434
1435
0
    pattern = apr_strmatch_precompile(parms->pool, original, 0);
1436
0
    *parms->data = pattern;
1437
0
    return OK;
1438
0
}
1439
1440
static const char *replace_func(ap_expr_eval_ctx_t *ctx, const void *data,
1441
                               const apr_array_header_t *args)
1442
0
{
1443
0
    char *buff, *original, *replacement;
1444
0
    struct ap_varbuf vb;
1445
0
    apr_size_t repl_len, orig_len;
1446
0
    const char *repl;
1447
0
    apr_size_t bytes;
1448
0
    apr_size_t len;
1449
0
    const apr_strmatch_pattern *pattern = data;
1450
0
    if (args->nelts != 3) {
1451
0
        *ctx->err = apr_psprintf(ctx->p, "replace() function needs "
1452
0
                                 "exactly 3 arguments, got %d", args->nelts);
1453
0
        return "";
1454
0
    }
1455
1456
0
    buff = APR_ARRAY_IDX(args, 0, char *);
1457
0
    original = APR_ARRAY_IDX(args, 1, char *);
1458
0
    replacement = APR_ARRAY_IDX(args, 2, char *);
1459
0
    repl_len = strlen(replacement);
1460
0
    orig_len = strlen(original);
1461
0
    bytes = strlen(buff);
1462
1463
0
    ap_varbuf_init(ctx->p, &vb, 0);
1464
0
    vb.strlen = 0;
1465
    
1466
0
    while ((repl = apr_strmatch(pattern, buff, bytes))) {
1467
0
        len = (apr_size_t) (repl - buff);
1468
0
        ap_varbuf_strmemcat(&vb, buff, len);
1469
0
        ap_varbuf_strmemcat(&vb, replacement, repl_len);
1470
1471
0
        len += orig_len;
1472
0
        bytes -= len;
1473
0
        buff += len;
1474
0
    }
1475
1476
0
    return ap_varbuf_pdup(ctx->p, &vb, NULL, 0, buff, bytes, &len);
1477
0
}
1478
1479
0
#define MAX_FILE_SIZE 10*1024*1024
1480
static const char *file_func(ap_expr_eval_ctx_t *ctx, const void *data,
1481
                             char *arg)
1482
0
{
1483
0
    apr_file_t *fp;
1484
0
    char *buf;
1485
0
    apr_off_t offset;
1486
0
    apr_size_t len;
1487
0
    apr_finfo_t finfo;
1488
1489
0
    if (apr_file_open(&fp, arg, APR_READ|APR_BUFFERED,
1490
0
                      APR_OS_DEFAULT, ctx->p) != APR_SUCCESS) {
1491
0
        *ctx->err = apr_psprintf(ctx->p, "Cannot open file %s", arg);
1492
0
        return "";
1493
0
    }
1494
0
    apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
1495
0
    if (finfo.size > MAX_FILE_SIZE) {
1496
0
        *ctx->err = apr_psprintf(ctx->p, "File %s too large", arg);
1497
0
        apr_file_close(fp);
1498
0
        return "";
1499
0
    }
1500
0
    len = (apr_size_t)finfo.size;
1501
0
    if (len == 0) {
1502
0
        apr_file_close(fp);
1503
0
        return "";
1504
0
    }
1505
0
    else {
1506
0
        if ((buf = (char *)apr_palloc(ctx->p, sizeof(char)*(len+1))) == NULL) {
1507
0
            *ctx->err = "Cannot allocate memory";
1508
0
            apr_file_close(fp);
1509
0
            return "";
1510
0
        }
1511
0
        offset = 0;
1512
0
        apr_file_seek(fp, APR_SET, &offset);
1513
0
        if (apr_file_read(fp, buf, &len) != APR_SUCCESS) {
1514
0
            *ctx->err = apr_psprintf(ctx->p, "Cannot read from file %s", arg);
1515
0
            apr_file_close(fp);
1516
0
            return "";
1517
0
        }
1518
0
        buf[len] = '\0';
1519
0
    }
1520
0
    apr_file_close(fp);
1521
0
    return buf;
1522
0
}
1523
1524
static const char *filesize_func(ap_expr_eval_ctx_t *ctx, const void *data,
1525
                                  char *arg)
1526
0
{
1527
0
    apr_finfo_t sb;
1528
0
    if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) == APR_SUCCESS
1529
0
        && sb.filetype == APR_REG && sb.size > 0)
1530
0
        return apr_psprintf(ctx->p, "%" APR_OFF_T_FMT, sb.size);
1531
0
    else
1532
0
        return "0";
1533
0
}
1534
1535
static const char *filemod_func(ap_expr_eval_ctx_t *ctx, const void *data,
1536
                                  char *arg)
1537
0
{
1538
0
    apr_finfo_t sb;
1539
0
    if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) == APR_SUCCESS
1540
0
        && sb.filetype == APR_REG && sb.mtime > 0)
1541
0
        return apr_psprintf(ctx->p, "%" APR_OFF_T_FMT, (apr_off_t)sb.mtime);
1542
0
    else
1543
0
        return "0";
1544
0
}
1545
1546
1547
static const char *unescape_func(ap_expr_eval_ctx_t *ctx, const void *data,
1548
                                 const char *arg)
1549
0
{
1550
0
    char *result = apr_pstrdup(ctx->p, arg);
1551
0
    int ret = ap_unescape_url_keep2f(result, 0);
1552
0
    if (ret == OK)
1553
0
        return result;
1554
0
    expr_eval_log(ctx, APLOG_DEBUG, APLOGNO(00538)
1555
0
                  "%s %% escape in unescape('%s') at %s:%d",
1556
0
                  ret == HTTP_BAD_REQUEST ? "Bad" : "Forbidden", arg,
1557
0
                  ctx->info->filename, ctx->info->line_number);
1558
0
    return "";
1559
0
}
1560
1561
static int op_nz(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1562
0
{
1563
0
    const char *name = (const char *)data;
1564
0
    if (name[0] == 'z')
1565
0
        return (arg[0] == '\0');
1566
0
    else
1567
0
        return (arg[0] != '\0');
1568
0
}
1569
1570
static int op_file_min(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1571
0
{
1572
0
    apr_finfo_t sb;
1573
0
    const char *name = (const char *)data;
1574
0
    if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) != APR_SUCCESS)
1575
0
        return FALSE;
1576
0
    switch (name[0]) {
1577
0
    case 'd':
1578
0
        return (sb.filetype == APR_DIR);
1579
0
    case 'e':
1580
0
        return TRUE;
1581
0
    case 'f':
1582
0
        return (sb.filetype == APR_REG);
1583
0
    case 's':
1584
0
        return (sb.filetype == APR_REG && sb.size > 0);
1585
0
    default:
1586
0
        ap_assert(0);
1587
0
    }
1588
0
    return FALSE;
1589
0
}
1590
1591
static int op_file_link(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1592
0
{
1593
0
#if !defined(OS2)
1594
0
    apr_finfo_t sb;
1595
0
    if (apr_stat(&sb, arg, APR_FINFO_MIN | APR_FINFO_LINK, ctx->p) == APR_SUCCESS
1596
0
        && sb.filetype == APR_LNK) {
1597
0
        return TRUE;
1598
0
    }
1599
0
#endif
1600
0
    return FALSE;
1601
0
}
1602
1603
static int op_file_xbit(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1604
0
{
1605
0
    apr_finfo_t sb;
1606
0
    if (apr_stat(&sb, arg, APR_FINFO_PROT| APR_FINFO_LINK, ctx->p) == APR_SUCCESS
1607
0
        && (sb.protection & (APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE))) {
1608
0
        return TRUE;
1609
0
    }
1610
0
    return FALSE;
1611
0
}
1612
1613
static int op_url_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1614
0
{
1615
0
    int rc = FALSE;
1616
0
    request_rec  *rsub, *r = ctx->r;
1617
0
    if (!r)
1618
0
        return FALSE;
1619
    /* avoid some infinite recursions */
1620
0
    if (r->main && r->main->uri && r->uri && strcmp(r->main->uri, r->uri) == 0)
1621
0
        return FALSE;
1622
1623
0
    rsub = ap_sub_req_lookup_uri(arg, r, NULL);
1624
0
    if (rsub->status < 400) {
1625
0
            rc = TRUE;
1626
0
    }
1627
0
    expr_eval_log(ctx, APLOG_TRACE5,
1628
0
                  "Subrequest for -U %s at %s:%d gave status: %d",
1629
0
                  arg, ctx->info->filename, ctx->info->line_number,
1630
0
                  rsub->status);
1631
0
    ap_destroy_sub_req(rsub);
1632
0
    return rc;
1633
0
}
1634
1635
static int op_file_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1636
0
{
1637
0
    int rc = FALSE;
1638
0
    apr_finfo_t sb;
1639
0
    request_rec *rsub, *r = ctx->r;
1640
0
    if (!r)
1641
0
        return FALSE;
1642
0
    rsub = ap_sub_req_lookup_file(arg, r, NULL);
1643
0
    if (rsub->status < 300 &&
1644
        /* double-check that file exists since default result is 200 */
1645
0
        apr_stat(&sb, rsub->filename, APR_FINFO_MIN, ctx->p) == APR_SUCCESS) {
1646
0
        rc = TRUE;
1647
0
    }
1648
0
    expr_eval_log(ctx, APLOG_TRACE5,
1649
0
                  "Subrequest for -F %s at %s:%d gave status: %d",
1650
0
                  arg, ctx->info->filename, ctx->info->line_number,
1651
0
                  rsub->status);
1652
0
    ap_destroy_sub_req(rsub);
1653
0
    return rc;
1654
0
}
1655
1656
1657
APR_DECLARE_OPTIONAL_FN(int, http2_is_h2, (conn_rec *));
1658
static APR_OPTIONAL_FN_TYPE(http2_is_h2) *is_http2 = NULL;
1659
1660
static const char *const conn_var_names[] = {
1661
    "HTTPS",                    /*  0 */
1662
    "IPV6",                     /*  1 */
1663
    "CONN_LOG_ID",              /*  2 */
1664
    "CONN_REMOTE_ADDR",         /*  3 */
1665
    "HTTP2",                    /*  4 */
1666
    NULL
1667
};
1668
1669
static const char *conn_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1670
0
{
1671
0
    int index = ((const char **)data - conn_var_names);
1672
0
    conn_rec *c = ctx->c;
1673
0
    if (!c)
1674
0
        return "";
1675
1676
0
    switch (index) {
1677
0
    case 0:
1678
0
        if (ap_ssl_conn_is_ssl(c))
1679
0
            return "on";
1680
0
        else
1681
0
            return "off";
1682
0
    case 1:
1683
0
#if APR_HAVE_IPV6
1684
0
        {
1685
0
            apr_sockaddr_t *addr = c->client_addr;
1686
0
            if (addr->family == AF_INET6
1687
0
                && !IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr))
1688
0
                return "on";
1689
0
            else
1690
0
                return "off";
1691
0
        }
1692
#else
1693
        return "off";
1694
#endif
1695
0
    case 2:
1696
0
        return c->log_id;
1697
0
    case 3:
1698
0
        return c->client_ip;
1699
0
    case 4:
1700
0
        if (is_http2 && is_http2(c))
1701
0
            return "on";
1702
0
        else
1703
0
            return "off";
1704
0
    default:
1705
0
        ap_assert(0);
1706
0
        return NULL;
1707
0
    }
1708
0
}
1709
1710
static const char *const request_var_names[] = {
1711
    "REQUEST_METHOD",           /*  0 */
1712
    "REQUEST_SCHEME",           /*  1 */
1713
    "REQUEST_URI",              /*  2 */
1714
    "REQUEST_FILENAME",         /*  3 */
1715
    "REMOTE_HOST",              /*  4 */
1716
    "REMOTE_IDENT",             /*  5 */
1717
    "REMOTE_USER",              /*  6 */
1718
    "SERVER_ADMIN",             /*  7 */
1719
    "SERVER_NAME",              /*  8 */
1720
    "SERVER_PORT",              /*  9 */
1721
    "SERVER_PROTOCOL",          /* 10 */
1722
    "SCRIPT_FILENAME",          /* 11 */
1723
    "PATH_INFO",                /* 12 */
1724
    "QUERY_STRING",             /* 13 */
1725
    "IS_SUBREQ",                /* 14 */
1726
    "DOCUMENT_ROOT",            /* 15 */
1727
    "AUTH_TYPE",                /* 16 */
1728
    "THE_REQUEST",              /* 17 */
1729
    "CONTENT_TYPE",             /* 18 */
1730
    "HANDLER",                  /* 19 */
1731
    "REQUEST_LOG_ID",           /* 20 */
1732
    "SCRIPT_USER",              /* 21 */
1733
    "SCRIPT_GROUP",             /* 22 */
1734
    "DOCUMENT_URI",             /* 23 */
1735
    "LAST_MODIFIED",            /* 24 */
1736
    "CONTEXT_PREFIX",           /* 25 */
1737
    "CONTEXT_DOCUMENT_ROOT",    /* 26 */
1738
    "REQUEST_STATUS",           /* 27 */
1739
    "REMOTE_ADDR",              /* 28 */
1740
    "SERVER_PROTOCOL_VERSION",  /* 29 */
1741
    "SERVER_PROTOCOL_VERSION_MAJOR",  /* 30 */
1742
    "SERVER_PROTOCOL_VERSION_MINOR",  /* 31 */
1743
    "REMOTE_PORT",                    /* 32 */
1744
    NULL
1745
};
1746
1747
static const char *request_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1748
0
{
1749
0
    int index = ((const char **)data - request_var_names);
1750
0
    request_rec *r = ctx->r;
1751
0
    if (!r)
1752
0
        return "";
1753
1754
0
    switch (index) {
1755
0
    case 0:
1756
0
        return r->method;
1757
0
    case 1:
1758
0
        return ap_http_scheme(r);
1759
0
    case 2:
1760
0
        return r->uri;
1761
0
    case 3:
1762
0
        return r->filename;
1763
0
    case 4:
1764
0
        return ap_get_useragent_host(r, REMOTE_NAME, NULL);
1765
0
    case 5:
1766
0
        return ap_get_remote_logname(r);
1767
0
    case 6:
1768
0
        return r->user;
1769
0
    case 7:
1770
0
        return r->server->server_admin;
1771
0
    case 8:
1772
0
        return ap_get_server_name_for_url(r);
1773
0
    case 9:
1774
0
        return apr_psprintf(ctx->p, "%u", ap_get_server_port(r));
1775
0
    case 10:
1776
0
        return r->protocol;
1777
0
    case 11:
1778
0
        return r->filename;
1779
0
    case 12:
1780
0
        return r->path_info;
1781
0
    case 13:
1782
0
        return r->args;
1783
0
    case 14:
1784
0
        return (r->main != NULL ? "true" : "false");
1785
0
    case 15:
1786
0
        return ap_document_root(r);
1787
0
    case 16:
1788
0
        return r->ap_auth_type;
1789
0
    case 17:
1790
0
        return r->the_request;
1791
0
    case 18:
1792
0
        return r->content_type;
1793
0
    case 19:
1794
0
        return r->handler;
1795
0
    case 20:
1796
0
        return r->log_id;
1797
0
    case 21:
1798
0
        {
1799
0
            char *result = "";
1800
0
            if (r->finfo.valid & APR_FINFO_USER)
1801
0
                apr_uid_name_get(&result, r->finfo.user, ctx->p);
1802
0
            return result;
1803
0
        }
1804
0
    case 22:
1805
0
        {
1806
0
            char *result = "";
1807
0
            if (r->finfo.valid & APR_FINFO_USER)
1808
0
                apr_gid_name_get(&result, r->finfo.group, ctx->p);
1809
0
            return result;
1810
0
        }
1811
0
    case 23:
1812
0
        {
1813
0
            const char *uri = apr_table_get(r->subprocess_env, "DOCUMENT_URI");
1814
0
            return uri ? uri : r->uri;
1815
0
        }
1816
0
    case 24:
1817
0
        {
1818
0
            apr_time_exp_t tm;
1819
0
            apr_time_exp_lt(&tm, r->mtime);
1820
0
            return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
1821
0
                                (tm.tm_year / 100) + 19, (tm.tm_year % 100),
1822
0
                                tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
1823
0
                                tm.tm_sec);
1824
0
        }
1825
0
    case 25:
1826
0
        return ap_context_prefix(r);
1827
0
    case 26:
1828
0
        return ap_context_document_root(r);
1829
0
    case 27:
1830
0
        return r->status ? apr_psprintf(ctx->p, "%d", r->status) : "";
1831
0
    case 28:
1832
0
        return r->useragent_ip;
1833
0
    case 29:
1834
0
        switch (r->proto_num) {
1835
0
        case 1001:  return "1001";   /* 1.1 */
1836
0
        case 1000:  return "1000";   /* 1.0 */
1837
0
        case 9:     return "9";      /* 0.9 */
1838
0
        }
1839
0
        return apr_psprintf(ctx->p, "%d", r->proto_num);
1840
0
    case 30:
1841
0
        switch (HTTP_VERSION_MAJOR(r->proto_num)) {
1842
0
        case 0:     return "0";
1843
0
        case 1:     return "1";
1844
0
        }
1845
0
        return apr_psprintf(ctx->p, "%d", HTTP_VERSION_MAJOR(r->proto_num));
1846
0
    case 31:
1847
0
        switch (HTTP_VERSION_MINOR(r->proto_num)) {
1848
0
        case 0:     return "0";
1849
0
        case 1:     return "1";
1850
0
        case 9:     return "9";
1851
0
        }
1852
0
        return apr_psprintf(ctx->p, "%d", HTTP_VERSION_MINOR(r->proto_num));
1853
0
    case 32:
1854
0
        return apr_psprintf(ctx->p, "%u", ctx->c->client_addr->port);
1855
0
    default:
1856
0
        ap_assert(0);
1857
0
        return NULL;
1858
0
    }
1859
0
}
1860
1861
static const char *const req_header_var_names[] = {
1862
    "HTTP_USER_AGENT",       /* 0 */
1863
    "HTTP_PROXY_CONNECTION", /* 1 */
1864
    "HTTP_REFERER",          /* 2 */
1865
    "HTTP_COOKIE",           /* 3 */
1866
    "HTTP_FORWARDED",        /* 4 */
1867
    "HTTP_HOST",             /* 5 */
1868
    "HTTP_ACCEPT",           /* 6 */
1869
    NULL
1870
};
1871
1872
static const char *const req_header_header_names[] = {
1873
    "User-Agent",
1874
    "Proxy-Connection",
1875
    "Referer",
1876
    "Cookie",
1877
    "Forwarded",
1878
    "Host",
1879
    "Accept"
1880
};
1881
1882
static const char *req_header_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1883
0
{
1884
0
    const char **const varname = (const char **)data;
1885
0
    int index = (varname - req_header_var_names);
1886
0
    const char *name;
1887
1888
0
    AP_DEBUG_ASSERT(index < 7);
1889
0
    if (!ctx->r)
1890
0
        return "";
1891
1892
0
    name = req_header_header_names[index];
1893
    /* Skip the 'Vary: Host' header combination
1894
     * as indicated in rfc7231 section-7.1.4
1895
     */
1896
0
    if (strcasecmp(name, "Host")){
1897
0
        add_vary(ctx, name);
1898
0
    }
1899
0
    return apr_table_get(ctx->r->headers_in, name);
1900
0
}
1901
1902
static const char *const misc_var_names[] = {
1903
    "TIME_YEAR",        /* 0 */
1904
    "TIME_MON",         /* 1 */
1905
    "TIME_DAY",         /* 2 */
1906
    "TIME_HOUR",        /* 3 */
1907
    "TIME_MIN",         /* 4 */
1908
    "TIME_SEC",         /* 5 */
1909
    "TIME_WDAY",        /* 6 */
1910
    "TIME",             /* 7 */
1911
    "SERVER_SOFTWARE",  /* 8 */
1912
    "API_VERSION",      /* 9 */
1913
    NULL
1914
};
1915
1916
static const char *misc_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1917
0
{
1918
0
    apr_time_exp_t tm;
1919
0
    int index = ((const char **)data - misc_var_names);
1920
0
    apr_time_exp_lt(&tm, apr_time_now());
1921
1922
0
    switch (index) {
1923
0
    case 0:
1924
0
        return apr_psprintf(ctx->p, "%02d%02d", (tm.tm_year / 100) + 19,
1925
0
                            tm.tm_year % 100);
1926
0
    case 1:
1927
0
        return apr_psprintf(ctx->p, "%02d", tm.tm_mon+1);
1928
0
    case 2:
1929
0
        return apr_psprintf(ctx->p, "%02d", tm.tm_mday);
1930
0
    case 3:
1931
0
        return apr_psprintf(ctx->p, "%02d", tm.tm_hour);
1932
0
    case 4:
1933
0
        return apr_psprintf(ctx->p, "%02d", tm.tm_min);
1934
0
    case 5:
1935
0
        return apr_psprintf(ctx->p, "%02d", tm.tm_sec);
1936
0
    case 6:
1937
0
        return apr_psprintf(ctx->p, "%d", tm.tm_wday);
1938
0
    case 7:
1939
0
        return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
1940
0
                            (tm.tm_year / 100) + 19, (tm.tm_year % 100),
1941
0
                            tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
1942
0
                            tm.tm_sec);
1943
0
    case 8:
1944
0
        return ap_get_server_banner();
1945
0
    case 9:
1946
0
        return apr_itoa(ctx->p, MODULE_MAGIC_NUMBER_MAJOR);
1947
0
    default:
1948
0
        ap_assert(0);
1949
0
    }
1950
1951
0
    return NULL;
1952
0
}
1953
1954
static int subnet_parse_arg(ap_expr_lookup_parms *parms)
1955
0
{
1956
0
    apr_ipsubnet_t *subnet;
1957
0
    const char *addr = parms->arg;
1958
0
    const char *mask;
1959
0
    apr_status_t ret;
1960
1961
0
    if (!parms->arg) {
1962
0
        *parms->err = apr_psprintf(parms->ptemp,
1963
0
                                   "-%s requires subnet/netmask as constant argument",
1964
0
                                   parms->name);
1965
0
        return !OK;
1966
0
    }
1967
1968
0
    mask = ap_strchr_c(addr, '/');
1969
0
    if (mask) {
1970
0
        addr = apr_pstrmemdup(parms->ptemp, addr, mask - addr);
1971
0
        mask++;
1972
0
    }
1973
1974
0
    ret = apr_ipsubnet_create(&subnet, addr, mask, parms->pool);
1975
0
    if (ret != APR_SUCCESS) {
1976
0
        *parms->err = "parsing of subnet/netmask failed";
1977
0
        return !OK;
1978
0
    }
1979
1980
0
    *parms->data = subnet;
1981
0
    return OK;
1982
0
}
1983
1984
static int op_ipmatch(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg1,
1985
                const char *arg2)
1986
0
{
1987
0
    apr_ipsubnet_t *subnet = (apr_ipsubnet_t *)data;
1988
0
    apr_sockaddr_t *saddr;
1989
1990
0
    AP_DEBUG_ASSERT(subnet != NULL);
1991
1992
    /* maybe log an error if this goes wrong? */
1993
0
    if (apr_sockaddr_info_get(&saddr, arg1, APR_UNSPEC, 0, 0, ctx->p) != APR_SUCCESS)
1994
0
        return FALSE;
1995
1996
0
    return apr_ipsubnet_test(subnet, saddr);
1997
0
}
1998
1999
static int op_R(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg1)
2000
0
{
2001
0
    apr_ipsubnet_t *subnet = (apr_ipsubnet_t *)data;
2002
2003
0
    AP_DEBUG_ASSERT(subnet != NULL);
2004
2005
0
    if (!ctx->r)
2006
0
        return FALSE;
2007
2008
0
    return apr_ipsubnet_test(subnet, ctx->r->useragent_addr);
2009
0
}
2010
2011
static int op_T(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
2012
0
{
2013
0
    switch (arg[0]) {
2014
0
    case '\0':
2015
0
        return FALSE;
2016
0
    case 'o':
2017
0
    case 'O':
2018
0
        return strcasecmp(arg, "off") == 0 ? FALSE : TRUE;
2019
0
    case 'n':
2020
0
    case 'N':
2021
0
        return strcasecmp(arg, "no") == 0 ? FALSE : TRUE;
2022
0
    case 'f':
2023
0
    case 'F':
2024
0
        return strcasecmp(arg, "false") == 0 ? FALSE : TRUE;
2025
0
    case '0':
2026
0
        return arg[1] == '\0' ? FALSE : TRUE;
2027
0
    default:
2028
0
        return TRUE;
2029
0
    }
2030
0
}
2031
2032
static int op_fnmatch(ap_expr_eval_ctx_t *ctx, const void *data,
2033
                      const char *arg1, const char *arg2)
2034
0
{
2035
0
    return (APR_SUCCESS == apr_fnmatch(arg2, arg1, APR_FNM_PATHNAME));
2036
0
}
2037
2038
static int op_strmatch(ap_expr_eval_ctx_t *ctx, const void *data,
2039
                       const char *arg1, const char *arg2)
2040
0
{
2041
0
    return (APR_SUCCESS == apr_fnmatch(arg2, arg1, 0));
2042
0
}
2043
2044
static int op_strcmatch(ap_expr_eval_ctx_t *ctx, const void *data,
2045
                        const char *arg1, const char *arg2)
2046
0
{
2047
0
    return (APR_SUCCESS == apr_fnmatch(arg2, arg1, APR_FNM_CASE_BLIND));
2048
0
}
2049
2050
struct expr_provider_single {
2051
    const void *func;
2052
    const char *name;
2053
    ap_expr_lookup_fn_t *arg_parsing_func;
2054
    int restricted;
2055
};
2056
2057
struct expr_provider_multi {
2058
    const void *func;
2059
    const char *const *names;
2060
};
2061
2062
static const struct expr_provider_multi var_providers[] = {
2063
    { misc_var_fn, misc_var_names },
2064
    { req_header_var_fn, req_header_var_names },
2065
    { request_var_fn, request_var_names },
2066
    { conn_var_fn, conn_var_names },
2067
    { NULL, NULL }
2068
};
2069
2070
static const struct expr_provider_single string_func_providers[] = {
2071
    { osenv_func,           "osenv",          NULL, 0 },
2072
    { env_func,             "env",            NULL, 0 },
2073
    { req_table_func,       "resp",           NULL, 0 },
2074
    { req_table_func,       "req",            NULL, 0 },
2075
    /* 'http' as alias for 'req' for compatibility with ssl_expr */
2076
    { req_table_func,       "http",           NULL, 0 },
2077
    { req_table_func,       "note",           NULL, 0 },
2078
    { req_table_func,       "reqenv",         NULL, 0 },
2079
    { req_table_func,       "req_novary",     NULL, 0 },
2080
    { tolower_func,         "tolower",        NULL, 0 },
2081
    { toupper_func,         "toupper",        NULL, 0 },
2082
    { escape_func,          "escape",         NULL, 0 },
2083
    { unescape_func,        "unescape",       NULL, 0 },
2084
    { file_func,            "file",           NULL, 1 },
2085
    { filesize_func,        "filesize",       NULL, 1 },
2086
    { filemod_func,         "filemod",        NULL, 1 },
2087
    { base64_func,          "base64",         NULL, 0 },
2088
    { unbase64_func,        "unbase64",       NULL, 0 },
2089
    { sha1_func,            "sha1",           NULL, 0 },
2090
    { md5_func,             "md5",            NULL, 0 },
2091
#if APR_VERSION_AT_LEAST(1,6,0)
2092
    { ldap_func,            "ldap",           NULL, 0 },
2093
#endif
2094
    { replace_func,         "replace",        replace_func_parse_arg, 0 },
2095
    { NULL, NULL, NULL}
2096
};
2097
2098
static const struct expr_provider_single unary_op_providers[] = {
2099
    { op_nz,        "n", NULL,             0 },
2100
    { op_nz,        "z", NULL,             0 },
2101
    { op_R,         "R", subnet_parse_arg, 0 },
2102
    { op_T,         "T", NULL,             0 },
2103
    { op_file_min,  "d", NULL,             1 },
2104
    { op_file_min,  "e", NULL,             1 },
2105
    { op_file_min,  "f", NULL,             1 },
2106
    { op_file_min,  "s", NULL,             1 },
2107
    { op_file_link, "L", NULL,             1 },
2108
    { op_file_link, "h", NULL,             1 },
2109
    { op_file_xbit, "x", NULL,             1 },
2110
    { op_file_subr, "F", NULL,             0 },
2111
    { op_url_subr,  "U", NULL,             0 },
2112
    { op_url_subr,  "A", NULL,             0 },
2113
    { NULL, NULL, NULL }
2114
};
2115
2116
static const struct expr_provider_single binary_op_providers[] = {
2117
    { op_ipmatch,   "ipmatch",      subnet_parse_arg, 0 },
2118
    { op_fnmatch,   "fnmatch",      NULL,             0 },
2119
    { op_strmatch,  "strmatch",     NULL,             0 },
2120
    { op_strcmatch, "strcmatch",    NULL,             0 },
2121
    { NULL, NULL, NULL }
2122
};
2123
2124
static int core_expr_lookup(ap_expr_lookup_parms *parms)
2125
0
{
2126
0
    switch (parms->type) {
2127
0
    case AP_EXPR_FUNC_VAR: {
2128
0
            const struct expr_provider_multi *prov = var_providers;
2129
0
            while (prov->func) {
2130
0
                const char *const *name = prov->names;
2131
0
                while (*name) {
2132
0
                    if (ap_cstr_casecmp(*name, parms->name) == 0) {
2133
0
                        *parms->func = prov->func;
2134
0
                        *parms->data = name;
2135
0
                        return OK;
2136
0
                    }
2137
0
                    name++;
2138
0
                }
2139
0
                prov++;
2140
0
            }
2141
0
        }
2142
0
        break;
2143
0
    case AP_EXPR_FUNC_STRING:
2144
0
    case AP_EXPR_FUNC_OP_UNARY:
2145
0
    case AP_EXPR_FUNC_OP_BINARY: {
2146
0
            const struct expr_provider_single *prov = NULL;
2147
0
            switch (parms->type) {
2148
0
            case AP_EXPR_FUNC_STRING:
2149
0
                prov = string_func_providers;
2150
0
                break;
2151
0
            case AP_EXPR_FUNC_OP_UNARY:
2152
0
                prov = unary_op_providers;
2153
0
                break;
2154
0
            case AP_EXPR_FUNC_OP_BINARY:
2155
0
                prov = binary_op_providers;
2156
0
                break;
2157
0
            default:
2158
0
                ap_assert(0);
2159
0
            }
2160
0
            while (prov && prov->func) {
2161
0
                int match;
2162
0
                if (parms->type == AP_EXPR_FUNC_OP_UNARY)
2163
0
                    match = !strcmp(prov->name, parms->name);
2164
0
                else
2165
0
                    match = !ap_cstr_casecmp(prov->name, parms->name);
2166
0
                if (match) {
2167
0
                    if ((parms->flags & AP_EXPR_FLAG_RESTRICTED)
2168
0
                        && prov->restricted) {
2169
0
                        *parms->err =
2170
0
                            apr_psprintf(parms->ptemp,
2171
0
                                         "%s%s not available in restricted context",
2172
0
                                         (parms->type == AP_EXPR_FUNC_STRING) ? "" : "-",
2173
0
                                         prov->name);
2174
0
                        return !OK;
2175
0
                    }
2176
0
                    *parms->func = prov->func;
2177
0
                    if (prov->arg_parsing_func) {
2178
0
                        return prov->arg_parsing_func(parms);
2179
0
                    }
2180
0
                    else {
2181
0
                        *parms->data = prov->name;
2182
0
                        return OK;
2183
0
                    }
2184
0
                }
2185
0
                prov++;
2186
0
            }
2187
0
        }
2188
0
        break;
2189
0
    default:
2190
0
        break;
2191
0
    }
2192
0
    return DECLINED;
2193
0
}
2194
2195
static int expr_lookup_not_found(ap_expr_lookup_parms *parms)
2196
0
{
2197
0
    const char *type;
2198
0
    const char *prefix = "";
2199
2200
0
    switch (parms->type) {
2201
0
    case AP_EXPR_FUNC_VAR:
2202
0
        type = "Variable";
2203
0
        break;
2204
0
    case AP_EXPR_FUNC_STRING:
2205
0
        type = "Function";
2206
0
        break;
2207
0
    case AP_EXPR_FUNC_LIST:
2208
0
        type = "List-returning function";
2209
0
        break;
2210
0
    case AP_EXPR_FUNC_OP_UNARY:
2211
0
        type = "Unary operator";
2212
0
        break;
2213
0
    case AP_EXPR_FUNC_OP_BINARY:
2214
0
        type = "Binary operator";
2215
0
        break;
2216
0
    default:
2217
0
        *parms->err = "Invalid expression type in expr_lookup";
2218
0
        return !OK;
2219
0
    }
2220
0
    if (   parms->type == AP_EXPR_FUNC_OP_UNARY
2221
0
        || parms->type == AP_EXPR_FUNC_OP_BINARY) {
2222
0
        prefix = "-";
2223
0
    }
2224
0
    *parms->err = apr_psprintf(parms->ptemp, "%s '%s%s' does not exist", type,
2225
0
                               prefix, parms->name);
2226
0
    return !OK;
2227
0
}
2228
2229
static int ap_expr_post_config(apr_pool_t *pconf, apr_pool_t *plog,
2230
                               apr_pool_t *ptemp, server_rec *s)
2231
0
{
2232
0
    is_http2 = APR_RETRIEVE_OPTIONAL_FN(http2_is_h2);
2233
0
    return OK;
2234
0
}
2235
2236
void ap_expr_init(apr_pool_t *p)
2237
0
{
2238
0
    ap_hook_expr_lookup(core_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE);
2239
0
    ap_hook_expr_lookup(expr_lookup_not_found, NULL, NULL, APR_HOOK_REALLY_LAST);
2240
0
    ap_hook_post_config(ap_expr_post_config, NULL, NULL, APR_HOOK_MIDDLE);
2241
0
}
2242