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 <jdennis@redhat.com>
License: MIT
This commit is contained in:
John Dennis 2015-05-28 13:30:23 -04:00 committed by Benjamin Dauvergne
parent 4544ea9e9d
commit bdecdc248c
3 changed files with 88 additions and 51 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;