Blame SOURCES/log-status-response.patch

d64f60
commit 582f283c49c754a07aee6eea0fbcd4b188f23236
d64f60
Author: John Dennis <jdennis@redhat.com>
d64f60
Date:   Wed Feb 7 09:45:18 2018 -0500
d64f60
d64f60
    Log SAML status response information
d64f60
    
d64f60
    Knowing if a SAML operation failed and the reason why is essential to
d64f60
    diagnose problems. The SAML Status Response is always included in all
d64f60
    SAML responses. In addition to the major reason why a transaction
d64f60
    failed it may also include extra expository information giving
d64f60
    additional details. Unfortunately we never logged any of the status
d64f60
    response information when a failure occurred. This patch adds code to
d64f60
    log the status response information.
d64f60
    
d64f60
    In addition the patch adds diagnostic logging of received POST data.
d64f60
    
d64f60
    Signed-off-by: John Dennis <jdennis@redhat.com>
d64f60
d64f60
diff --git a/auth_mellon.h b/auth_mellon.h
d64f60
index a10bc4c..289db0c 100644
d64f60
--- a/auth_mellon.h
d64f60
+++ b/auth_mellon.h
d64f60
@@ -511,6 +511,9 @@ char *am_ecp_service_options_str(apr_pool_t *pool, ECPServiceOptions options);
d64f60
 bool am_is_paos_request(request_rec *r, int *error_code);
d64f60
 #endif /* HAVE_ECP */
d64f60
 
d64f60
+char *
d64f60
+am_saml_response_status_str(request_rec *r, LassoNode *node);
d64f60
+
d64f60
 int am_auth_mellon_user(request_rec *r);
d64f60
 int am_check_uid(request_rec *r);
d64f60
 int am_handler(request_rec *r);
d64f60
@@ -577,6 +580,11 @@ am_diag_log_lasso_node(request_rec *r, int level, LassoNode *node,
d64f60
                        const char *fmt, ...)
d64f60
     __attribute__((format(printf,4,5)));
d64f60
 
d64f60
+void
d64f60
+am_diag_log_saml_status_response(request_rec *r, int level, LassoNode *node,
d64f60
+                                 const char *fmt, ...)
d64f60
+    __attribute__((format(printf,4,5)));
d64f60
+
d64f60
 void
d64f60
 am_diag_log_profile(request_rec *r, int level, LassoProfile *profile,
d64f60
                     const char *fmt, ...)
d64f60
@@ -608,6 +616,7 @@ am_diag_time_t_to_8601(request_rec *r, apr_time_t t);
d64f60
 #define am_diag_log_cache_entry(...) do {} while(0)
d64f60
 #define am_diag_log_file_data(...) do {} while(0)
d64f60
 #define am_diag_log_lasso_node(...) do {} while(0)
d64f60
+#define am_diag_log_saml_status_response(...) do {} while(0)
d64f60
 #define am_diag_log_profile(...) do {} while(0)
d64f60
 #define am_diag_printf(...) do {} while(0)
d64f60
 
d64f60
diff --git a/auth_mellon_diagnostics.c b/auth_mellon_diagnostics.c
d64f60
index 289a878..89fbc62 100644
d64f60
--- a/auth_mellon_diagnostics.c
d64f60
+++ b/auth_mellon_diagnostics.c
d64f60
@@ -867,7 +867,9 @@ am_diag_log_lasso_node(request_rec *r, int level, LassoNode *node,
d64f60
         write_indented_text(diag_cfg->fd, level+1, xml);
d64f60
         lasso_release_string(xml);
d64f60
     } else {
d64f60
-        apr_file_printf(diag_cfg->fd, "node is NULL\n");
d64f60
+        apr_file_printf(diag_cfg->fd,
d64f60
+                        "%snode is NULL\n",
d64f60
+                        indent(level+1));
d64f60
     }
d64f60
     apr_file_flush(diag_cfg->fd);
d64f60
 }
d64f60
@@ -919,6 +921,99 @@ am_diag_log_file_data(request_rec *r, int level, am_file_data_t *file_data,
d64f60
     apr_file_flush(diag_cfg->fd);
d64f60
 }
d64f60
 
d64f60
+void
d64f60
+am_diag_log_saml_status_response(request_rec *r, int level, LassoNode *node,
d64f60
+                                 const char *fmt, ...)
d64f60
+{
d64f60
+    va_list ap;
d64f60
+    am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server);
d64f60
+    am_req_cfg_rec *req_cfg = am_get_req_cfg(r);
d64f60
+
d64f60
+    LassoSamlp2StatusResponse *response = (LassoSamlp2StatusResponse*)node;
d64f60
+    LassoSamlp2Status *status = NULL;
d64f60
+    const char *status_code1 = NULL;
d64f60
+    const char *status_code2 = NULL;
d64f60
+
d64f60
+    if (!AM_DIAG_ENABLED(diag_cfg)) return;
d64f60
+    if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return;
d64f60
+
d64f60
+    va_start(ap, fmt);
d64f60
+    am_diag_format_line(r->pool, diag_cfg->fd, level, fmt, ap);
d64f60
+    va_end(ap);
d64f60
+
d64f60
+    if (response == NULL) {
d64f60
+        apr_file_printf(diag_cfg->fd,
d64f60
+                        "%sresponse is NULL\n", indent(level+1));
d64f60
+        return;
d64f60
+    }
d64f60
+
d64f60
+
d64f60
+    if (!LASSO_IS_SAMLP2_STATUS_RESPONSE(response)) {
d64f60
+        apr_file_printf(diag_cfg->fd,
d64f60
+                        "%sERROR, expected LassoSamlp2StatusResponse "
d64f60
+                        "but got %s\n",
d64f60
+                        indent(level+1),
d64f60
+                        lasso_node_get_name((LassoNode*)response));
d64f60
+        return;
d64f60
+    }
d64f60
+
d64f60
+    status = response->Status;
d64f60
+    if (status == NULL                  ||
d64f60
+        !LASSO_IS_SAMLP2_STATUS(status) ||
d64f60
+        status->StatusCode == NULL      ||
d64f60
+        status->StatusCode->Value == NULL) {
d64f60
+        apr_file_printf(diag_cfg->fd,
d64f60
+                        "%sStatus missing\n",
d64f60
+                        indent(level+1));
d64f60
+        return;
d64f60
+    }
d64f60
+
d64f60
+    status_code1 = status->StatusCode->Value;
d64f60
+    if (status->StatusCode->StatusCode) {
d64f60
+        status_code2 = status->StatusCode->StatusCode->Value;
d64f60
+    }
d64f60
+
d64f60
+
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sID: %s\n",
d64f60
+                    indent(level+1), response->ID);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sInResponseTo: %s\n",
d64f60
+                    indent(level+1), response->InResponseTo);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sVersion: %s\n",
d64f60
+                    indent(level+1), response->Version);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sIssueInstant: %s\n",
d64f60
+                    indent(level+1), response->IssueInstant);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sConsent: %s\n",
d64f60
+                    indent(level+1), response->Consent);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sIssuer: %s\n",
d64f60
+                    indent(level+1), response->Issuer->content);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sDestination: %s\n",
d64f60
+                    indent(level+1), response->Destination);
d64f60
+
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sStatus:\n", indent(level+1));
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sTop Level Status code: %s\n",
d64f60
+                    indent(level+2), status_code1);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%s2nd Level Status code: %s\n",
d64f60
+                    indent(level+2), status_code2);
d64f60
+    apr_file_printf(diag_cfg->fd,
d64f60
+                    "%sStatus Message: %s\n",
d64f60
+                    indent(level+2), status->StatusMessage);
d64f60
+    am_diag_log_lasso_node(r, level+2, (LassoNode*)status->StatusDetail,
d64f60
+                           "Status Detail:");
d64f60
+
d64f60
+    return;
d64f60
+
d64f60
+}
d64f60
+
d64f60
 void
d64f60
 am_diag_log_profile(request_rec *r, int level, LassoProfile *profile,
d64f60
                     const char *fmt, ...)
d64f60
diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c
d64f60
index 030abe7..5058744 100644
d64f60
--- a/auth_mellon_handler.c
d64f60
+++ b/auth_mellon_handler.c
d64f60
@@ -826,6 +826,8 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout)
d64f60
     am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
d64f60
 
d64f60
     res = lasso_logout_process_response_msg(logout, r->args);
d64f60
+    am_diag_log_lasso_node(r, 0, LASSO_PROFILE(logout)->response,
d64f60
+                           "SAML Response (%s):", __func__);
d64f60
 #ifdef HAVE_lasso_profile_set_signature_verify_hint
d64f60
     if(res != 0 && res != LASSO_DS_ERROR_SIGNATURE_NOT_FOUND &&
d64f60
        logout->parent.remote_providerID != NULL) {
d64f60
@@ -841,7 +843,10 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout)
d64f60
     if(res != 0) {
d64f60
         AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r,
d64f60
                       "Unable to process logout response."
d64f60
-                      " Lasso error: [%i] %s", res, lasso_strerror(res));
d64f60
+                      " Lasso error: [%i] %s, SAML Response: %s",
d64f60
+                      res, lasso_strerror(res),
d64f60
+                      am_saml_response_status_str(r,
d64f60
+                        LASSO_PROFILE(logout)->response));
d64f60
 
d64f60
         lasso_logout_destroy(logout);
d64f60
         return HTTP_BAD_REQUEST;
d64f60
@@ -1760,9 +1765,6 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login,
d64f60
     int rc;
d64f60
     const char *idp;
d64f60
 
d64f60
-    am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response,
d64f60
-                           "SAMLResponse:");
d64f60
-
d64f60
     url = am_reconstruct_url(r);
d64f60
     chr = strchr(url, '?');
d64f60
     if (! chr) {
d64f60
@@ -2039,10 +2041,15 @@ static int am_handle_post_reply(request_rec *r)
d64f60
 
d64f60
     /* Process login responce. */
d64f60
     rc = lasso_login_process_authn_response_msg(login, saml_response);
d64f60
+    am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response,
d64f60
+                           "SAML Response (%s):", __func__);
d64f60
     if (rc != 0) {
d64f60
         AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r,
d64f60
                       "Error processing authn response."
d64f60
-                      " Lasso error: [%i] %s", rc, lasso_strerror(rc));
d64f60
+                      " Lasso error: [%i] %s, SAML Response: %s",
d64f60
+                      rc, lasso_strerror(rc),
d64f60
+                      am_saml_response_status_str(r,
d64f60
+                        LASSO_PROFILE(login)->response));
d64f60
 
d64f60
         lasso_login_destroy(login);
d64f60
         err = HTTP_BAD_REQUEST;
d64f60
@@ -2134,10 +2141,15 @@ static int am_handle_paos_reply(request_rec *r)
d64f60
 
d64f60
     /* Process login response. */
d64f60
     rc = lasso_login_process_paos_response_msg(login, post_data);
d64f60
+    am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response,
d64f60
+                           "SAML Response (%s):", __func__);
d64f60
     if (rc != 0) {
d64f60
         AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r,
d64f60
                       "Error processing ECP authn response."
d64f60
-                      " Lasso error: [%i] %s", rc, lasso_strerror(rc));
d64f60
+                      " Lasso error: [%i] %s, SAML Response: %s",
d64f60
+                      rc, lasso_strerror(rc),
d64f60
+                      am_saml_response_status_str(r,
d64f60
+                        LASSO_PROFILE(login)->response));
d64f60
 
d64f60
         lasso_login_destroy(login);
d64f60
         err = HTTP_BAD_REQUEST;
d64f60
@@ -2275,10 +2287,16 @@ static int am_handle_artifact_reply(request_rec *r)
d64f60
     }
d64f60
 
d64f60
     rc = lasso_login_process_response_msg(login, response);
d64f60
+    am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response,
d64f60
+                           "SAML Response (%s):", __func__);
d64f60
     if(rc != 0) {
d64f60
         AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r,
d64f60
                       "Failed to handle HTTP-Artifact response data."
d64f60
-                      " Lasso error: [%i] %s", rc, lasso_strerror(rc));
d64f60
+                      " Lasso error: [%i] %s, SAML Response: %s",
d64f60
+                      rc, lasso_strerror(rc),
d64f60
+                      am_saml_response_status_str(r,
d64f60
+                        LASSO_PROFILE(login)->response));
d64f60
+
d64f60
         lasso_login_destroy(login);
d64f60
         return HTTP_INTERNAL_SERVER_ERROR;
d64f60
     }
d64f60
@@ -2947,8 +2965,9 @@ static int am_set_authn_request_content(request_rec *r, LassoLogin *login)
d64f60
 {
d64f60
 
d64f60
     am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->request,
d64f60
-                           "SAML AuthnRequest: http_method=%s",
d64f60
-                           am_diag_lasso_http_method_str(login->http_method));
d64f60
+                           "SAML AuthnRequest: http_method=%s URL=%s",
d64f60
+                           am_diag_lasso_http_method_str(login->http_method),
d64f60
+                           LASSO_PROFILE(login)->msg_url);
d64f60
 
d64f60
     switch (login->http_method) {
d64f60
     case LASSO_HTTP_METHOD_REDIRECT:
d64f60
diff --git a/auth_mellon_util.c b/auth_mellon_util.c
d64f60
index 6538160..1fd3d4b 100644
d64f60
--- a/auth_mellon_util.c
d64f60
+++ b/auth_mellon_util.c
d64f60
@@ -636,6 +636,7 @@ int am_read_post_data(request_rec *r, char **data, apr_size_t *length)
d64f60
         bytes_left -= read_length;
d64f60
     }
d64f60
 
d64f60
+    am_diag_printf(r, "POST data: %s\n", *data);
d64f60
     return OK;
d64f60
 }
d64f60
 
d64f60
@@ -2630,3 +2631,38 @@ bool am_is_paos_request(request_rec *r, int *error_code)
d64f60
     return is_paos;
d64f60
 }
d64f60
 #endif /* HAVE_ECP */
d64f60
+
d64f60
+char *
d64f60
+am_saml_response_status_str(request_rec *r, LassoNode *node)
d64f60
+{
d64f60
+    LassoSamlp2StatusResponse *response = (LassoSamlp2StatusResponse*)node;
d64f60
+    LassoSamlp2Status *status = NULL;
d64f60
+    const char *status_code1 = NULL;
d64f60
+    const char *status_code2 = NULL;
d64f60
+
d64f60
+    if (!LASSO_IS_SAMLP2_STATUS_RESPONSE(response)) {
d64f60
+        return apr_psprintf(r->pool,
d64f60
+                            "error, expected LassoSamlp2StatusResponse "
d64f60
+                            "but got %s",
d64f60
+                            lasso_node_get_name((LassoNode*)response));
d64f60
+    }
d64f60
+
d64f60
+    status = response->Status;
d64f60
+    if (status == NULL                  ||
d64f60
+        !LASSO_IS_SAMLP2_STATUS(status) ||
d64f60
+        status->StatusCode == NULL      ||
d64f60
+        status->StatusCode->Value == NULL) {
d64f60
+        return apr_psprintf(r->pool, "Status missing");
d64f60
+
d64f60
+    }
d64f60
+
d64f60
+    status_code1 = status->StatusCode->Value;
d64f60
+    if (status->StatusCode->StatusCode) {
d64f60
+        status_code2 = status->StatusCode->StatusCode->Value;
d64f60
+    }
d64f60
+
d64f60
+    return apr_psprintf(r->pool,
d64f60
+                        "StatusCode1=\"%s\", StatusCode2=\"%s\", "
d64f60
+                        "StatusMessage=\"%s\"",
d64f60
+                        status_code1, status_code2, status->StatusMessage);
d64f60
+}