Blame SOURCES/0001-Modify-am_handler-setup-to-run-before-mod_proxy.patch

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