Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logout endpoint should handle idP POST response #84

Merged
merged 3 commits into from
Jan 17, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 52 additions & 8 deletions auth_mellon_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,19 +896,23 @@ static int am_handle_invalidate_request(request_rec *r)
* request_rec *r The logout response request.
* LassoLogout *logout A LassoLogout object initiated with
* the current session.
* input in POST case: url-decoded SAMLResponse parameter,
* in GET case: url-encoded query string.
* args Url-encoded parameters.
*
* Returns:
* OK on success, or an error if any of the steps fail.
*/
static int am_handle_logout_response(request_rec *r, LassoLogout *logout)
static int am_handle_logout_response_cmn(request_rec *r, LassoLogout *logout,
char *input, char *args)
{
gint res;
int rc;
am_cache_entry_t *session;
char *return_to;
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);

res = lasso_logout_process_response_msg(logout, r->args);
res = lasso_logout_process_response_msg(logout, input);
am_diag_log_lasso_node(r, 0, LASSO_PROFILE(logout)->response,
"SAML Response (%s):", __func__);
#ifdef HAVE_lasso_profile_set_signature_verify_hint
Expand All @@ -919,7 +923,7 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout)
APR_HASH_KEY_STRING)) {
lasso_profile_set_signature_verify_hint(&logout->parent,
LASSO_PROFILE_SIGNATURE_VERIFY_HINT_IGNORE);
res = lasso_logout_process_response_msg(logout, r->args);
res = lasso_logout_process_response_msg(logout, input);
}
}
#endif
Expand All @@ -946,7 +950,7 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout)
am_delete_request_session(r, session);
}

return_to = am_extract_query_parameter(r->pool, r->args, "RelayState");
return_to = am_extract_query_parameter(r->pool, args, "RelayState");
if(return_to == NULL) {
AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r,
"No RelayState parameter to logout response handler."
Expand Down Expand Up @@ -981,6 +985,35 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout)
return HTTP_SEE_OTHER;
}

static int am_handle_logout_response_GET(request_rec *r, LassoLogout *logout)
{
return am_handle_logout_response_cmn(r, logout, r->args, r->args);
}

static int am_handle_logout_response_POST(request_rec *r, LassoLogout *logout,
char *post_data)
{
int rc = 0;
char *saml_response;

saml_response = am_extract_query_parameter(r->pool, post_data,
"SAMLResponse");

if (saml_response == NULL) {
AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r,
"Could not find SAMLResponse field in POST data.");
return HTTP_BAD_REQUEST;
}

rc = am_urldecode(saml_response);
if (rc != OK) {
AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r,
"Could not urldecode SAMLResponse value.");
return rc;
}
return am_handle_logout_response_cmn(r, logout, saml_response,
post_data);
}

/* This function initiates a logout request and sends it to the IdP.
*
Expand Down Expand Up @@ -1175,23 +1208,34 @@ static int am_handle_logout(request_rec *r)
* - logout requests: The IdP sends a logout request to this service.
* it can be either through HTTP-Redirect or SOAP.
* - logout responses: We have sent a logout request to the IdP, and
* are receiving a response.
* are receiving a response either via GET or POST.
* - We want to initiate a logout request.
*/

/* First check for IdP-initiated SOAP logout request */
/*
* First check for POST method, which could be either IdP-initiated SOAP
* logout request or POST logout response from IdP.
*/
if ((r->args == NULL) && (r->method_number == M_POST)) {
int rc;
char *post_data;
const char *content_type;

/* Check Content-Type */
content_type = apr_table_get(r->headers_in, "Content-Type");

rc = am_read_post_data(r, &post_data, NULL);
if (rc != OK) {
AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r,
"Error reading POST data.");
return HTTP_INTERNAL_SERVER_ERROR;
}
return am_handle_logout_request(r, logout, post_data);

if (content_type != NULL &&
am_has_header(r, content_type, "application/x-www-form-urlencoded"))
return am_handle_logout_response_POST(r, logout, post_data);
else
return am_handle_logout_request(r, logout, post_data);
} else if(am_extract_query_parameter(r->pool, r->args,
"SAMLRequest") != NULL) {
/* SAMLRequest - logout request from the IdP. */
Expand All @@ -1200,7 +1244,7 @@ static int am_handle_logout(request_rec *r)
} else if(am_extract_query_parameter(r->pool, r->args,
"SAMLResponse") != NULL) {
/* SAMLResponse - logout response from the IdP. */
return am_handle_logout_response(r, logout);
return am_handle_logout_response_GET(r, logout);

} else if(am_extract_query_parameter(r->pool, r->args,
"ReturnTo") != NULL) {
Expand Down