]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
restrict per-dir file funcs centrally
authorEric Covener <covener@apache.org>
Fri, 5 Jun 2026 10:27:34 +0000 (10:27 +0000)
committerEric Covener <covener@apache.org>
Fri, 5 Jun 2026 10:27:34 +0000 (10:27 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1935016 13f79535-47bb-0310-9956-ffa450edef68

include/ap_expr.h
modules/mappers/mod_rewrite.c
modules/metadata/mod_setenvif.c
modules/proxy/mod_proxy_fcgi.c
server/util_expr_eval.c

index 8923de7db7964349dac6cbd10232ace6e6f2bb26..4e0c6ec1efef33093ef84a035e1623e0980a9058 100644 (file)
@@ -66,6 +66,8 @@ typedef struct {
 #define AP_EXPR_FLAG_RESTRICTED            4
 /** Expression evaluates to a string, not to a bool */
 #define AP_EXPR_FLAG_STRING_RESULT         8
+/** Don't allow functions/vars that expose content from the filesystem. */
+#define AP_EXPR_FLAG_RESTRICTED_FILE_FUNC   16
 
 
 /**
index 346c504f9a655c4a94a7c1dcab212d1855c6b916..c89b2adc786985c31d2c685ea7c5c87e315f93dc 100644 (file)
@@ -3689,8 +3689,6 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
         int in_htaccess = cmd->pool == cmd->temp_pool;
         unsigned int flags = newcond->flags & CONDFLAG_NOVARY ?
                              AP_EXPR_FLAG_DONT_VARY : 0;
-        /* Use restricted ap_expr() parser in htaccess context. */
-        if (in_htaccess) flags |= AP_EXPR_FLAG_RESTRICTED;
         newcond->expr = ap_expr_parse_cmd(cmd, a2, flags, &err, NULL);
         if (err)
             return apr_psprintf(cmd->pool, "RewriteCond: cannot compile "
index 89dd394e74df6e735a0a3f5eefab734acd532a26..87f11dd4ce4aa3ba22415b537be82d886f6f6580 100644 (file)
@@ -437,11 +437,6 @@ static const char *add_setenvifexpr(cmd_parms *cmd, void *mconfig,
     const char *err;
     unsigned int flags = 0;
 
-    /* Use restricted ap_expr() parser in htaccess context. */
-    if (cmd->pool == cmd->temp_pool) {
-        flags |= AP_EXPR_FLAG_RESTRICTED;
-    }
-
     /*
      * Determine from our context into which record to put the entry.
      * cmd->path == NULL means we're in server-wide context; otherwise,
index af3fb896bc0c63881f618c2246ade783270283bd..f9b28dc7889765dcb22431779ec40e86333030bd 100644 (file)
@@ -1344,11 +1344,6 @@ static const char *cmd_setenv(cmd_parms *cmd, void *in_dconf,
     const char *envvar = arg2;
     unsigned int flags = 0;
 
-    /* Use restricted ap_expr() parser in htaccess context. */
-    if (cmd->pool == cmd->temp_pool) {
-        flags |= AP_EXPR_FLAG_RESTRICTED;
-    }
-
     new = apr_array_push(dconf->env_fixups);
     new->cond = ap_expr_parse_cmd(cmd, arg1, flags, &err, NULL);
     if (err) {
index 603ade679cc9b0240c8a4b04a8e7fd5a76a18930..82f3288a2c16e6a3149ff79ea313f06fa5f6954e 100644 (file)
@@ -639,6 +639,12 @@ AP_DECLARE(ap_expr_info_t*) ap_expr_parse_cmd_mi(const cmd_parms *cmd,
     info->line_number = cmd->directive->line_num;
     info->flags = flags;
     info->module_index = module_index;
+
+    /* Use restricted-contents ap_expr() parser in htaccess context. */
+    if (cmd->pool == cmd->temp_pool) {
+        info->flags |= AP_EXPR_FLAG_RESTRICTED_FILE_FUNC;
+    }
+
     *err = ap_expr_parse(cmd->pool, cmd->temp_pool, info, expr, lookup_fn);
 
     if (*err)
@@ -2079,11 +2085,15 @@ static int op_strcmatch(ap_expr_eval_ctx_t *ctx, const void *data,
     return (APR_SUCCESS == apr_fnmatch(arg2, arg1, APR_FNM_CASE_BLIND));
 }
 
+#define RESTRICTED_FILE_TEST 0x01
+#define RESTRICTED_FILE_FUNC 0x02
+#define RESTRICTED_ALL      (RESTRICTED_FILE_TEST | RESTRICTED_FILE_FUNC)
+
 struct expr_provider_single {
     const void *func;
     const char *name;
     ap_expr_lookup_fn_t *arg_parsing_func;
-    int restricted;
+    unsigned int restricted;
 };
 
 struct expr_provider_multi {
@@ -2113,9 +2123,9 @@ static const struct expr_provider_single string_func_providers[] = {
     { toupper_func,         "toupper",        NULL, 0 },
     { escape_func,          "escape",         NULL, 0 },
     { unescape_func,        "unescape",       NULL, 0 },
-    { file_func,            "file",           NULL, 1 },
-    { filesize_func,        "filesize",       NULL, 1 },
-    { filemod_func,         "filemod",        NULL, 1 },
+    { file_func,            "file",           NULL, RESTRICTED_FILE_FUNC },
+    { filesize_func,        "filesize",       NULL, RESTRICTED_FILE_FUNC },
+    { filemod_func,         "filemod",        NULL, RESTRICTED_FILE_FUNC },
     { base64_func,          "base64",         NULL, 0 },
     { unbase64_func,        "unbase64",       NULL, 0 },
     { sha1_func,            "sha1",           NULL, 0 },
@@ -2133,13 +2143,13 @@ static const struct expr_provider_single unary_op_providers[] = {
     { op_nz,        "z", NULL,             0 },
     { op_R,         "R", subnet_parse_arg, 0 },
     { op_T,         "T", NULL,             0 },
-    { op_file_min,  "d", NULL,             1 },
-    { op_file_min,  "e", NULL,             1 },
-    { op_file_min,  "f", NULL,             1 },
-    { op_file_min,  "s", NULL,             1 },
-    { op_file_link, "L", NULL,             1 },
-    { op_file_link, "h", NULL,             1 },
-    { op_file_xbit, "x", NULL,             1 },
+    { op_file_min,  "d", NULL,             RESTRICTED_FILE_TEST },
+    { op_file_min,  "e", NULL,             RESTRICTED_FILE_TEST },
+    { op_file_min,  "f", NULL,             RESTRICTED_FILE_TEST },
+    { op_file_min,  "s", NULL,             RESTRICTED_FILE_TEST },
+    { op_file_link, "L", NULL,             RESTRICTED_FILE_TEST },
+    { op_file_link, "h", NULL,             RESTRICTED_FILE_TEST },
+    { op_file_xbit, "x", NULL,             RESTRICTED_FILE_TEST },
     { op_file_subr, "F", NULL,             0 },
     { op_url_subr,  "U", NULL,             0 },
     { op_url_subr,  "A", NULL,             0 },
@@ -2197,8 +2207,10 @@ static int core_expr_lookup(ap_expr_lookup_parms *parms)
                 else
                     match = !ap_cstr_casecmp(prov->name, parms->name);
                 if (match) {
-                    if ((parms->flags & AP_EXPR_FLAG_RESTRICTED)
-                        && prov->restricted) {
+                    if (((parms->flags & AP_EXPR_FLAG_RESTRICTED)
+                         && (prov->restricted & RESTRICTED_ALL))
+                        || ((parms->flags & AP_EXPR_FLAG_RESTRICTED_FILE_FUNC)
+                            && (prov->restricted & RESTRICTED_FILE_FUNC))) {
                         *parms->err =
                             apr_psprintf(parms->ptemp,
                                          "%s%s not available in restricted context",