[saml 2.0] use the new SessionIndex storage for SLO management

It shoulf fix any missing functionnalities regarding missing session indexes
in logout requests sent by identity providers or service providers.
This commit is contained in:
Benjamin Dauvergne 2011-12-22 18:16:46 +01:00
parent 7498143628
commit ee4058bc22
2 changed files with 88 additions and 114 deletions

View File

@ -837,9 +837,16 @@ lasso_saml20_login_build_assertion(LassoLogin *login,
lasso_check_good_rc(lasso_server_saml2_assertion_setup_signature(profile->server,
assertion));
/* Encrypt NameID */
if (do_encrypt_nameid) {
/* store assertion in session object */
if (profile->session == NULL) {
profile->session = lasso_session_new();
}
lasso_session_add_assertion(profile->session, profile->remote_providerID,
LASSO_NODE(assertion));
/* FIXME: as with assertions, it should be possible to setup encryption of NameID for later */
goto_cleanup_if_fail_with_rc(provider != NULL, LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
@ -860,14 +867,6 @@ lasso_saml20_login_build_assertion(LassoLogin *login,
lasso_provider_get_encryption_sym_key_type(provider));
}
/* store assertion in session object */
if (profile->session == NULL) {
profile->session = lasso_session_new();
}
lasso_session_add_assertion(profile->session, profile->remote_providerID,
LASSO_NODE(assertion));
response = LASSO_SAMLP2_RESPONSE(profile->response);
lasso_list_add_gobject(response->Assertion, assertion);
lasso_assign_gobject(login->private_data->saml2_assertion, assertion);
@ -919,6 +918,17 @@ lasso_saml20_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_me
lasso_assign_string(subject_confirmation_data->Recipient, url);
}
/* If there is a non-encrypted NameID, fix the assertion in the session */
if (assertion && assertion->Subject && assertion->Subject->NameID) {
/* store assertion in session object */
if (profile->session == NULL) {
profile->session = lasso_session_new();
}
lasso_session_add_assertion(profile->session, profile->remote_providerID,
LASSO_NODE(assertion));
}
lasso_check_good_rc(lasso_saml20_profile_build_response_msg(profile, NULL, http_method,
url));
@ -1334,7 +1344,7 @@ lasso_saml20_login_accept_sso(LassoLogin *login)
{
LassoProfile *profile;
LassoSaml2Assertion *assertion;
GList *previous_assertions, *t;
GList *previous_assertion_ids, *t;
LassoSaml2NameID *ni;
LassoFederation *federation;
@ -1346,23 +1356,15 @@ lasso_saml20_login_accept_sso(LassoLogin *login)
if (assertion == NULL)
return LASSO_PROFILE_ERROR_MISSING_ASSERTION;
previous_assertions = lasso_session_get_assertions(profile->session,
previous_assertion_ids = lasso_session_get_assertion_ids(profile->session,
profile->remote_providerID);
for (t = previous_assertions; t; t = g_list_next(t)) {
LassoSaml2Assertion *ta;
if (LASSO_IS_SAML2_ASSERTION(t->data) == FALSE) {
continue;
}
ta = t->data;
if (lasso_strisequal(ta->ID,assertion->ID)) {
lasso_release_list(previous_assertions);
lasso_foreach(t, previous_assertion_ids) {
if (lasso_strisequal(t->data, assertion->ID)) {
lasso_release_list_of_strings(previous_assertion_ids);
return LASSO_LOGIN_ERROR_ASSERTION_REPLAY;
}
}
lasso_release_list(previous_assertions);
lasso_release_list_of_strings(previous_assertion_ids);
lasso_session_add_assertion(profile->session, profile->remote_providerID,
LASSO_NODE(assertion));
@ -1425,6 +1427,16 @@ lasso_saml20_login_build_authn_response_msg(LassoLogin *login)
lasso_assign_string(subject_confirmation_data->Recipient, url);
}
/* If there is a non-encrypted NameID, fix the assertion in the session */
if (assertion && assertion->Subject && assertion->Subject->NameID) {
/* store assertion in session object */
if (profile->session == NULL) {
profile->session = lasso_session_new();
}
lasso_session_add_assertion(profile->session, profile->remote_providerID,
LASSO_NODE(assertion));
}
switch (login->protocolProfile) {
case LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST:
http_method = LASSO_HTTP_METHOD_POST;

View File

@ -34,6 +34,7 @@
#include "../id-ff/sessionprivate.h"
#include "../id-ff/profileprivate.h"
#include "../id-ff/serverprivate.h"
#include "../id-ff/sessionprivate.h"
#include "../xml/xml_enc.h"
@ -45,23 +46,15 @@
static void check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile);
static char*
_lasso_saml2_assertion_get_session_index(LassoSaml2Assertion *assertion)
{
if (! LASSO_IS_SAML2_AUTHN_STATEMENT(assertion->AuthnStatement->data))
return NULL;
return((LassoSaml2AuthnStatement*)assertion->AuthnStatement->data)->SessionIndex;
}
int
lasso_saml20_logout_init_request(LassoLogout *logout, LassoProvider *remote_provider,
LassoHttpMethod http_method)
{
LassoProfile *profile = &logout->parent;
LassoNode *assertion_n = NULL;
LassoSaml2Assertion *assertion = NULL;
LassoSession *session = NULL;
LassoSamlp2LogoutRequest *logout_request = NULL;
GList *name_ids = NULL;
LassoSaml2NameID *name_id = NULL;
int rc = 0;
logout_request = (LassoSamlp2LogoutRequest*) lasso_samlp2_logout_request_new();
@ -75,19 +68,14 @@ lasso_saml20_logout_init_request(LassoLogout *logout, LassoProvider *remote_prov
/* session existence has been checked in id-ff/ */
session = lasso_profile_get_session(profile);
assertion_n = lasso_session_get_assertion(session, profile->remote_providerID);
if (LASSO_IS_SAML2_ASSERTION(assertion_n) == FALSE) {
return critical_error(LASSO_PROFILE_ERROR_MISSING_ASSERTION);
name_ids = lasso_session_get_name_ids(session, profile->remote_providerID);
if (!name_ids || ! LASSO_IS_SAML2_NAME_ID(name_ids->data)) {
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_MISSING_ASSERTION);
}
lasso_ref(assertion_n);
assertion = (LassoSaml2Assertion*)assertion_n;
name_id = name_ids->data; /* take the first */
/* Set the NameID */
goto_cleanup_if_fail_with_rc(assertion->Subject != NULL,
LASSO_PROFILE_ERROR_MISSING_SUBJECT);
goto_cleanup_if_fail_with_rc(assertion->Subject->NameID != NULL,
LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER);
lasso_assign_gobject(logout_request->NameID, assertion->Subject->NameID);
lasso_assign_gobject(logout_request->NameID, name_id);
/* Encrypt NameID */
if (lasso_provider_get_encryption_mode(remote_provider) == LASSO_ENCRYPTION_MODE_NAMEID) {
@ -97,17 +85,17 @@ lasso_saml20_logout_init_request(LassoLogout *logout, LassoProvider *remote_prov
}
/* set the session index if one is found */
lasso_assign_string(logout_request->SessionIndex,
_lasso_saml2_assertion_get_session_index(assertion));
{
GList *session_indexes = lasso_session_get_session_indexes(profile->session,
remote_provider->ProviderID,
&name_id->parent);
lasso_samlp2_logout_request_set_session_indexes(logout_request, session_indexes);
lasso_release_list_of_strings(session_indexes);
}
cleanup:
/* all is going well, remove the assertion */
if (rc == 0) {
lasso_session_remove_assertion(session,
profile->remote_providerID);
}
lasso_release_list_of_gobjects(name_ids);
lasso_release_gobject(logout_request);
lasso_release_gobject(assertion_n);
return rc;
}
@ -152,26 +140,25 @@ cleanup:
int
lasso_saml20_logout_validate_request(LassoLogout *logout)
{
LassoProfile *profile = LASSO_PROFILE(logout);
LassoProvider *remote_provider;
LassoSamlp2StatusResponse *response;
LassoSaml2NameID *name_id;
LassoNode *assertion_n;
LassoSaml2Assertion *assertion;
LassoSamlp2LogoutRequest *logout_request;
LassoProfile *profile = &logout->parent;
LassoProvider *remote_provider = NULL;
LassoSamlp2StatusResponse *response = NULL;
LassoSaml2NameID *name_id = NULL;
LassoSamlp2LogoutRequest *logout_request = NULL;
GList *local_session_indexes = NULL;
GList *logout_session_indexes = NULL;
int rc = 0;
if (LASSO_IS_SAMLP2_LOGOUT_REQUEST(profile->request) == FALSE)
return LASSO_PROFILE_ERROR_MISSING_REQUEST;
goto_cleanup_if_fail_with_rc(LASSO_IS_SAMLP2_LOGOUT_REQUEST(profile->request),
LASSO_PROFILE_ERROR_MISSING_REQUEST);
logout_request = (LassoSamlp2LogoutRequest*)profile->request;
/* check the issuer */
lasso_assign_string(profile->remote_providerID,
logout_request->parent.Issuer->content);
remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
}
goto_cleanup_if_fail_with_rc(LASSO_IS_PROVIDER(remote_provider),
LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
/* create the response */
response = (LassoSamlp2StatusResponse*)lasso_samlp2_logout_response_new();
@ -183,66 +170,46 @@ lasso_saml20_logout_validate_request(LassoLogout *logout)
if (name_id == NULL) {
lasso_saml20_profile_set_response_status_responder(
profile, LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST);
return LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND;
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND);
}
if (profile->session == NULL) {
lasso_saml20_profile_set_response_status_responder(profile,
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
return critical_error(LASSO_PROFILE_ERROR_SESSION_NOT_FOUND);
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_SESSION_NOT_FOUND);
}
/* verify authentication */
assertion_n = lasso_session_get_assertion(profile->session, profile->remote_providerID);
if (LASSO_IS_SAML2_ASSERTION(assertion_n) == FALSE) {
if (profile->session) {
local_session_indexes = lasso_session_get_session_indexes(profile->session,
profile->remote_providerID, &name_id->parent);
}
if (! local_session_indexes) {
lasso_saml20_profile_set_response_status_responder(profile,
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
return LASSO_PROFILE_ERROR_MISSING_ASSERTION;
}
assertion = LASSO_SAML2_ASSERTION(assertion_n);
/* Verify name identifier and session matching */
if (assertion->Subject == NULL) {
lasso_saml20_profile_set_response_status(profile,
LASSO_SAML2_STATUS_CODE_RESPONDER,
"http://lasso.entrouvert.org/error/MalformedAssertion");
return LASSO_PROFILE_ERROR_MISSING_SUBJECT;
}
if (lasso_saml2_name_id_equals(name_id, assertion->Subject->NameID) != TRUE) {
lasso_saml20_profile_set_response_status_responder(profile,
LASSO_SAML2_STATUS_CODE_UNKNOWN_PRINCIPAL);
return LASSO_LOGOUT_ERROR_UNKNOWN_PRINCIPAL;
}
/* verify session index */
if (assertion->AuthnStatement) {
if (! LASSO_IS_SAML2_AUTHN_STATEMENT(assertion->AuthnStatement->data)) {
if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP && logout_request->SessionIndex == NULL) {
/* ok, no SessionIndex from IdP, all sessions logout */
} else {
GList *i, *j;
int ok = 0;
lasso_saml20_profile_set_response_status(profile,
LASSO_SAML2_STATUS_CODE_RESPONDER, "http://lasso.entrouvert.org/error/MalformedAssertion");
return LASSO_PROFILE_ERROR_BAD_SESSION_DUMP;
}
if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP && logout_request->SessionIndex == NULL) {
/* ok, no SessionIndex from IdP, all sessions logout */
} else {
GList *session_indexes = lasso_samlp2_logout_request_get_session_indexes(logout_request);
int ok = 0;
char *assertion_SessionIndex = NULL;
GList *iter;
logout_session_indexes = lasso_samlp2_logout_request_get_session_indexes(logout_request);
assertion_SessionIndex = _lasso_saml2_assertion_get_session_index(assertion);
lasso_foreach(iter, session_indexes) {
if (lasso_strisequal((char*)iter->data, assertion_SessionIndex)) {
lasso_foreach(i, logout_session_indexes) {
lasso_foreach(j, local_session_indexes) {
if (lasso_strisequal((char*)i->data, (char*)j->data)) {
ok = 1;
}
}
lasso_release_list_of_strings(session_indexes);
if (! ok) {
lasso_saml20_profile_set_response_status_responder(profile,
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
return LASSO_LOGOUT_ERROR_UNKNOWN_PRINCIPAL;
}
}
if (! ok) {
lasso_saml20_profile_set_response_status_responder(profile,
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
goto_cleanup_with_rc(LASSO_LOGOUT_ERROR_UNKNOWN_PRINCIPAL);
}
}
@ -259,7 +226,7 @@ lasso_saml20_logout_validate_request(LassoLogout *logout)
if (logout->private_data->all_soap == FALSE) {
lasso_saml20_profile_set_response_status_responder(profile,
LASSO_LIB_STATUS_CODE_UNSUPPORTED_PROFILE);
return LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE;
goto_cleanup_with_rc(LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE);
}
}
@ -279,6 +246,8 @@ lasso_saml20_logout_validate_request(LassoLogout *logout)
cleanup:
lasso_release_gobject(response);
lasso_release_list_of_strings(local_session_indexes);
lasso_release_list_of_strings(logout_session_indexes);
return rc;
}
@ -286,22 +255,15 @@ static void
check_soap_support(G_GNUC_UNUSED gchar *key, LassoProvider *provider, LassoProfile *profile)
{
const GList *supported_profiles;
LassoSaml2Assertion *assertion;
LassoNode *assertion_n;
if (strcmp(provider->ProviderID, profile->remote_providerID) == 0)
return; /* original service provider (initiated logout) */
assertion_n = lasso_session_get_assertion(profile->session, provider->ProviderID);
if (LASSO_IS_SAML2_ASSERTION(assertion_n) == FALSE) {
return; /* not authenticated with this provider */
if (! lasso_session_has_slo_session(profile->session, provider->ProviderID)) {
return;
}
assertion = LASSO_SAML2_ASSERTION(assertion_n);
supported_profiles = lasso_provider_get_metadata_list(provider,
"SingleLogoutService SOAP");
if (supported_profiles)
return; /* provider support profile */