|
|
d21d4d |
From cb5560f016d4f8bbca40670c59898afafb8d0763 Mon Sep 17 00:00:00 2001
|
|
|
d21d4d |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
d21d4d |
Date: Sun, 10 May 2020 19:56:53 +0200
|
|
|
d21d4d |
Subject: [PATCH] Backport of improve validation of the post-logout URL
|
|
|
d21d4d |
|
|
|
d21d4d |
---
|
|
|
d21d4d |
src/mod_auth_openidc.c | 90 +++++++++++++++++++++++++-----------------
|
|
|
d21d4d |
1 file changed, 53 insertions(+), 37 deletions(-)
|
|
|
d21d4d |
|
|
|
d21d4d |
diff --git a/src/mod_auth_openidc.c b/src/mod_auth_openidc.c
|
|
|
d21d4d |
index eaaec3c..e86c61e 100644
|
|
|
d21d4d |
--- a/src/mod_auth_openidc.c
|
|
|
d21d4d |
+++ b/src/mod_auth_openidc.c
|
|
|
d21d4d |
@@ -2563,6 +2563,52 @@ static int oidc_handle_logout_request(request_rec *r, oidc_cfg *c,
|
|
|
d21d4d |
return HTTP_MOVED_TEMPORARILY;
|
|
|
d21d4d |
}
|
|
|
d21d4d |
|
|
|
d21d4d |
+static apr_byte_t oidc_validate_post_logout_url(request_rec *r, const char *url, char **err_str, char **err_desc) {
|
|
|
d21d4d |
+ apr_uri_t uri;
|
|
|
d21d4d |
+ const char *c_host = NULL;
|
|
|
d21d4d |
+
|
|
|
d21d4d |
+ if (apr_uri_parse(r->pool, url, &uri) != APR_SUCCESS) {
|
|
|
d21d4d |
+ *err_str = apr_pstrdup(r->pool, "Malformed URL");
|
|
|
d21d4d |
+ *err_desc = apr_psprintf(r->pool, "Logout URL malformed: %s", url);
|
|
|
d21d4d |
+ oidc_error(r, "%s: %s", *err_str, *err_desc);
|
|
|
d21d4d |
+ return FALSE;
|
|
|
d21d4d |
+ }
|
|
|
d21d4d |
+
|
|
|
d21d4d |
+ c_host = oidc_get_current_url_host(r);
|
|
|
d21d4d |
+ if ((uri.hostname != NULL)
|
|
|
d21d4d |
+ && ((strstr(c_host, uri.hostname) == NULL)
|
|
|
d21d4d |
+ || (strstr(uri.hostname, c_host) == NULL))) {
|
|
|
d21d4d |
+ *err_str = apr_pstrdup(r->pool, "Invalid Request");
|
|
|
d21d4d |
+ *err_desc =
|
|
|
d21d4d |
+ apr_psprintf(r->pool,
|
|
|
d21d4d |
+ "logout value \"%s\" does not match the hostname of the current request \"%s\"",
|
|
|
d21d4d |
+ apr_uri_unparse(r->pool, &uri, 0), c_host);
|
|
|
d21d4d |
+ oidc_error(r, "%s: %s", *err_str, *err_desc);
|
|
|
d21d4d |
+ return FALSE;
|
|
|
d21d4d |
+ } else if (strstr(url, "/") != url) {
|
|
|
d21d4d |
+ *err_str = apr_pstrdup(r->pool, "Malformed URL");
|
|
|
d21d4d |
+ *err_desc =
|
|
|
d21d4d |
+ apr_psprintf(r->pool,
|
|
|
d21d4d |
+ "No hostname was parsed and it does not seem to be relative, i.e starting with '/': %s",
|
|
|
d21d4d |
+ url);
|
|
|
d21d4d |
+ oidc_error(r, "%s: %s", *err_str, *err_desc);
|
|
|
d21d4d |
+ return FALSE;
|
|
|
d21d4d |
+ }
|
|
|
d21d4d |
+
|
|
|
d21d4d |
+ /* validate the URL to prevent HTTP header splitting */
|
|
|
d21d4d |
+ if (((strstr(url, "\n") != NULL) || strstr(url, "\r") != NULL)) {
|
|
|
d21d4d |
+ *err_str = apr_pstrdup(r->pool, "Invalid Request");
|
|
|
d21d4d |
+ *err_desc =
|
|
|
d21d4d |
+ apr_psprintf(r->pool,
|
|
|
d21d4d |
+ "logout value \"%s\" contains illegal \"\n\" or \"\r\" character(s)",
|
|
|
d21d4d |
+ url);
|
|
|
d21d4d |
+ oidc_error(r, "%s: %s", *err_str, *err_desc);
|
|
|
d21d4d |
+ return FALSE;
|
|
|
d21d4d |
+ }
|
|
|
d21d4d |
+
|
|
|
d21d4d |
+ return TRUE;
|
|
|
d21d4d |
+}
|
|
|
d21d4d |
+
|
|
|
d21d4d |
/*
|
|
|
d21d4d |
* perform (single) logout
|
|
|
d21d4d |
*/
|
|
|
d21d4d |
@@ -2571,6 +2617,8 @@ static int oidc_handle_logout(request_rec *r, oidc_cfg *c,
|
|
|
d21d4d |
|
|
|
d21d4d |
/* pickup the command or URL where the user wants to go after logout */
|
|
|
d21d4d |
char *url = NULL;
|
|
|
d21d4d |
+ char *error_str = NULL;
|
|
|
d21d4d |
+ char *error_description = NULL;
|
|
|
d21d4d |
oidc_util_get_request_parameter(r, OIDC_REDIRECT_URI_REQUEST_LOGOUT, &url;;
|
|
|
d21d4d |
|
|
|
d21d4d |
oidc_debug(r, "enter (url=%s)", url);
|
|
|
d21d4d |
@@ -2587,43 +2635,11 @@ static int oidc_handle_logout(request_rec *r, oidc_cfg *c,
|
|
|
d21d4d |
|
|
|
d21d4d |
/* do input validation on the logout parameter value */
|
|
|
d21d4d |
|
|
|
d21d4d |
- const char *error_description = NULL;
|
|
|
d21d4d |
- apr_uri_t uri;
|
|
|
d21d4d |
-
|
|
|
d21d4d |
- if (apr_uri_parse(r->pool, url, &uri) != APR_SUCCESS) {
|
|
|
d21d4d |
- const char *error_description = apr_psprintf(r->pool,
|
|
|
d21d4d |
- "Logout URL malformed: %s", url);
|
|
|
d21d4d |
- oidc_error(r, "%s", error_description);
|
|
|
d21d4d |
- return oidc_util_html_send_error(r, c->error_template,
|
|
|
d21d4d |
- "Malformed URL", error_description,
|
|
|
d21d4d |
- HTTP_INTERNAL_SERVER_ERROR);
|
|
|
d21d4d |
-
|
|
|
d21d4d |
- }
|
|
|
d21d4d |
-
|
|
|
d21d4d |
- const char *c_host = oidc_get_current_url_host(r);
|
|
|
d21d4d |
- if ((uri.hostname != NULL)
|
|
|
d21d4d |
- && ((strstr(c_host, uri.hostname) == NULL)
|
|
|
d21d4d |
- || (strstr(uri.hostname, c_host) == NULL))) {
|
|
|
d21d4d |
- error_description =
|
|
|
d21d4d |
- apr_psprintf(r->pool,
|
|
|
d21d4d |
- "logout value \"%s\" does not match the hostname of the current request \"%s\"",
|
|
|
d21d4d |
- apr_uri_unparse(r->pool, &uri, 0), c_host);
|
|
|
d21d4d |
- oidc_error(r, "%s", error_description);
|
|
|
d21d4d |
- return oidc_util_html_send_error(r, c->error_template,
|
|
|
d21d4d |
- "Invalid Request", error_description,
|
|
|
d21d4d |
- HTTP_INTERNAL_SERVER_ERROR);
|
|
|
d21d4d |
- }
|
|
|
d21d4d |
-
|
|
|
d21d4d |
- /* validate the URL to prevent HTTP header splitting */
|
|
|
d21d4d |
- if (((strstr(url, "\n") != NULL) || strstr(url, "\r") != NULL)) {
|
|
|
d21d4d |
- error_description =
|
|
|
d21d4d |
- apr_psprintf(r->pool,
|
|
|
d21d4d |
- "logout value \"%s\" contains illegal \"\n\" or \"\r\" character(s)",
|
|
|
d21d4d |
- url);
|
|
|
d21d4d |
- oidc_error(r, "%s", error_description);
|
|
|
d21d4d |
- return oidc_util_html_send_error(r, c->error_template,
|
|
|
d21d4d |
- "Invalid Request", error_description,
|
|
|
d21d4d |
- HTTP_INTERNAL_SERVER_ERROR);
|
|
|
d21d4d |
+ if (oidc_validate_post_logout_url(r, url, &error_str,
|
|
|
d21d4d |
+ &error_description) == FALSE) {
|
|
|
d21d4d |
+ return oidc_util_html_send_error(r, c->error_template, error_str,
|
|
|
d21d4d |
+ error_description,
|
|
|
d21d4d |
+ HTTP_BAD_REQUEST);
|
|
|
d21d4d |
}
|
|
|
d21d4d |
}
|
|
|
d21d4d |
|
|
|
d21d4d |
--
|
|
|
d21d4d |
2.21.3
|
|
|
d21d4d |
|