From bdecdc248c337bd53b70a486b326e1d2d4e08d2c Mon Sep 17 00:00:00 2001 From: John Dennis Date: Thu, 28 May 2015 13:30:23 -0400 Subject: [PATCH] ECP and PAOS special handling ECP does not require an SP to know the remote IdP provider. Existing code made the assumption the remote provider always was necessary. Determination and setting of the remote consumer URL is different in the presence of ECP. Rework the logic to reflect differing requirements. Signed-off-by: John Dennis License: MIT --- lasso/id-ff/login.c | 17 ++++++-- lasso/saml-2.0/login.c | 30 ++++++++++--- lasso/saml-2.0/profile.c | 92 ++++++++++++++++++++++------------------ 3 files changed, 88 insertions(+), 51 deletions(-) diff --git a/lasso/id-ff/login.c b/lasso/id-ff/login.c index e6dfd784..8f80d3de 100644 --- a/lasso/id-ff/login.c +++ b/lasso/id-ff/login.c @@ -1110,6 +1110,10 @@ lasso_login_build_authn_request_msg(LassoLogin *login) profile = LASSO_PROFILE(login); lasso_profile_clean_msg_info(profile); + /* With PAOS ECP there is no remote provider, don't check for it, go straight to saml2.0 */ + if (login->http_method == LASSO_HTTP_METHOD_PAOS) { + return lasso_saml20_login_build_authn_request_msg(login); + } if (profile->remote_providerID == NULL) { /* this means lasso_login_init_request was not called before */ return critical_error(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID); @@ -1518,7 +1522,7 @@ lasso_login_init_authn_request(LassoLogin *login, const gchar *remote_providerID LassoHttpMethod http_method) { LassoProfile *profile; - LassoProvider *remote_provider; + LassoProvider *remote_provider = NULL; LassoServer *server = NULL; LassoSamlpRequestAbstract *request; lasso_error_t rc = 0; @@ -1533,6 +1537,13 @@ lasso_login_init_authn_request(LassoLogin *login, const gchar *remote_providerID lasso_release_string (profile->remote_providerID); lasso_release_gobject (profile->request); + server->parent.role = LASSO_PROVIDER_ROLE_SP; + + /* With PAOS ECP there is no remote provider, don't check for it, go straight to saml2.0 */ + if (http_method == LASSO_HTTP_METHOD_PAOS) { + return lasso_saml20_login_init_authn_request(login, http_method); + } + if (remote_providerID != NULL) { lasso_assign_string(profile->remote_providerID, remote_providerID); } else { @@ -1547,7 +1558,6 @@ lasso_login_init_authn_request(LassoLogin *login, const gchar *remote_providerID return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); remote_provider->role = LASSO_PROVIDER_ROLE_IDP; - server->parent.role = LASSO_PROVIDER_ROLE_SP; IF_SAML2(profile) { return lasso_saml20_login_init_authn_request(login, http_method); @@ -1569,7 +1579,8 @@ lasso_login_init_authn_request(LassoLogin *login, const gchar *remote_providerID lasso_assign_string(login->private_data->request_id, request->RequestID); request->MajorVersion = LASSO_LIB_MAJOR_VERSION_N; request->MinorVersion = LASSO_LIB_MINOR_VERSION_N; - if (lasso_provider_get_protocol_conformance(remote_provider) < LASSO_PROTOCOL_LIBERTY_1_2) { + if (remote_provider && + lasso_provider_get_protocol_conformance(remote_provider) < LASSO_PROTOCOL_LIBERTY_1_2) { request->MajorVersion = 1; request->MinorVersion = 0; } diff --git a/lasso/saml-2.0/login.c b/lasso/saml-2.0/login.c index d53c431a..0223183a 100644 --- a/lasso/saml-2.0/login.c +++ b/lasso/saml-2.0/login.c @@ -241,12 +241,30 @@ lasso_saml20_login_build_authn_request_msg(LassoLogin *login) if (login->http_method == LASSO_HTTP_METHOD_SOAP && lasso_strisequal(authn_request->ProtocolBinding,LASSO_SAML2_METADATA_BINDING_PAOS)) { login->http_method = LASSO_HTTP_METHOD_PAOS; - /* PAOS is special, the url passed to build_request is the AssertionConsumerServiceURL of - * this SP, not the destination. */ - url = lasso_saml20_login_get_assertion_consumer_service_url(login, - LASSO_PROVIDER(profile->server)); } + if (login->http_method == LASSO_HTTP_METHOD_PAOS) { + + /* + * PAOS is special, the url passed to build_request is the + * AssertionConsumerServiceURL of this SP, not the + * destination. + */ + if (authn_request->AssertionConsumerServiceURL) { + url = authn_request->AssertionConsumerServiceURL; + if (!lasso_saml20_provider_check_assertion_consumer_service_url( + LASSO_PROVIDER(profile->server), url, LASSO_SAML2_METADATA_BINDING_PAOS)) { + rc = LASSO_PROFILE_ERROR_INVALID_REQUEST; + goto cleanup; + } + } else { + url = lasso_saml20_provider_get_assertion_consumer_service_url_by_binding( + LASSO_PROVIDER(profile->server), LASSO_SAML2_METADATA_BINDING_PAOS); + lasso_assign_string(authn_request->AssertionConsumerServiceURL, url); + } + } + + lasso_check_good_rc(lasso_saml20_profile_build_request_msg(profile, "SingleSignOnService", login->http_method, url)); @@ -1022,8 +1040,8 @@ lasso_saml20_login_build_response_msg(LassoLogin *login) if (LASSO_IS_PROVIDER(remote_provider) == FALSE) return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); - assertionConsumerURL = lasso_saml20_login_get_assertion_consumer_service_url( - login, remote_provider); + assertionConsumerURL = lasso_saml20_provider_get_assertion_consumer_service_url_by_binding( + remote_provider, LASSO_SAML2_METADATA_BINDING_PAOS); assertion = login->private_data->saml2_assertion; if (LASSO_IS_SAML2_ASSERTION(assertion) == TRUE) { diff --git a/lasso/saml-2.0/profile.c b/lasso/saml-2.0/profile.c index c2a785f4..d5b1f9bd 100644 --- a/lasso/saml-2.0/profile.c +++ b/lasso/saml-2.0/profile.c @@ -799,51 +799,59 @@ lasso_saml20_profile_init_request(LassoProfile *profile, session = profile->session; } - /* set remote provider Id */ - if (! remote_provider_id) { - if (first_in_session) { - if (! session) { - return LASSO_PROFILE_ERROR_SESSION_NOT_FOUND; + /* + * With PAOS the ECP client determines the remote provider. + * Everthing in the following block of code depends on + * establishing the remote provider and subsequetnly operating + * on the remote provider. + */ + if (http_method != LASSO_HTTP_METHOD_PAOS) { + /* set remote provider Id */ + if (! remote_provider_id) { + if (first_in_session) { + if (! session) { + return LASSO_PROFILE_ERROR_SESSION_NOT_FOUND; + } + remote_provider_id_auto = lasso_session_get_provider_index(session, 0); + } else { + remote_provider_id_auto = lasso_server_get_first_providerID(server); } - remote_provider_id_auto = lasso_session_get_provider_index(session, 0); - } else { - remote_provider_id_auto = lasso_server_get_first_providerID(server); } - } - if (! remote_provider_id && ! remote_provider_id_auto) { - rc = LASSO_PROFILE_ERROR_CANNOT_FIND_A_PROVIDER; - goto cleanup; - } - if (remote_provider_id) { - lasso_assign_string(profile->remote_providerID, remote_provider_id); - } else { - lasso_assign_new_string(profile->remote_providerID, remote_provider_id_auto); - } - rc = get_provider(profile, &remote_provider); - if (rc) - goto cleanup; - /* set the name identifier */ - name_id = (LassoSaml2NameID*)lasso_profile_get_nameIdentifier(profile); - if (LASSO_IS_SAML2_NAME_ID(name_id)) { - lasso_assign_gobject(profile->nameIdentifier, (LassoNode*)name_id); - } + if (! remote_provider_id && ! remote_provider_id_auto) { + rc = LASSO_PROFILE_ERROR_CANNOT_FIND_A_PROVIDER; + goto cleanup; + } + if (remote_provider_id) { + lasso_assign_string(profile->remote_providerID, remote_provider_id); + } else { + lasso_assign_new_string(profile->remote_providerID, remote_provider_id_auto); + } + rc = get_provider(profile, &remote_provider); + if (rc) + goto cleanup; + /* set the name identifier */ + name_id = (LassoSaml2NameID*)lasso_profile_get_nameIdentifier(profile); + if (LASSO_IS_SAML2_NAME_ID(name_id)) { + lasso_assign_gobject(profile->nameIdentifier, (LassoNode*)name_id); + } - /* verify that this provider supports the current http method */ - if (http_method == LASSO_HTTP_METHOD_ANY) { - http_method = lasso_saml20_provider_get_first_http_method((LassoProvider*)server, - remote_provider, protocol_type); - } - if (http_method == LASSO_HTTP_METHOD_NONE) { - rc = LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; - goto cleanup; - } - if (! lasso_saml20_provider_accept_http_method( - (LassoProvider*)server, - remote_provider, - protocol_type, - http_method, - TRUE)) { - rc = LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + /* verify that this provider supports the current http method */ + if (http_method == LASSO_HTTP_METHOD_ANY) { + http_method = lasso_saml20_provider_get_first_http_method((LassoProvider*)server, + remote_provider, protocol_type); + } + if (http_method == LASSO_HTTP_METHOD_NONE) { + rc = LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + goto cleanup; + } + if (! lasso_saml20_provider_accept_http_method( + (LassoProvider*)server, + remote_provider, + protocol_type, + http_method, + TRUE)) { + rc = LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } } profile->http_request_method = http_method;