[id-ff 1.1] add support for multiple SessionIndex to lib:LogoutRequest

Combined with the new LassoSession storage for SessionIndex, it
should fix many bugs when doing SLO.
This commit is contained in:
Benjamin Dauvergne 2011-12-22 18:18:23 +01:00
parent ee4058bc22
commit b016558d06
3 changed files with 103 additions and 80 deletions

View File

@ -518,14 +518,13 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID,
LassoProfile *profile;
LassoProvider *remote_provider;
LassoSamlNameIdentifier *nameIdentifier = NULL;
LassoSaml2EncryptedElement *encryptedNameIdentifier = NULL;
LassoNode *assertion_n, *name_identifier_n;
LassoSamlAssertion *assertion;
LassoSamlSubjectStatementAbstract *subject_statement = NULL;
LassoFederation *federation = NULL;
gboolean is_http_redirect_get_method = FALSE;
LassoSession *session;
char *session_index = NULL;
GList *name_ids = NULL;
GList *session_indexes = NULL;
LassoLibLogoutRequest *lib_logout_request = NULL;
LassoSamlpRequestAbstract *request_abstract = NULL;
int rc = 0;
g_return_val_if_fail(LASSO_IS_LOGOUT(logout), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
@ -546,75 +545,27 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID,
lasso_assign_string(profile->remote_providerID, remote_providerID);
}
if (profile->remote_providerID == NULL) {
return critical_error(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID);
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID);
}
/* get the provider */
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_with_rc(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
}
IF_SAML2(profile) {
return lasso_saml20_logout_init_request(logout, remote_provider, http_method);
}
/* get assertion */
assertion_n = lasso_session_get_assertion(session, profile->remote_providerID);
if (LASSO_IS_SAML_ASSERTION(assertion_n) == FALSE) {
return critical_error(LASSO_PROFILE_ERROR_MISSING_ASSERTION);
}
assertion = LASSO_SAML_ASSERTION(assertion_n);
if (assertion->AuthenticationStatement && LASSO_IS_LIB_AUTHENTICATION_STATEMENT(
assertion->AuthenticationStatement)) {
LassoLibAuthenticationStatement *as =
LASSO_LIB_AUTHENTICATION_STATEMENT(assertion->AuthenticationStatement);
if (as->SessionIndex)
lasso_assign_string(session_index, as->SessionIndex);
}
/* if format is one time, then get name identifier from assertion,
else get name identifier from federation */
if (LASSO_IS_SAML_SUBJECT_STATEMENT_ABSTRACT(assertion->AuthenticationStatement)) {
subject_statement = LASSO_SAML_SUBJECT_STATEMENT_ABSTRACT(
assertion->AuthenticationStatement);
if (subject_statement && subject_statement->Subject) {
nameIdentifier = subject_statement->Subject->NameIdentifier;
encryptedNameIdentifier =
subject_statement->Subject->EncryptedNameIdentifier;
}
}
/* FIXME: Should first decrypt the EncryptedNameIdentifier */
if ((nameIdentifier && strcmp(nameIdentifier->Format,
LASSO_LIB_NAME_IDENTIFIER_FORMAT_ONE_TIME) != 0)
|| encryptedNameIdentifier) {
if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
}
federation = g_hash_table_lookup(profile->identity->federations,
profile->remote_providerID);
if (federation == NULL) {
return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
}
name_identifier_n = lasso_profile_get_nameIdentifier(profile);
if (name_identifier_n == NULL) {
return critical_error(LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND);
}
nameIdentifier = LASSO_SAML_NAME_IDENTIFIER(name_identifier_n);
if (federation->local_nameIdentifier) {
lasso_assign_gobject(profile->nameIdentifier, federation->local_nameIdentifier);
} else {
lasso_assign_gobject(profile->nameIdentifier, nameIdentifier);
}
} else {
lasso_assign_gobject(profile->nameIdentifier, nameIdentifier);
name_ids = lasso_session_get_name_ids(session, profile->remote_providerID);
if (! name_ids) {
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER);
}
nameIdentifier = name_ids->data;
lasso_assign_gobject(profile->nameIdentifier, nameIdentifier);
session_indexes = lasso_session_get_session_indexes(session,
profile->remote_providerID, profile->nameIdentifier);
/* get / verify http method */
if (http_method == LASSO_HTTP_METHOD_ANY) {
@ -634,7 +585,7 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID,
* failed, since the remote provider doesn't
* support any logout. remove assertion
* unconditionnaly. */
lasso_session_remove_assertion(profile->session,
lasso_session_remove_assertion(session,
profile->remote_providerID);
if (logout->initial_remote_providerID && logout->initial_request) {
lasso_assign_string(profile->remote_providerID,
@ -647,48 +598,49 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID,
0));
}
}
return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE;
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE);
}
}
/* build a new request object from http method */
if (http_method == LASSO_HTTP_METHOD_SOAP) {
lasso_assign_new_gobject(profile->request, lasso_lib_logout_request_new_full(
lib_logout_request = (LassoLibLogoutRequest*)lasso_lib_logout_request_new_full(
LASSO_PROVIDER(profile->server)->ProviderID,
nameIdentifier,
profile->server->certificate ?
LASSO_SIGNATURE_TYPE_WITHX509 : LASSO_SIGNATURE_TYPE_SIMPLE,
LASSO_SIGNATURE_METHOD_RSA_SHA1));
LASSO_SIGNATURE_METHOD_RSA_SHA1);
} else { /* http_method == LASSO_HTTP_METHOD_REDIRECT */
is_http_redirect_get_method = TRUE;
lasso_assign_new_gobject(profile->request, lasso_lib_logout_request_new_full(
lib_logout_request = (LassoLibLogoutRequest*)lasso_lib_logout_request_new_full(
LASSO_PROVIDER(profile->server)->ProviderID,
nameIdentifier,
LASSO_SIGNATURE_TYPE_NONE,
0));
0);
}
/* FIXME: Should encrypt nameIdentifier in the request here */
request_abstract = &lib_logout_request->parent;
if (lasso_provider_get_protocol_conformance(remote_provider) < LASSO_PROTOCOL_LIBERTY_1_2) {
LASSO_SAMLP_REQUEST_ABSTRACT(profile->request)->MajorVersion = 1;
LASSO_SAMLP_REQUEST_ABSTRACT(profile->request)->MinorVersion = 1;
request_abstract->MajorVersion = 1;
request_abstract->MinorVersion = 1;
}
lasso_assign_string(LASSO_LIB_LOGOUT_REQUEST(profile->request)->SessionIndex,
session_index);
lasso_assign_string(LASSO_LIB_LOGOUT_REQUEST(profile->request)->RelayState,
profile->msg_relayState);
lasso_lib_logout_request_set_session_indexes(lib_logout_request, session_indexes);
lasso_assign_string(lib_logout_request->RelayState, profile->msg_relayState);
/* if logout request from a SP and if an HTTP Redirect/GET method, then remove assertion */
if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP && is_http_redirect_get_method) {
lasso_session_remove_assertion(profile->session, profile->remote_providerID);
lasso_session_remove_assertion(session, profile->remote_providerID);
}
/* Save the http method */
logout->initial_http_request_method = http_method;
return 0;
lasso_assign_gobject(profile->request, lib_logout_request);
cleanup:
lasso_release_gobject(lib_logout_request);
lasso_release_list_of_strings(session_indexes);
lasso_release_list_of_gobjects(name_ids);
return rc;
}
/**

View File

@ -60,12 +60,22 @@
/* private methods */
/*****************************************************************************/
#define LASSO_LIB_LOGOUT_REQUEST_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), LASSO_TYPE_LIB_LOGOUT_REQUEST, \
struct _LassoLibLogoutRequestPrivate))
struct _LassoLibLogoutRequestPrivate {
GList *SessionIndex;
};
static struct XmlSnippet schema_snippets[] = {
{ "Extension", SNIPPET_EXTENSION, G_STRUCT_OFFSET(LassoLibLogoutRequest, Extension), NULL, NULL, NULL},
{ "ProviderID", SNIPPET_CONTENT, G_STRUCT_OFFSET(LassoLibLogoutRequest, ProviderID), NULL, NULL, NULL},
{ "NameIdentifier", SNIPPET_NODE, G_STRUCT_OFFSET(LassoLibLogoutRequest, NameIdentifier),
NULL, LASSO_SAML_ASSERTION_PREFIX, LASSO_SAML_ASSERTION_HREF},
{ "SessionIndex", SNIPPET_CONTENT, G_STRUCT_OFFSET(LassoLibLogoutRequest, SessionIndex), NULL, NULL, NULL},
{ "SessionIndex", SNIPPET_LIST_CONTENT|SNIPPET_PRIVATE, G_STRUCT_OFFSET(struct
_LassoLibLogoutRequestPrivate, SessionIndex), NULL, NULL, NULL},
{ "RelayState", SNIPPET_CONTENT, G_STRUCT_OFFSET(LassoLibLogoutRequest, RelayState), NULL, NULL, NULL},
{ "consent", SNIPPET_ATTRIBUTE, G_STRUCT_OFFSET(LassoLibLogoutRequest, consent), NULL, NULL, NULL},
{ "NotOnOrAfter", SNIPPET_ATTRIBUTE,
@ -136,6 +146,7 @@ class_init(LassoLibLogoutRequestClass *klass)
lasso_node_class_set_ns(nclass, LASSO_LIB_HREF, LASSO_LIB_PREFIX);
lasso_node_class_add_snippets(nclass, schema_snippets);
lasso_node_class_add_query_snippets(nclass, query_snippets);
g_type_class_add_private(nclass, sizeof(struct _LassoLibLogoutRequestPrivate));
}
GType
@ -208,3 +219,56 @@ lasso_lib_logout_request_new_full(char *providerID, LassoSamlNameIdentifier *nam
return LASSO_NODE(request);
}
/**
* lasso_lib_logout_request_set_session_indexes:
* @lib_logout_request: a #LassoLibLogoutRequest object
* @session_indexes:(element-type string): a list of session indexes
*
* Set the SessionIndex node for this idff:LogoutRequest.
*/
void
lasso_lib_logout_request_set_session_indexes(LassoLibLogoutRequest *lib_logout_request,
GList *session_indexes)
{
char *first = NULL;
struct _LassoLibLogoutRequestPrivate *private_data;
if (! LASSO_IS_LIB_LOGOUT_REQUEST(lib_logout_request))
return;
private_data = LASSO_LIB_LOGOUT_REQUEST_GET_PRIVATE(lib_logout_request);
if (session_indexes) {
first = session_indexes->data;
session_indexes = g_list_next(session_indexes);
}
lasso_assign_string(lib_logout_request->SessionIndex, first);
lasso_assign_list_of_strings(private_data->SessionIndex, session_indexes);
}
/**
* lasso_lib_logout_request_get_session_indexes:
* @lib_logout_request: a #LassoLibLogoutRequest object
*
* Get the SessionIndex node for this idff:LogoutRequest.
*
* Return value:(transfer full)(element-type utf8): a list of strings
*/
GList*
lasso_lib_logout_request_get_session_indexes(LassoLibLogoutRequest *lib_logout_request)
{
struct _LassoLibLogoutRequestPrivate *private_data;
GList *ret = NULL;
GList *i = NULL;
if (! LASSO_IS_LIB_LOGOUT_REQUEST(lib_logout_request))
return NULL;
private_data = LASSO_LIB_LOGOUT_REQUEST_GET_PRIVATE(lib_logout_request);
if (lib_logout_request->SessionIndex) {
lasso_list_add_string(ret, lib_logout_request->SessionIndex);
}
lasso_foreach(i, private_data->SessionIndex) {
lasso_list_add_string(ret, i->data);
}
return ret;
}

View File

@ -74,6 +74,13 @@ LASSO_EXPORT LassoNode* lasso_lib_logout_request_new_full(
char *providerID, LassoSamlNameIdentifier *nameIdentifier,
LassoSignatureType sign_type, LassoSignatureMethod sign_method);
LASSO_EXPORT void lasso_lib_logout_request_set_session_indexes(
LassoLibLogoutRequest *lib_logout_request,
GList *session_indexes);
LASSO_EXPORT GList* lasso_lib_logout_request_get_session_indexes(
LassoLibLogoutRequest *lib_logout_request);
#ifdef __cplusplus
}
#endif /* __cplusplus */