From: Eric Covener Date: Fri, 5 Jun 2026 10:28:53 +0000 (+0000) Subject: Merge r1935016 from trunk: X-Git-Tag: 2.4.68-rc1-candidate~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f63f26aff6aa747357b84b5bd09c45325fa7f9ba;p=thirdparty%2Fapache%2Fhttpd.git Merge r1935016 from trunk: restrict per-dir file funcs centrally Reviewed By: covener, jorton, jfclere git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1935017 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/ap_expr.h b/include/ap_expr.h index 8e57fcdadc..16138c9f6c 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 9b1c5b4b6a..f1bc03cb2e 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -3682,8 +3682,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 b74c9c07dd..0f44e0d01b 100644 --- a/modules/metadata/mod_setenvif.c +++ b/modules/metadata/mod_setenvif.c @@ -424,11 +424,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 ef090ddc77..82e0c1e421 100644 --- a/modules/proxy/mod_proxy_fcgi.c +++ b/modules/proxy/mod_proxy_fcgi.c @@ -1340,11 +1340,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 038d5a06d7..d4cbf92c76 100644 --- a/server/util_expr_eval.c +++ b/server/util_expr_eval.c @@ -437,6 +437,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) @@ -1661,11 +1667,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 { @@ -1695,8 +1705,8 @@ 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 }, + { file_func, "file", NULL, RESTRICTED_FILE_FUNC }, + { filesize_func, "filesize", NULL, RESTRICTED_FILE_FUNC }, { base64_func, "base64", NULL, 0 }, { unbase64_func, "unbase64", NULL, 0 }, { sha1_func, "sha1", NULL, 0 }, @@ -1712,13 +1722,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 }, @@ -1776,8 +1786,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",