From: Eric Covener Date: Fri, 5 Jun 2026 10:27:34 +0000 (+0000) Subject: restrict per-dir file funcs centrally X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=0bc2ece957a4461978a5ff14f24182a3be05eed9;p=thirdparty%2Fapache%2Fhttpd.git restrict per-dir file funcs centrally git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1935016 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/ap_expr.h b/include/ap_expr.h index 8923de7db7..4e0c6ec1ef 100644 --- a/include/ap_expr.h +++ b/include/ap_expr.h @@ -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 /** diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 346c504f9a..c89b2adc78 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -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 " diff --git a/modules/metadata/mod_setenvif.c b/modules/metadata/mod_setenvif.c index 89dd394e74..87f11dd4ce 100644 --- a/modules/metadata/mod_setenvif.c +++ b/modules/metadata/mod_setenvif.c @@ -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, diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c index af3fb896bc..f9b28dc788 100644 --- a/modules/proxy/mod_proxy_fcgi.c +++ b/modules/proxy/mod_proxy_fcgi.c @@ -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) { diff --git a/server/util_expr_eval.c b/server/util_expr_eval.c index 603ade679c..82f3288a2c 100644 --- a/server/util_expr_eval.c +++ b/server/util_expr_eval.c @@ -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",