diff --git a/SOURCES/httpd-2.4.37-CVE-2023-25690.patch b/SOURCES/httpd-2.4.37-CVE-2023-25690.patch index 878d6e6..5b24a06 100644 --- a/SOURCES/httpd-2.4.37-CVE-2023-25690.patch +++ b/SOURCES/httpd-2.4.37-CVE-2023-25690.patch @@ -1,5 +1,28 @@ +diff --git a/docs/manual/mod/mod_rewrite.html.en b/docs/manual/mod/mod_rewrite.html.en +index 815ec72..2b8ed35 100644 +--- a/docs/manual/mod/mod_rewrite.html.en ++++ b/docs/manual/mod/mod_rewrite.html.en +@@ -1265,7 +1265,17 @@ cannot use $N in the substitution string! + B + Escape non-alphanumeric characters in backreferences before + applying the transformation. details ... +- ++ ++ ++ BCTLS ++ Like [B], but only escape control characters and spaces. ++ details ... ++ ++ ++ BNE ++ Characters of [B] or [BCTLS] which should not be escaped. ++ details ... ++ + + backrefnoplus|BNP + If backreferences are being escaped, spaces should be escaped to diff --git a/docs/manual/rewrite/flags.html.en b/docs/manual/rewrite/flags.html.en -index 80d0759..9673094 100644 +index 80d0759..21edfe7 100644 --- a/docs/manual/rewrite/flags.html.en +++ b/docs/manual/rewrite/flags.html.en @@ -85,10 +85,6 @@ of how you might use them.

@@ -13,7 +36,7 @@ index 80d0759..9673094 100644

mod_rewrite has to unescape URLs before mapping them, so backreferences are unescaped at the time they are applied. -@@ -120,6 +116,16 @@ when the backend may break if presented with an unescaped URL.

+@@ -120,6 +116,20 @@ when the backend may break if presented with an unescaped URL.

An alternative to this flag is using a RewriteCond to capture against %{THE_REQUEST} which will capture strings in the encoded form.

@@ -24,25 +47,266 @@ index 80d0759..9673094 100644 +the entire third argument of RewriteRule +and the space must not be the last character in the list.

+ -+
# Escape spaces and question marks.
++
# Escape spaces and question marks.  The quotes around the final argument
++# are required when a space is included.
 +RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B= ?]"
++ ++

To limit the characters escaped this way, see #flag_bne ++and #flag_bctls

+
top

BNP|backrefnoplus (don't escape space to +)

+@@ -127,8 +137,40 @@ strings in the encoded form.

+ in a backreference to %20 rather than '+'. Useful when the backreference + will be used in the path component rather than the query string.

+ ++
++# Escape spaces to %20 in the path instead of + as used in form submission via
++# the query string
++RewriteRule "^search/(.*)$" "/search.php/$1" "[B,BNP]"
++
++ +

This flag is available in version 2.4.26 and later.

+ ++
top
++
++

BCTLS

++

The [BCTLS] flag is similar to the [B] flag, but only escapes ++control characters and the space character. This is the same set of ++characters rejected when they are copied into the query string unencoded. ++

++ ++
++# Escape control characters and spaces
++RewriteRule "^search/(.*)$" "/search.php/$1" "[BCTLS]"
++
++ ++
top
++
++

BNE

++

The list of characters in [BNE=...] are treated as exclusions to the ++characters of the [B] or [BCTLS] flags. The listed characters will not be ++escaped. ++

++ ++
++# Escape the default characters, but leave /
++RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B,BNE=/]"
++
++ +
top
+
+

C|chain

+@@ -204,7 +246,7 @@ browsers that support this feature. +

Consider this example:

+ +
RewriteEngine On
+-RewriteRule "^/index\.html" "-" [CO=frontdoor:yes:.example.com:1440:/]
++RewriteRule "^/index\.html" "-" [CO=frontdoor:yes:.example.com:1440:/]
+ + +

In the example give, the rule doesn't rewrite the request. +@@ -410,8 +452,8 @@ argument to index.php, however, the index.php, the RewriteRule will be skipped.

+ +
RewriteBase "/"
+-RewriteCond "%{REQUEST_URI}" "!=/index.php"
+-RewriteRule "^(.*)" "/index.php?req=$1" [L,PT]
++RewriteCond "%{REQUEST_URI}" !=/index.php ++RewriteRule "^(.*)" "/index.php?req=$1" [L,PT] + +
top
+
+@@ -434,11 +476,11 @@ pattern still matches (i.e., while the URI still contains an + A), perform this substitution (i.e., replace the + A with a B).

+ +-

In 2.4.8 and later, this module returns an error after 32,000 iterations to ++

In 2.4.8 and later, this module returns an error after 10,000 iterations to + protect against unintended looping. An alternative maximum number of + iterations can be specified by adding to the N flag.

+
# Be willing to replace 1 character in each pass of the loop
+-RewriteRule "(.+)[><;]$" "$1" [N=64000]
++RewriteRule "(.+)[><;]$" "$1" [N=32000]
+ # ... or, give up if after 10 loops
+ RewriteRule "(.+)[><;]$" "$1" [N=10]
+ +@@ -681,19 +723,21 @@ URI in request' warnings. +

The [S] flag is used to skip rules that you don't want to run. The + syntax of the skip flag is [S=N], where N signifies + the number of rules to skip (provided the +-RewriteRule matches). This can be thought of as a goto +-statement in your rewrite ruleset. In the following example, we only want +-to run the RewriteRule if the +-requested URI doesn't correspond with an actual file.

++RewriteRule and any preceding ++RewriteCond directives match). This can be thought of as a ++goto statement in your rewrite ruleset. In the following ++example, we only want to run the ++RewriteRule if the requested URI doesn't correspond with an ++actual file.

+ +
# Is the request for a non-existent file?
+-RewriteCond "%{REQUEST_FILENAME}" "!-f"
+-RewriteCond "%{REQUEST_FILENAME}" "!-d"
++RewriteCond "%{REQUEST_FILENAME}" !-f
++RewriteCond "%{REQUEST_FILENAME}" !-d
+ # If so, skip these two RewriteRules
+-RewriteRule ".?" "-" [S=2]
++RewriteRule ".?"                  "-" [S=2]
+ 
+-RewriteRule "(.*\.gif)" "images.php?$1"
+-RewriteRule "(.*\.html)" "docs.php?$1"
++RewriteRule "(.*\.gif)" "images.php?$1" ++RewriteRule "(.*\.html)" "docs.php?$1" + + +

This technique is useful because a RewriteCond only applies to the +@@ -705,18 +749,18 @@ use this to make pseudo if-then-else constructs: The last rule of + the then-clause becomes skip=N, where N is the + number of rules in the else-clause:

+
# Does the file exist?
+-RewriteCond "%{REQUEST_FILENAME}" "!-f"
+-RewriteCond "%{REQUEST_FILENAME}" "!-d"
++RewriteCond "%{REQUEST_FILENAME}" !-f
++RewriteCond "%{REQUEST_FILENAME}" !-d
+ # Create an if-then-else construct by skipping 3 lines if we meant to go to the "else" stanza.
+-RewriteRule ".?" "-" [S=3]
++RewriteRule ".?"                  "-" [S=3]
+ 
+ # IF the file exists, then:
+-    RewriteRule "(.*\.gif)" "images.php?$1"
++    RewriteRule "(.*\.gif)"  "images.php?$1"
+     RewriteRule "(.*\.html)" "docs.php?$1"
+     # Skip past the "else" stanza.
+-    RewriteRule ".?" "-" [S=1]
++    RewriteRule ".?"         "-" [S=1]
+ # ELSE...
+-    RewriteRule "(.*)" "404.php?file=$1"
++    RewriteRule "(.*)"       "404.php?file=$1"
+ # END
+ + +@@ -733,7 +777,7 @@ sent. This has the same effect as the # Serve .pl files as plain text +-RewriteRule "\.pl$" "-" [T=text/plain] ++RewriteRule "\.pl$" "-" [T=text/plain] + + +

Or, perhaps, if you have a camera that produces jpeg images without +@@ -741,7 +785,7 @@ file extensions, you could force those images to be served with the + correct MIME type by virtue of their file names:

+ +
# Files with 'IMG' in the name are jpg images.
+-RewriteRule "IMG" "-" [T=image/jpg]
++RewriteRule "IMG" "-" [T=image/jpg] + + +

Please note that this is a trivial example, and could be better done diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c -index 38dbb24..c3937ad 100644 +index 38dbb24..b71c67c 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c -@@ -168,6 +168,7 @@ static const char* really_last_key = "rewrite_really_last"; +@@ -101,6 +101,8 @@ + #include "mod_rewrite.h" + #include "ap_expr.h" + ++#include "test_char.h" ++ + static ap_dbd_t *(*dbd_acquire)(request_rec*) = NULL; + static void (*dbd_prepare)(server_rec*, const char*, const char*) = NULL; + static const char* really_last_key = "rewrite_really_last"; +@@ -168,6 +170,8 @@ static const char* really_last_key = "rewrite_really_last"; #define RULEFLAG_END (1<<17) #define RULEFLAG_ESCAPENOPLUS (1<<18) #define RULEFLAG_QSLAST (1<<19) +#define RULEFLAG_QSNONE (1<<20) /* programattic only */ ++#define RULEFLAG_ESCAPECTLS (1<<21) /* return code of the rewrite rule * the result may be escaped - or not -@@ -761,15 +762,24 @@ static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme) +@@ -321,7 +325,8 @@ typedef struct { + data_item *cookie; /* added cookies */ + int skip; /* number of next rules to skip */ + int maxrounds; /* limit on number of loops with N flag */ +- char *escapes; /* specific backref escapes */ ++ const char *escapes; /* specific backref escapes */ ++ const char *noescapes; /* specific backref chars not to escape */ + } rewriterule_entry; + + typedef struct { +@@ -422,7 +427,9 @@ static const char *rewritemap_mutex_type = "rewrite-map"; + /* Optional functions imported from mod_ssl when loaded: */ + static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *rewrite_ssl_lookup = NULL; + static APR_OPTIONAL_FN_TYPE(ssl_is_https) *rewrite_is_https = NULL; +-static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus); ++static char *escape_backref(apr_pool_t *p, const char *path, ++ const char *escapeme, const char *noescapeme, ++ int flags); + + /* + * +-------------------------------------------------------+ +@@ -645,18 +652,26 @@ static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix, + return where; + } + ++ + /* + * Escapes a backreference in a similar way as php's urlencode does. + * Based on ap_os_escape_path in server/util.c + */ +-static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus) { +- char *copy = apr_palloc(p, 3 * strlen(path) + 3); ++static char *escape_backref(apr_pool_t *p, const char *path, ++ const char *escapeme, const char *noescapeme, ++ int flags) ++{ ++ char *copy = apr_palloc(p, 3 * strlen(path) + 1); + const unsigned char *s = (const unsigned char *)path; + unsigned char *d = (unsigned char *)copy; +- unsigned c; ++ int noplus = (flags & RULEFLAG_ESCAPENOPLUS) != 0; ++ int ctls = (flags & RULEFLAG_ESCAPECTLS) != 0; ++ unsigned char c; + + while ((c = *s)) { +- if (!escapeme) { ++ if (((ctls ? !TEST_CHAR(c, T_VCHAR_OBSTEXT) : !escapeme) ++ || (escapeme && ap_strchr_c(escapeme, c))) ++ && (!noescapeme || !ap_strchr_c(noescapeme, c))) { + if (apr_isalnum(c) || c == '_') { + *d++ = c; + } +@@ -667,23 +682,8 @@ static char *escape_backref(apr_pool_t *p, const char *path, const char *escapem + d = c2x(c, '%', d); + } + } +- else { +- const char *esc = escapeme; +- while (*esc) { +- if (c == *esc) { +- if (c == ' ' && !noplus) { +- *d++ = '+'; +- } +- else { +- d = c2x(c, '%', d); +- } +- break; +- } +- ++esc; +- } +- if (!*esc) { +- *d++ = c; +- } ++ else { ++ *d++ = c; + } + ++s; + } +@@ -761,15 +761,24 @@ static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme) ap_escape_uri(p, cp), NULL); } @@ -69,7 +333,7 @@ index 38dbb24..c3937ad 100644 /* don't touch, unless it's a scheme for which a query string makes sense. * See RFC 1738 and RFC 2368. -@@ -794,7 +804,7 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, +@@ -794,7 +803,7 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, olduri = apr_pstrdup(r->pool, r->filename); *q++ = '\0'; if (qsappend) { @@ -78,7 +342,7 @@ index 38dbb24..c3937ad 100644 r->args = apr_pstrcat(r->pool, q, "&" , r->args, NULL); } } -@@ -802,9 +812,9 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, +@@ -802,9 +811,9 @@ static void splitout_queryargs(request_rec *r, int qsappend, int qsdiscard, r->args = apr_pstrdup(r->pool, q); } @@ -90,6 +354,16 @@ index 38dbb24..c3937ad 100644 if (!len) { r->args = NULL; } +@@ -2436,7 +2445,8 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) + /* escape the backreference */ + char *tmp2, *tmp; + tmp = apr_pstrmemdup(pool, bri->source + bri->regmatch[n].rm_so, span); +- tmp2 = escape_backref(pool, tmp, entry->escapes, entry->flags & RULEFLAG_ESCAPENOPLUS); ++ tmp2 = escape_backref(pool, tmp, entry->escapes, entry->noescapes, ++ entry->flags); + rewritelog((ctx->r, 5, ctx->perdir, "escaping backreference '%s' to '%s'", + tmp, tmp2)); + @@ -2733,7 +2743,7 @@ static apr_status_t rewritelock_remove(void *data) * XXX: what an inclined parser. Seems we have to leave it so * for backwards compat. *sigh* @@ -128,7 +402,33 @@ index 38dbb24..c3937ad 100644 return apr_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str, "'", NULL); } -@@ -3749,7 +3761,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, +@@ -3500,13 +3512,24 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg, + case 'B': + if (!*key || !strcasecmp(key, "ackrefescaping")) { + cfg->flags |= RULEFLAG_ESCAPEBACKREF; +- if (val && *val) { ++ if (val && *val) { + cfg->escapes = val; + } + } ++ else if (!strcasecmp(key, "NE")) { ++ if (val && *val) { ++ cfg->noescapes = val; ++ } ++ else { ++ return "flag 'BNE' wants a list of characters (i.e. [BNE=...])"; ++ } ++ } + else if (!strcasecmp(key, "NP") || !strcasecmp(key, "ackrefernoplus")) { + cfg->flags |= RULEFLAG_ESCAPENOPLUS; + } ++ else if (!strcasecmp(key, "CTLS")) { ++ cfg->flags |= RULEFLAG_ESCAPECTLS|RULEFLAG_ESCAPEBACKREF; ++ } + else { + ++error; + } +@@ -3749,7 +3772,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, rewrite_server_conf *sconf; rewriterule_entry *newrule; ap_regex_t *regexp; @@ -137,7 +437,7 @@ index 38dbb24..c3937ad 100644 const char *err; sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module); -@@ -3763,7 +3775,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, +@@ -3763,12 +3786,11 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, } /* parse the argument line ourself */ @@ -146,13 +446,29 @@ index 38dbb24..c3937ad 100644 return apr_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str, "'", NULL); } -@@ -3810,6 +3822,16 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, + +- /* arg3: optional flags field */ + newrule->forced_mimetype = NULL; + newrule->forced_handler = NULL; + newrule->forced_responsecode = HTTP_MOVED_TEMPORARILY; +@@ -3777,6 +3799,9 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, + newrule->cookie = NULL; + newrule->skip = 0; + newrule->maxrounds = REWRITE_MAX_ROUNDS; ++ newrule->escapes = newrule->noescapes = NULL; ++ ++ /* arg3: optional flags field */ + if (a3 != NULL) { + if ((err = cmd_parseflagfield(cmd->pool, newrule, a3, + cmd_rewriterule_setflag)) != NULL) { +@@ -3810,6 +3835,17 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf, newrule->flags |= RULEFLAG_NOSUB; } + if (*(a2_end-1) == '?') { + /* a literal ? at the end of the unsubstituted rewrite rule */ + newrule->flags |= RULEFLAG_QSNONE; ++ *(a2_end-1) = '\0'; /* trailing ? has done its job */ + } + else if (newrule->flags & RULEFLAG_QSDISCARD) { + if (NULL == ap_strchr(newrule->output, '?')) { @@ -163,7 +479,7 @@ index 38dbb24..c3937ad 100644 /* now, if the server or per-dir config holds an * array of RewriteCond entries, we take it for us * and clear the array -@@ -4215,9 +4237,7 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx) +@@ -4215,9 +4251,7 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx) r->path_info = NULL; } @@ -174,29 +490,78 @@ index 38dbb24..c3937ad 100644 /* Add the previously stripped per-directory location prefix, unless * (1) it's an absolute URL path and -@@ -4699,6 +4719,17 @@ static int hook_uri2file(request_rec *r) - unsigned skip; - apr_size_t flen; +@@ -4696,8 +4730,25 @@ static int hook_uri2file(request_rec *r) + } -+ if (r->args && *(ap_scan_vchar_obstext(r->args))) { + if (rulestatus) { +- unsigned skip; +- apr_size_t flen; ++ unsigned skip_absolute = is_absolute_uri(r->filename, NULL); ++ apr_size_t flen = r->filename ? strlen(r->filename) : 0; ++ int to_proxyreq = (flen > 6 && strncmp(r->filename, "proxy:", 6) == 0); ++ int will_escape = skip_absolute && (rulestatus != ACTION_NOESCAPE); ++ ++ if (r->args ++ && !will_escape ++ && *(ap_scan_vchar_obstext(r->args))) { + /* + * We have a raw control character or a ' ' in r->args. + * Correct encoding was missed. ++ * Correct encoding was missed and we're not going to escape ++ * it before returning. + */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10410) + "Rewritten query string contains control " + "characters or spaces"); + return HTTP_FORBIDDEN; + } -+ + if (ACTION_STATUS == rulestatus) { int n = r->status; +@@ -4706,8 +4757,7 @@ static int hook_uri2file(request_rec *r) + return n; + } -@@ -4983,6 +5014,17 @@ static int hook_fixup(request_rec *r) +- flen = r->filename ? strlen(r->filename) : 0; +- if (flen > 6 && strncmp(r->filename, "proxy:", 6) == 0) { ++ if (to_proxyreq) { + /* it should be go on as an internal proxy request */ + + /* check if the proxy module is enabled, so +@@ -4749,7 +4799,7 @@ static int hook_uri2file(request_rec *r) + r->filename)); + return OK; + } +- else if ((skip = is_absolute_uri(r->filename, NULL)) > 0) { ++ else if (skip_absolute > 0) { + int n; + + /* it was finally rewritten to a remote URL */ +@@ -4757,7 +4807,7 @@ static int hook_uri2file(request_rec *r) + if (rulestatus != ACTION_NOESCAPE) { + rewritelog((r, 1, NULL, "escaping %s for redirect", + r->filename)); +- r->filename = escape_absolute_uri(r->pool, r->filename, skip); ++ r->filename = escape_absolute_uri(r->pool, r->filename, skip_absolute); + } + + /* append the QUERY_STRING part */ +@@ -4981,7 +5031,26 @@ static int hook_fixup(request_rec *r) + */ + rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory); if (rulestatus) { - unsigned skip; - -+ if (r->args && *(ap_scan_vchar_obstext(r->args))) { +- unsigned skip; ++ unsigned skip_absolute = is_absolute_uri(r->filename, NULL); ++ int to_proxyreq = 0; ++ int will_escape = 0; ++ ++ l = strlen(r->filename); ++ to_proxyreq = l > 6 && strncmp(r->filename, "proxy:", 6) == 0; ++ will_escape = skip_absolute && (rulestatus != ACTION_NOESCAPE); ++ ++ if (r->args ++ && !will_escape ++ && *(ap_scan_vchar_obstext(r->args))) { + /* + * We have a raw control character or a ' ' in r->args. + * Correct encoding was missed. @@ -206,12 +571,48 @@ index 38dbb24..c3937ad 100644 + "characters or spaces"); + return HTTP_FORBIDDEN; + } -+ + if (ACTION_STATUS == rulestatus) { int n = r->status; +@@ -4990,8 +5059,7 @@ static int hook_fixup(request_rec *r) + return n; + } +- l = strlen(r->filename); +- if (l > 6 && strncmp(r->filename, "proxy:", 6) == 0) { ++ if (to_proxyreq) { + /* it should go on as an internal proxy request */ + + /* make sure the QUERY_STRING and +@@ -5015,7 +5083,7 @@ static int hook_fixup(request_rec *r) + "%s [OK]", r->filename)); + return OK; + } +- else if ((skip = is_absolute_uri(r->filename, NULL)) > 0) { ++ else if (skip_absolute > 0) { + /* it was finally rewritten to a remote URL */ + + /* because we are in a per-dir context +@@ -5024,7 +5092,7 @@ static int hook_fixup(request_rec *r) + */ + if (dconf->baseurl != NULL) { + /* skip 'scheme://' */ +- cp = r->filename + skip; ++ cp = r->filename + skip_absolute; + + if ((cp = ap_strchr(cp, '/')) != NULL && *(++cp)) { + rewritelog((r, 2, dconf->directory, +@@ -5069,7 +5137,7 @@ static int hook_fixup(request_rec *r) + if (rulestatus != ACTION_NOESCAPE) { + rewritelog((r, 1, dconf->directory, "escaping %s for redirect", + r->filename)); +- r->filename = escape_absolute_uri(r->pool, r->filename, skip); ++ r->filename = escape_absolute_uri(r->pool, r->filename, skip_absolute); + } + + /* append the QUERY_STRING part */ diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c -index 058b03f..a529c02 100644 +index 6faabea..59396a8 100644 --- a/modules/proxy/mod_proxy_ajp.c +++ b/modules/proxy/mod_proxy_ajp.c @@ -69,6 +69,16 @@ static int proxy_ajp_canon(request_rec *r, char *url) @@ -253,7 +654,7 @@ index 3a28038..c599e1a 100644 if (path == NULL) return HTTP_BAD_REQUEST; diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c -index c1c591a..58a8c86 100644 +index 7da9bde..2cdc61e 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -90,6 +90,16 @@ static int proxy_http_canon(request_rec *r, char *url) @@ -294,3 +695,41 @@ index e005a94..f5e27d9 100644 } if (path == NULL) return HTTP_BAD_REQUEST; +diff --git a/server/gen_test_char.c b/server/gen_test_char.c +index 48ae6f4..6a153a3 100644 +--- a/server/gen_test_char.c ++++ b/server/gen_test_char.c +@@ -169,5 +169,15 @@ int main(int argc, char *argv[]) + + printf("\n};\n"); + ++ ++ printf( ++ "/* we assume the folks using this ensure 0 <= c < 256... which means\n" ++ " * you need a cast to (unsigned char) first, you can't just plug a\n" ++ " * char in here and get it to work, because if char is signed then it\n" ++ " * will first be sign extended.\n" ++ " */\n" ++ "#define TEST_CHAR(c, f) (test_char_table[(unsigned char)(c)] & (f))\n" ++ ); ++ + return 0; + } +diff --git a/server/util.c b/server/util.c +index 2a5dd04..1d82fd8 100644 +--- a/server/util.c ++++ b/server/util.c +@@ -74,13 +74,6 @@ + */ + #include "test_char.h" + +-/* we assume the folks using this ensure 0 <= c < 256... which means +- * you need a cast to (unsigned char) first, you can't just plug a +- * char in here and get it to work, because if char is signed then it +- * will first be sign extended. +- */ +-#define TEST_CHAR(c, f) (test_char_table[(unsigned char)(c)] & (f)) +- + /* Win32/NetWare/OS2 need to check for both forward and back slashes + * in ap_getparents() and ap_escape_url. + */ diff --git a/SPECS/httpd.spec b/SPECS/httpd.spec index 8493acc..6a8ef49 100644 --- a/SPECS/httpd.spec +++ b/SPECS/httpd.spec @@ -13,7 +13,7 @@ Summary: Apache HTTP Server Name: httpd Version: 2.4.37 -Release: 56%{?dist}.4 +Release: 56%{?dist}.6 URL: https://httpd.apache.org/ Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2 Source2: httpd.logrotate @@ -974,6 +974,9 @@ rm -rf $RPM_BUILD_ROOT %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Thu Apr 27 2023 Luboš Uhliarik - 2.4.37-56.6 +- Resolves: #2190133 - mod_rewrite regression with CVE-2023-25690 + * Sat Mar 18 2023 Luboš Uhliarik - 2.4.37-56.4 - Resolves: #2177748 - CVE-2023-25690 httpd:2.4/httpd: HTTP request splitting with mod_rewrite and mod_proxy