diff options
Diffstat (limited to '0001-Modify-am_handler-setup-to-run-before-mod_proxy.patch')
-rw-r--r-- | 0001-Modify-am_handler-setup-to-run-before-mod_proxy.patch | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/0001-Modify-am_handler-setup-to-run-before-mod_proxy.patch b/0001-Modify-am_handler-setup-to-run-before-mod_proxy.patch new file mode 100644 index 0000000..23e4ac8 --- /dev/null +++ b/0001-Modify-am_handler-setup-to-run-before-mod_proxy.patch @@ -0,0 +1,80 @@ +From e09a28a30e13e5c22b481010f26b4a7743a09280 Mon Sep 17 00:00:00 2001 +From: John Dennis <jdennis@redhat.com> +Date: Tue, 5 Mar 2019 10:15:48 +0100 +Subject: [PATCH] Modify am_handler setup to run before mod_proxy + +The way the ECP flow works is that when a client initiates the flow, the +SP's response is HTTP 200, but not the requested content, but a signed XML +document that contains the "samlp:AuthnRequest" element. The idea is that +the ECP client would then determine the IDP and send the document to the +IDP, get a samlp:Response and convey that to the SP to get access to the +protected resource. + +Internally, the auth check which is normally done with am_check_uid() set to +apache's ap_hook_check_user_id() hook, just responds with OK, so it pretends +to authenticate the user. Then in the usual flow, the request reaches the +ap_hook_handler which handles the request. There in the pipeline, mellon +registers functions am_handler() which should run first (APR_HOOK_FIRST), +determine that this request is an ECP one and return the ECP AuthnRequest +document. But in case the proxy module is also in the picture, the proxy +module "races" for who gets to be the first to handle the request in the +pipeline and wins. Therefore, the request reaches the protected resource +via mod_proxy and returns it. + +This fix modifies the ap_hook_handler() call to explicitly run before +handlers from mod_proxy.c + +To reproduce the bug: +0) Have a SP with mellon connected to a Keycloak IDP (or any other IDP I + guess). In the example below, my SAML SP is saml.federation.test +1) Set a Location protected by mellon that proxies requests to another + URL. For example: + + ProxyPass /sp-proxy http://app.federation.test/example_app/ + <Location /sp-proxy> + AuthType Mellon + MellonEnable auth + Require valid-user + </Location> + +2) call: + curl -L -H "Accept: application/vnd.paos+xml" \ + -H 'PAOS: ver="urn:liberty:paos:2003-08";"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"' \ + http://saml.federation.test/sp-proxy + +Before the patch, you would see whatever is served from the proxied +page. With the patch, you should get back a XML document with a +samlp:AuthnRequest. +--- + mod_auth_mellon.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/mod_auth_mellon.c b/mod_auth_mellon.c +index 74bd328..5330f48 100644 +--- a/mod_auth_mellon.c ++++ b/mod_auth_mellon.c +@@ -207,6 +207,12 @@ static int am_create_request(request_rec *r) + + static void register_hooks(apr_pool_t *p) + { ++ /* Our handler needs to run before mod_proxy so that it can properly ++ * return ECP AuthnRequest messages when running as a reverse proxy. ++ * See: https://github.com/Uninett/mod_auth_mellon/pull/196 ++ */ ++ static const char * const run_handler_before[]={ "mod_proxy.c", NULL }; ++ + ap_hook_access_checker(am_auth_mellon_user, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_user_id(am_check_uid, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_config(am_global_init, NULL, NULL, APR_HOOK_MIDDLE); +@@ -222,7 +228,7 @@ static void register_hooks(apr_pool_t *p) + * Therefore this hook must run before any handler that may check + * r->handler and decide that it is the only handler for this URL. + */ +- ap_hook_handler(am_handler, NULL, NULL, APR_HOOK_FIRST); ++ ap_hook_handler(am_handler, NULL, run_handler_before, APR_HOOK_FIRST); + + #ifdef ENABLE_DIAGNOSTICS + ap_hook_open_logs(am_diag_log_init,NULL,NULL,APR_HOOK_MIDDLE); +-- +2.19.2 + |