From: Moritz Schlarb <schlarbm@uni-mainz.de>
Author: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
Date: Tue, 20 Dec 2022 12:04:24 +0100
Subject: Fix CVE-2022-23527: prevent open redirect

- CVE-2022-23527: prevent open redirect in default setup when OIDCRedirectURLsAllowed is not configured
  see: https://github.com/zmartzone/mod_auth_openidc/security/advisories/GHSA-q6f2-285m-gr53

Origin: backport, https://github.com/zmartzone/mod_auth_openidc/commit/87119f44b9a88312dbc1f752d720bcd2371b94a8
Forwarded: not-needed
---
 src/mod_auth_openidc.c | 14 ++++++++++++++
 src/mod_auth_openidc.h |  1 +
 src/util.c             | 18 ++++++++++++++++++
 3 files changed, 33 insertions(+)

diff --git a/src/mod_auth_openidc.c b/src/mod_auth_openidc.c
index b36f6c1..099c716 100644
--- a/src/mod_auth_openidc.c
+++ b/src/mod_auth_openidc.c
@@ -2543,6 +2543,20 @@ static apr_byte_t oidc_validate_redirect_url(request_rec *r, oidc_cfg *c,
 		oidc_error(r, "%s: %s", *err_str, *err_desc);
 		return FALSE;
 	}
+	if (       (strstr(url, "/%09") != NULL) || (oidc_util_strcasestr(url, "/%2f") != NULL)
+			|| (strstr(url, "/\t") != NULL)
+			|| (strstr(url, "/%68") != NULL) || (oidc_util_strcasestr(url, "/http:") != NULL)
+			|| (oidc_util_strcasestr(url, "/https:") != NULL) || (oidc_util_strcasestr(url, "/javascript:") != NULL)
+			|| (strstr(url, "/〱") != NULL) || (strstr(url, "/〵") != NULL)
+			|| (strstr(url, "/ゝ") != NULL) || (strstr(url, "/ー") != NULL)
+			|| (strstr(url, "/〱") != NULL) || (strstr(url, "/ｰ") != NULL)
+			|| (strstr(url, "/<") != NULL) || (oidc_util_strcasestr(url, "%01javascript:") != NULL)
+			|| (strstr(url, "/%5c") != NULL) || (strstr(url, "/\\") != NULL)) {
+		*err_str = apr_pstrdup(r->pool, "Invalid URL");
+		*err_desc = apr_psprintf(r->pool, "URL value \"%s\" contains illegal character(s)", url);
+		oidc_error(r, "%s: %s", *err_str, *err_desc);
+		return FALSE;
+	}
 
 	return TRUE;
 }
diff --git a/src/mod_auth_openidc.h b/src/mod_auth_openidc.h
index 2218d76..8757411 100644
--- a/src/mod_auth_openidc.h
+++ b/src/mod_auth_openidc.h
@@ -800,6 +800,7 @@ char *oidc_util_http_query_encoded_url(request_rec *r, const char *url, const ap
 char *oidc_util_get_full_path(apr_pool_t *pool, const char *abs_or_rel_filename);
 apr_byte_t oidc_enabled(request_rec *r);
 char *oidc_util_http_form_encoded_data(request_rec *r, const apr_table_t *params);
+char* oidc_util_strcasestr(const char *s1, const char *s2);
 
 /* HTTP header constants */
 #define OIDC_HTTP_HDR_COOKIE							"Cookie"
diff --git a/src/util.c b/src/util.c
index 4c46156..c6453d0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -446,6 +446,24 @@ char* oidc_util_javascript_escape(apr_pool_t *pool, const char *s) {
     return output;
 }
 
+char* oidc_util_strcasestr(const char *s1, const char *s2) {
+	const char *s = s1;
+	const char *p = s2;
+	do {
+		if (!*p)
+			return (char*) s1;
+		if ((*p == *s) || (tolower(*p) == tolower(*s))) {
+			++p;
+			++s;
+		} else {
+			p = s2;
+			if (!*s)
+				return NULL;
+			s = ++s1;
+		}
+	} while (1);
+	return *p ? NULL : (char*) s1;
+}
 
 /*
  * get the URL scheme that is currently being accessed
