summaryrefslogtreecommitdiff
path: root/0001-Modify-am_handler-setup-to-run-before-mod_proxy.patch
diff options
context:
space:
mode:
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.patch80
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
+