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

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