From 9a2f8d404e659df76ef91ce80e762ccdc2590f2b Mon Sep 17 00:00:00 2001 From: John Dennis Date: Thu, 28 May 2015 14:04:32 -0400 Subject: [PATCH] Implement PAOS request and response messages Re-implement lasso_profile_saml20_build_paos_request_msg() and lasso_saml20_login_process_paos_response_msg() to use the functionality introduced by earlier patches and to assure they are functionally complete. Signed-off-by: John Dennis License: MIT --- lasso/saml-2.0/login.c | 68 ++++++++++++++++++++++++++++++++++++++-- lasso/saml-2.0/profile.c | 37 ++++++++++++++++++---- 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/lasso/saml-2.0/login.c b/lasso/saml-2.0/login.c index 0223183a..76c31310 100644 --- a/lasso/saml-2.0/login.c +++ b/lasso/saml-2.0/login.c @@ -38,6 +38,9 @@ #include "../id-ff/sessionprivate.h" #include "../id-ff/loginprivate.h" +#include "../xml/ecp/ecp_relaystate.h" +#include "../xml/paos_response.h" + #include "../xml/xml_enc.h" #include "../xml/saml-2.0/samlp2_authn_request.h" @@ -1065,22 +1068,83 @@ cleanup: return rc; } +/** + * lasso_saml20_login_process_paos_response_msg: + * @login: a #LassoLogin profile object + * @msg: ECP to SP PAOS message + * + * Process an ECP to SP PAOS response message. + * + * SAML2 Profile for ECP (Section 4.2) defines these steps for an ECP + * transaction + * + * 1. ECP issues HTTP Request to SP + * 2. SP issues to ECP using PAOS + * 3. ECP determines IdP + * 4. ECP conveys to IdP using SOAP + * 5. IdP identifies principal + * 6. IdP issues to ECP, targeted at SP using SOAP + * 7. ECP conveys to SP using PAOS + * 8. SP grants or denies access to principal + * + * This function is used in the implemention of Step 8 in an SP. The + * ECP response from Step 7 has been received from the ECP client, the + * SP must now parse the response and act upon the result of the Authn + * request the SP issued in Step 2. If the SOAP body contains a + * samlp:Response with a saml:Assertion the assertion is processed in + * the context of the @login parameter. + * + * The response may contain in the SOAP header a paos:Response or + * ecp:RelayState elment, both are optional. If the ecp:RelayState is + * present it is assigned to the #LassoProfile.msg_relayState + * field. If the paos:Response is present it's refToMessageID + * attribute is assigned to the #LassoProfile.msg_messageID field. + */ gint lasso_saml20_login_process_paos_response_msg(LassoLogin *login, gchar *msg) { + LassoSoapHeader *header = NULL; LassoProfile *profile; int rc1, rc2; lasso_null_param(msg); profile = LASSO_PROFILE(login); - rc1 = lasso_saml20_profile_process_soap_response(profile, msg); - rc2 = lasso_saml20_login_process_response_status_and_assertion(login); + rc1 = lasso_saml20_profile_process_soap_response_with_headers(profile, msg, &header); + + /* + * If the SOAP message contained a header check for the optional + * paos:Response and ecp:RelayState elements, if they exist extract their + * values into the profile. + */ + if (header) { + GList *i = NULL; + LassoEcpRelayState *ecp_relaystate = NULL; + LassoPaosResponse *paos_response = NULL; + + lasso_foreach(i, header->Other) { + if (!ecp_relaystate && LASSO_IS_ECP_RELAYSTATE(i->data)) { + ecp_relaystate = (LassoEcpRelayState *)i->data; + } else if (!paos_response && LASSO_IS_PAOS_RESPONSE(i->data)) { + paos_response = (LassoPaosResponse *)i->data; + } + if (ecp_relaystate && paos_response) break; + } + if (ecp_relaystate) { + lasso_assign_string(profile->msg_relayState, ecp_relaystate->RelayState); + } + if (paos_response) { + lasso_profile_set_message_id(profile, paos_response->refToMessageID); + } + } + + rc2 = lasso_saml20_login_process_response_status_and_assertion(login); if (rc1) { return rc1; } return rc2; + } /** diff --git a/lasso/saml-2.0/profile.c b/lasso/saml-2.0/profile.c index d5b1f9bd..1057e0df 100644 --- a/lasso/saml-2.0/profile.c +++ b/lasso/saml-2.0/profile.c @@ -42,15 +42,19 @@ #include "../xml/saml-2.0/samlp2_request_abstract.h" #include "../xml/saml-2.0/samlp2_artifact_resolve.h" #include "../xml/saml-2.0/samlp2_artifact_response.h" +#include "../xml/saml-2.0/samlp2_authn_request.h" #include "../xml/saml-2.0/samlp2_name_id_mapping_response.h" #include "../xml/saml-2.0/samlp2_status_response.h" #include "../xml/saml-2.0/samlp2_response.h" #include "../xml/saml-2.0/saml2_assertion.h" #include "../xml/saml-2.0/saml2_xsd.h" +#include "../xml/soap-1.1/soap_envelope.h" #include "../xml/misc_text_node.h" #include "../utils.h" #include "../debug.h" + + static char* lasso_saml20_profile_build_artifact(LassoProvider *provider); static int lasso_saml20_profile_export_to_query(LassoProfile *profile, LassoNode *msg, char **query, LassoSignatureContext context); @@ -907,26 +911,44 @@ lasso_saml20_profile_build_soap_request_msg(LassoProfile *profile, const char *u static int lasso_profile_saml20_build_paos_request_msg(LassoProfile *profile, const char *url) { + int rc = 0; + LassoSamlp2AuthnRequest *request; + LassoSamlp2IDPList *idp_list = NULL; + + lasso_extract_node_or_fail(request, profile->request, SAMLP2_AUTHN_REQUEST, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + + if (lasso_profile_get_idp_list(profile)) { + lasso_extract_node_or_fail(idp_list, + lasso_profile_get_idp_list(profile), + SAMLP2_IDP_LIST, + LASSO_PROFILE_ERROR_INVALID_IDP_LIST); + } + lasso_assign_new_string(profile->msg_body, - lasso_node_export_to_paos_request(profile->request, - profile->server->parent.ProviderID, url, - profile->msg_relayState)); + lasso_node_export_to_paos_request_full(profile->request, + profile->server->parent.ProviderID, url, + lasso_profile_get_message_id(profile), + profile->msg_relayState, + request->IsPassive, request->ProviderName, + idp_list)); + check_msg_body; - return 0; + +cleanup: + return rc; } int lasso_saml20_profile_build_request_msg(LassoProfile *profile, const char *service, LassoHttpMethod method, const char *_url) { - LassoProvider *provider; char *made_url = NULL, *url; int rc = 0; lasso_bad_param(PROFILE, profile); lasso_profile_clean_msg_info(profile); - lasso_check_good_rc(get_provider(profile, &provider)); url = (char*)_url; /* check presence of a request */ @@ -936,6 +958,9 @@ lasso_saml20_profile_build_request_msg(LassoProfile *profile, const char *servic /* if not explicitely given, automatically determine an URI from the metadatas */ if (url == NULL) { + LassoProvider *provider; + + lasso_check_good_rc(get_provider(profile, &provider)); made_url = url = get_url(provider, service, http_method_to_binding(method)); }