diff options
| author | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2011-12-23 11:21:36 +0100 |
|---|---|---|
| committer | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2011-12-23 11:21:36 +0100 |
| commit | 8f06751564ed5f767345e17ae0f09ee8199e4a49 (patch) | |
| tree | eba37902b77b7169bbb79394daad95a550d56742 | |
| parent | 69c61627d3b8494c9f8544f19293c9b345ec103d (diff) | |
| parent | af4c8de94722d51dd000276eb5e51c26c314f903 (diff) | |
Merge branch 'more-datas-in-sessions'
| -rw-r--r-- | docs/reference/lasso/lasso-docs.sgml | 2 | ||||
| -rw-r--r-- | docs/reference/lasso/lasso-sections.txt | 1 | ||||
| -rw-r--r-- | lasso/debug.h | 1 | ||||
| -rw-r--r-- | lasso/id-ff/login.c | 86 | ||||
| -rw-r--r-- | lasso/id-ff/logout.c | 112 | ||||
| -rw-r--r-- | lasso/id-ff/profile.c | 2 | ||||
| -rw-r--r-- | lasso/id-ff/profile.h | 3 | ||||
| -rw-r--r-- | lasso/id-ff/session.c | 420 | ||||
| -rw-r--r-- | lasso/id-ff/session.h | 7 | ||||
| -rw-r--r-- | lasso/id-ff/sessionprivate.h | 6 | ||||
| -rw-r--r-- | lasso/lasso.c | 5 | ||||
| -rw-r--r-- | lasso/saml-2.0/login.c | 58 | ||||
| -rw-r--r-- | lasso/saml-2.0/logout.c | 146 | ||||
| -rw-r--r-- | lasso/xml/lib_logout_request.c | 64 | ||||
| -rw-r--r-- | lasso/xml/lib_logout_request.h | 7 | ||||
| -rw-r--r-- | lasso/xml/saml_name_identifier.c | 14 | ||||
| -rw-r--r-- | lasso/xml/saml_name_identifier.h | 3 | ||||
| -rw-r--r-- | lasso/xml/strings.h | 6 | ||||
| -rw-r--r-- | tests/login_tests.c | 28 |
19 files changed, 708 insertions, 263 deletions
diff --git a/docs/reference/lasso/lasso-docs.sgml b/docs/reference/lasso/lasso-docs.sgml index e92d447e..b71fefcf 100644 --- a/docs/reference/lasso/lasso-docs.sgml +++ b/docs/reference/lasso/lasso-docs.sgml @@ -213,7 +213,7 @@ the <ulink url="http://lasso.entrouvert.org/license">GNU General Public License< <chapter id="saml2"> <title>SAML 2.0 Single Sign On profiles</title> <para> - The profile <link linkend="lasso-LassoLogin">LassoLogin</link> and <link linkend="lasso-LassoLogout">LassoLogout</link> are shared between SAML + The profile <link linkend="lasso-login">LassoLogin</link> and <link linkend="lasso-LassoLogout">LassoLogout</link> are shared between SAML 2.0 and ID-FF 1.2, depending on the declared protocol support, Lasso will create request respecting the chosen standard. Beware that initialization of the <link linkend="lasso-LassoLogin">LassoLogin</link> object, after construction, diff --git a/docs/reference/lasso/lasso-sections.txt b/docs/reference/lasso/lasso-sections.txt index 74d998a5..cdd019fa 100644 --- a/docs/reference/lasso/lasso-sections.txt +++ b/docs/reference/lasso/lasso-sections.txt @@ -220,7 +220,6 @@ LASSO_LECP_GET_CLASS <SECTION> <FILE>login</FILE> -LassoLoginProtocolProfile <TITLE>LassoLogin</TITLE> LassoLogin lasso_login_new diff --git a/lasso/debug.h b/lasso/debug.h index ce294ac7..f98f7882 100644 --- a/lasso/debug.h +++ b/lasso/debug.h @@ -37,6 +37,7 @@ LASSO_EXPORT extern gboolean lasso_flag_memory_debug; LASSO_EXPORT extern gboolean lasso_flag_strict_checking; LASSO_EXPORT extern gboolean lasso_flag_add_signature; LASSO_EXPORT extern gboolean lasso_flag_sign_messages; +LASSO_EXPORT extern gboolean lasso_flag_thin_sessions; #ifdef __cplusplus } diff --git a/lasso/id-ff/login.c b/lasso/id-ff/login.c index dd3cc5c7..9191e033 100644 --- a/lasso/id-ff/login.c +++ b/lasso/id-ff/login.c @@ -259,6 +259,7 @@ #include "../xml/saml_conditions.h" #include "../xml/samlp_response.h" #include "../xml/saml-2.0/saml2_encrypted_element.h" +#include "../xml/misc_text_node.h" #include "profileprivate.h" @@ -401,19 +402,20 @@ lasso_login_build_assertion(LassoLogin *login, } } + /* add session index */ + if (lasso_provider_get_first_http_method(&login->parent.server->parent, + provider, LASSO_MD_PROTOCOL_TYPE_SINGLE_LOGOUT) != LASSO_HTTP_METHOD_NONE) { + lasso_assign_string(as->SessionIndex, assertion->AssertionID); + } + assertion->AuthenticationStatement = LASSO_SAML_AUTHENTICATION_STATEMENT(as); /* Save signing material in assertion private datas to be able to sign later */ lasso_check_good_rc(lasso_server_set_signature_for_provider_by_name(login->parent.server, profile->remote_providerID, (LassoNode*)assertion)); - - if (login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST || \ - login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_LECP) { - /* only add assertion if response is an AuthnResponse */ - lasso_list_add_gobject(LASSO_SAMLP_RESPONSE(profile->response)->Assertion, - assertion); - } + lasso_list_add_gobject(LASSO_SAMLP_RESPONSE(profile->response)->Assertion, + assertion); #ifdef LASSO_WSF_ENABLED lasso_login_assertion_add_discovery(login, assertion); @@ -858,6 +860,8 @@ lasso_login_build_assertion_artifact(LassoLogin *login) b64_samlArt = xmlSecBase64Encode(samlArt, 42, 0); lasso_assign_string(login->assertionArtifact, (char*)b64_samlArt); + lasso_assign_string(login->parent.private_data->artifact, + (char*)b64_samlArt); lasso_release_xml_string(b64_samlArt); } @@ -906,12 +910,12 @@ lasso_login_build_assertion_artifact(LassoLogin *login) gint lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) { - LassoProvider *remote_provider; - LassoProfile *profile; - gchar *url; - xmlChar *b64_samlArt; - char *relayState; - gint ret = 0; + LassoProvider *remote_provider = NULL; + LassoProfile *profile = NULL; + gchar *url = NULL; + xmlChar *b64_samlArt = NULL; + xmlChar *relayState = NULL; + gint rc = 0; g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); @@ -920,7 +924,7 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) if (profile->remote_providerID == NULL) { /* this means lasso_login_init_request was not called before */ - return critical_error(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID); + goto_cleanup_with_rc(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID); } IF_SAML2(profile) { @@ -928,18 +932,18 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) } if (http_method != LASSO_HTTP_METHOD_REDIRECT && http_method != LASSO_HTTP_METHOD_POST) { - return critical_error(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD); + goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD); } /* ProtocolProfile must be BrwsArt */ if (login->protocolProfile != LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART) { - return critical_error(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE); + goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE); } /* build artifact infos */ 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); url = lasso_provider_get_assertion_consumer_service_url(remote_provider, LASSO_LIB_AUTHN_REQUEST(profile->request)->AssertionConsumerServiceID); @@ -985,12 +989,12 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) } b64_samlArt = xmlStrdup((xmlChar*)login->assertionArtifact); - relayState = (char*)xmlURIEscapeStr( + relayState = xmlURIEscapeStr( (xmlChar*)LASSO_LIB_AUTHN_REQUEST(profile->request)->RelayState, NULL); if (http_method == LASSO_HTTP_METHOD_REDIRECT) { xmlChar *escaped_artifact = xmlURIEscapeStr(b64_samlArt, NULL); - gchar *query; + gchar *query = NULL; if (relayState == NULL) { query = g_strdup_printf("SAMLart=%s", escaped_artifact); @@ -1000,20 +1004,16 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) } lasso_assign_new_string(profile->msg_url, lasso_concat_url_query(url, query)); lasso_release_string(query); - - xmlFree(escaped_artifact); + lasso_release_xml_string(escaped_artifact); } if (http_method == LASSO_HTTP_METHOD_POST) { lasso_assign_string(profile->msg_url, url); lasso_assign_string(profile->msg_body, (char*)b64_samlArt); if (relayState != NULL) { - lasso_assign_string(profile->msg_relayState, relayState); + lasso_assign_string(profile->msg_relayState, (char*)relayState); } } - lasso_release_string(url); - xmlFree(b64_samlArt); - xmlFree(relayState); if (strcmp(LASSO_SAMLP_RESPONSE(profile->response)->Status->StatusCode->Value, LASSO_SAML_STATUS_CODE_SUCCESS) != 0) { @@ -1026,7 +1026,25 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) lasso_session_remove_status(profile->session, profile->remote_providerID); } - return ret; + /* store the response as the artifact message */ + lasso_check_good_rc(lasso_server_set_signature_for_provider_by_name( + profile->server, + profile->remote_providerID, + profile->response)); + /* comply with the new way of storing artifacts */ + lasso_assign_string(profile->private_data->artifact, + login->assertionArtifact); + /* Artifact profile for ID-FF 1.2 is special, this is not the full message which is relayed + * but only its assertion content, the Response container is changed from a + * lib:AuthnResponse to a samlp:Response. + */ + lasso_assign_new_string(profile->private_data->artifact_message, + lasso_node_export_to_xml((LassoNode*)login->assertion)); +cleanup: + lasso_release_string(url); + lasso_release_xml_string(b64_samlArt); + lasso_release_xml_string(relayState); + return rc; } /** @@ -1363,8 +1381,8 @@ cleanup: gint lasso_login_build_response_msg(LassoLogin *login, gchar *remote_providerID) { - LassoProvider *remote_provider; - LassoProfile *profile; + LassoProvider *remote_provider = NULL; + LassoProfile *profile = NULL; lasso_error_t rc = 0; g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); @@ -1426,6 +1444,16 @@ lasso_login_build_response_msg(LassoLogin *login, gchar *remote_providerID) lasso_profile_set_response_status(profile, LASSO_SAML_STATUS_CODE_SUCCESS); lasso_session_remove_status(profile->session, remote_providerID); + } else if (profile->private_data->artifact_message) { + xmlDoc *doc; + char *artifact_message = profile->private_data->artifact_message; + doc = lasso_xml_parse_memory(artifact_message, + strlen(artifact_message)); + lasso_profile_set_response_status(profile, + LASSO_SAML_STATUS_CODE_SUCCESS); + lasso_list_add_new_gobject(((LassoSamlpResponse*)profile->response)->Assertion, + lasso_misc_text_node_new_with_xml_node(xmlDocGetRootElement(doc))); + lasso_release_doc(doc); } } } else { @@ -2174,6 +2202,8 @@ lasso_login_process_request_msg(LassoLogin *login, gchar *request_msg) /* get AssertionArtifact */ lasso_assign_string(login->assertionArtifact, LASSO_SAMLP_REQUEST(profile->request)->AssertionArtifact); + lasso_assign_string(login->parent.private_data->artifact, + login->assertionArtifact); /* Keep a copy of request msg so signature can be verified when we get * the providerId in lasso_login_build_response_msg() diff --git a/lasso/id-ff/logout.c b/lasso/id-ff/logout.c index 7567a47d..51f82f4c 100644 --- a/lasso/id-ff/logout.c +++ b/lasso/id-ff/logout.c @@ -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; } /** diff --git a/lasso/id-ff/profile.c b/lasso/id-ff/profile.c index bc9a65d1..768c3ea2 100644 --- a/lasso/id-ff/profile.c +++ b/lasso/id-ff/profile.c @@ -675,7 +675,7 @@ lasso_profile_set_soap_fault_response(LassoProfile *profile, const char *faultco * * Return value: #LASSO_PROVIDER_ROLE_NONE if nothing can be said, #LASSO_PROVIDER_ROLE_SP if a * federation qualifier by @remote_provider_id exists or #LASSO_PROVIDER_ROLE_IDP if a federation - * qualifier by our own #LassoProvider.providerID exists. + * qualifier by our own #LassoProvider.ProviderID exists. */ LassoProviderRole lasso_profile_sso_role_with(LassoProfile *profile, const char *remote_provider_id) { diff --git a/lasso/id-ff/profile.h b/lasso/id-ff/profile.h index d04f1727..096d2f92 100644 --- a/lasso/id-ff/profile.h +++ b/lasso/id-ff/profile.h @@ -139,6 +139,9 @@ typedef enum { * HTTP-Post binding), the body of the POST will be in this field, * @msg_relayState: put there the relaystate to put in the genereated URL for HTTP-Redirect or * HTTP-Get binding. + * @signature_status: result of the last signature validation. + * @identity: the state of federation linking for the current user. + * @session: the state of global SSO session for the current user. * * #LassoProfile, child class of #LassoNode is the basis object of profiles object like #LassoLogin, #LassoLogout, * #LassoDefederation, #LassoNameIdentifierMapping, #LassoNameRegistration, #LassoNameIdManagement diff --git a/lasso/id-ff/session.c b/lasso/id-ff/session.c index d55e35b5..d5294ff3 100644 --- a/lasso/id-ff/session.c +++ b/lasso/id-ff/session.c @@ -32,9 +32,12 @@ #include "../lasso_config.h" #include "session.h" #include "sessionprivate.h" +#include "../xml/lib_authentication_statement.h" #include "../xml/saml_assertion.h" +#include "../xml/saml-2.0/saml2_authn_statement.h" #include "../xml/saml-2.0/saml2_assertion.h" #include "../utils.h" +#include "../debug.h" #include <libxml/parser.h> #include <libxml/tree.h> @@ -45,10 +48,145 @@ #include "../id-wsf-2.0/sessionprivate.h" #endif +static gboolean lasso_match_name_id(LassoNode *a, LassoNode *b); + +struct _NidAndSessionIndex { + LassoNode *name_id; + char *assertion_id; + char *session_index; +}; + +struct _NidAndSessionIndex * +lasso_new_nid_and_session_index(LassoNode *name_id, const char *assertion_id, const char + *session_index) +{ + struct _NidAndSessionIndex *nid_and_session_index = g_new0(struct _NidAndSessionIndex, 1); + lasso_assign_gobject(nid_and_session_index->name_id, name_id); + lasso_assign_string(nid_and_session_index->assertion_id, assertion_id); + lasso_assign_string(nid_and_session_index->session_index, session_index); + + return nid_and_session_index; +} + +void +lasso_release_nid_and_session_index(struct _NidAndSessionIndex *nid_and_session_index) +{ + lasso_release_gobject(nid_and_session_index->name_id); + lasso_release_string(nid_and_session_index->session_index); + lasso_release_string(nid_and_session_index->assertion_id); +} + +void +lasso_release_list_of_nid_an_session_index(GList *list) +{ + g_list_foreach(list, (GFunc)lasso_release_nid_and_session_index, NULL); + g_list_free(list); +} + /*****************************************************************************/ /* public methods */ /*****************************************************************************/ +static void +lasso_session_add_nid_and_session_index(LassoSession *session, + const char *providerID, + struct _NidAndSessionIndex *nid_and_session_index) +{ + GList *l = g_hash_table_lookup(session->private_data->nid_and_session_indexes, providerID); + GList *i; + + lasso_foreach(i, l) { + struct _NidAndSessionIndex *other_nid_and_sid = i->data; + + /* do some sharing and limit doublons */ + if (lasso_match_name_id(other_nid_and_sid->name_id, nid_and_session_index->name_id)) { + if (lasso_strisequal(other_nid_and_sid->session_index, nid_and_session_index->session_index)) { + lasso_release_nid_and_session_index(nid_and_session_index); + return; + } + // lasso_assign_gobject(nid_and_session_index->name_id, other_nid_and_sid->name_id); + } + } + if (l) { + l = g_list_append(l, nid_and_session_index); + } else { + l = g_list_append(l, nid_and_session_index); + g_hash_table_insert(session->private_data->nid_and_session_indexes, + g_strdup(providerID), l); + } +} + +/** + * lasso_session_add_assertion_nid_and_session_index: + * + * Extract NameID and SessionIndex and keep them around. + * + */ +static gint +lasso_session_add_assertion_nid_and_session_index(LassoSession *session, const gchar *providerID, + LassoNode *assertion) +{ + struct _NidAndSessionIndex *nid_and_session_index = NULL; + + lasso_bad_param(SESSION, session); + lasso_null_param(assertion); + + if (LASSO_IS_SAML_ASSERTION(assertion)) { /* saml 1.1 */ + LassoSamlAssertion *saml_assertion = (LassoSamlAssertion*) assertion; + LassoLibAuthenticationStatement *auth_statement = NULL; + LassoSamlSubjectStatementAbstract *ss = NULL; + + if (saml_assertion->SubjectStatement) + ss = &saml_assertion->SubjectStatement->parent; + else if (saml_assertion->AuthenticationStatement) + ss = &saml_assertion->AuthenticationStatement->parent; + else + return LASSO_PARAM_ERROR_INVALID_VALUE; + if (! ss->Subject) + return LASSO_PARAM_ERROR_INVALID_VALUE; + if (! ss->Subject->NameIdentifier) + return LASSO_PARAM_ERROR_INVALID_VALUE; + if (! LASSO_IS_LIB_AUTHENTICATION_STATEMENT(saml_assertion->AuthenticationStatement)) + return LASSO_ERROR_UNIMPLEMENTED; + auth_statement = (LassoLibAuthenticationStatement*) + saml_assertion->AuthenticationStatement; + if (! auth_statement->SessionIndex) + return 0; + nid_and_session_index = lasso_new_nid_and_session_index( + (LassoNode*)ss->Subject->NameIdentifier, + saml_assertion->AssertionID, + auth_statement->SessionIndex); + lasso_session_add_nid_and_session_index(session, + providerID, nid_and_session_index); + } else if (LASSO_IS_SAML2_ASSERTION(assertion)) { /* saml 2.0 */ + LassoSaml2Assertion *saml2_assertion = (LassoSaml2Assertion*) assertion; + GList *iter; + + if (! saml2_assertion->Subject) + return LASSO_PARAM_ERROR_INVALID_VALUE; + if (! saml2_assertion->Subject->NameID) + return LASSO_PARAM_ERROR_INVALID_VALUE; + if (! saml2_assertion->AuthnStatement) + return 0; + lasso_foreach(iter, saml2_assertion->AuthnStatement) { + LassoSaml2AuthnStatement *authn_statement = iter->data; + + if (authn_statement->SessionIndex) { + nid_and_session_index = lasso_new_nid_and_session_index( + (LassoNode*)saml2_assertion->Subject->NameID, + saml2_assertion->ID, + authn_statement->SessionIndex); + lasso_session_add_nid_and_session_index(session, + providerID, + nid_and_session_index); + } + } + } else { + return LASSO_ERROR_UNIMPLEMENTED; + } + return 0; +} + static gint lasso_session_add_assertion_simple(LassoSession *session, const char *providerID, LassoNode *assertion) @@ -57,12 +195,142 @@ lasso_session_add_assertion_simple(LassoSession *session, const char *providerID g_return_val_if_fail(providerID != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); g_return_val_if_fail(assertion != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + if (lasso_flag_thin_sessions) { /* do not store the full assertion */ + return 0; + } g_hash_table_insert(session->assertions, g_strdup(providerID), g_object_ref(assertion)); return 0; } +static gboolean +lasso_match_name_id(LassoNode *a, LassoNode *b) +{ + if (LASSO_IS_SAML_NAME_IDENTIFIER(a) && LASSO_IS_SAML_NAME_IDENTIFIER(b)) { + return lasso_saml_name_identifier_equals((LassoSamlNameIdentifier*)a, + (LassoSamlNameIdentifier*)b); + + } else if (LASSO_IS_SAML2_NAME_ID(a) && LASSO_IS_SAML2_NAME_ID(b)) { + return lasso_saml2_name_id_equals((LassoSaml2NameID*)a, + (LassoSaml2NameID*)b); + } + return FALSE; +} + +/** + * lasso_session_get_session_indexes: + * @session: a #LassoSession object + * @providerID: a provider id + * @name_id: a #LassoSamlAssertion or #LassoSaml2Assertion object + * + * Gets all the registered session indexes for this session. + * + * Return value:(transfer full)(element-type utf8): a list of string containing the session index identifiers. + */ +GList* +lasso_session_get_session_indexes(LassoSession *session, + const gchar *providerID, + LassoNode *node) +{ + GList *l = NULL, *iter = NULL; + GList *ret = NULL; + + if (! LASSO_IS_SESSION(session)) + return NULL; + if (! providerID) + return NULL; + l = g_hash_table_lookup(session->private_data->nid_and_session_indexes, + providerID); + + lasso_foreach(iter, l) { + struct _NidAndSessionIndex *nid_and_session_index = iter->data; + + if (! nid_and_session_index->session_index) + continue; + + if (node && ! lasso_match_name_id(node, nid_and_session_index->name_id)) { + continue; + } + lasso_list_add_string(ret, nid_and_session_index->session_index); + } + return ret; +} + +/** + * lasso_session_get_name_ids: + * @session: a #LassoSession object + * @providerID: a provider identifier + * + * List the known NameID coming from this provider during this session. + * + * Return value:(transfer full)(element-type LassoNode): a list of #LassoNode objects. + */ +GList* +lasso_session_get_name_ids(LassoSession *session, const gchar *providerID) +{ + GList *nid_and_session_indexes = NULL; + GList *ret = NULL; + GList *i, *j; + + if (! LASSO_IS_SESSION(session)) + return NULL; + + if (! providerID) + return NULL; + + nid_and_session_indexes = g_hash_table_lookup(session->private_data->nid_and_session_indexes, + providerID); + + lasso_foreach(i, nid_and_session_indexes) { + struct _NidAndSessionIndex *nid_and_session_index = i->data; + int ok = 1; + + lasso_foreach(j, ret) { + if (lasso_match_name_id(j->data, nid_and_session_index->name_id)) { + ok = 0; + break; + } + } + if (ok) { + lasso_list_add_gobject(ret, nid_and_session_index->name_id); + } + } + return ret; +} + +/** + * lasso_session_get_assertion_ids: + * @session: a #LassoSession object + * @providerID: a provider identifier + * + * List the ids of assertions received during the current session. + * + * Return value:(transfer full)(element-type utf8): a list of strings + */ +GList* +lasso_session_get_assertion_ids(LassoSession *session, const gchar *providerID) +{ + GList *nid_and_session_indexes = NULL; + GList *ret = NULL; + GList *i; + + if (! LASSO_IS_SESSION(session)) + return NULL; + + if (! providerID) + return NULL; + + nid_and_session_indexes = g_hash_table_lookup(session->private_data->nid_and_session_indexes, + providerID); + + lasso_foreach(i, nid_and_session_indexes) { + struct _NidAndSessionIndex *nid_and_session_index = i->data; + lasso_list_add_string(ret, nid_and_session_index->assertion_id); + } + return ret; +} + /** * lasso_session_add_assertion: * @session: a #LassoSession @@ -83,7 +351,10 @@ lasso_session_add_assertion(LassoSession *session, const char *providerID, Lasso if (ret != 0) { return ret; } - + ret = lasso_session_add_assertion_nid_and_session_index(session, providerID, assertion); + if (ret != 0) { + return ret; + } /* ID-WSF specific need */ if (LASSO_IS_SAML_ASSERTION(assertion)) { LassoSamlAssertion *saml_assertion = LASSO_SAML_ASSERTION(assertion); @@ -253,7 +524,7 @@ lasso_session_get_status(LassoSession *session, const gchar *providerID) } static void -add_providerID(gchar *key, G_GNUC_UNUSED LassoLibAssertion *assertion, LassoSession *session) +add_providerID(gchar *key, G_GNUC_UNUSED struct _NidAndSessionIndex *ignored, LassoSession *session) { lasso_list_add_string(session->private_data->providerIDs, key); } @@ -277,7 +548,7 @@ lasso_session_get_provider_index(LassoSession *session, gint index) g_return_val_if_fail(LASSO_IS_SESSION(session), NULL); g_return_val_if_fail(session->private_data, NULL); - length = g_hash_table_size(session->assertions); + length = g_hash_table_size(session->private_data->nid_and_session_indexes); if (length == 0) return NULL; @@ -308,7 +579,8 @@ lasso_session_init_provider_ids(LassoSession *session) g_return_if_fail(session->private_data); lasso_release_list_of_strings(session->private_data->providerIDs); - g_hash_table_foreach(session->assertions, (GHFunc)add_providerID, session); + g_hash_table_foreach(session->private_data->nid_and_session_indexes, (GHFunc)add_providerID, + session); } @@ -327,12 +599,18 @@ lasso_session_is_empty(LassoSession *session) return TRUE; } - if (g_hash_table_size(session->assertions)) { + if (g_hash_table_size(session->assertions) + + g_hash_table_size(session->private_data->status) + + g_hash_table_size(session->private_data->assertions_by_id) + + g_hash_table_size(session->private_data->nid_and_session_indexes)) + { return FALSE; } - if (g_hash_table_size(session->private_data->status)) { +#ifdef LASSO_WSF_ENABLED + if (g_hash_table_size(session->eprs)) { return FALSE; } +#endif return TRUE; } @@ -352,7 +630,10 @@ lasso_session_count_assertions(LassoSession *session) if (! LASSO_IS_SESSION(session)) return -1; - hashtable = session->assertions; + if (lasso_flag_thin_sessions) + hashtable = session->private_data->nid_and_session_indexes; + else + hashtable = session->assertions; return hashtable ? g_hash_table_size(hashtable) : 0; } @@ -377,16 +658,21 @@ lasso_session_is_dirty(LassoSession *session) gint lasso_session_remove_assertion(LassoSession *session, const gchar *providerID) { - if (! LASSO_IS_SESSION(session) || lasso_strisempty(providerID)) { - return LASSO_PARAM_ERROR_INVALID_VALUE; - } + int rc = 0; + gboolean ok1, ok2; + + lasso_bad_param(SESSION, session); + lasso_return_val_if_fail(! lasso_strisempty(providerID), LASSO_PARAM_ERROR_INVALID_VALUE); - if (g_hash_table_remove(session->assertions, providerID)) { + ok1 = g_hash_table_remove(session->assertions, providerID); + ok2 = g_hash_table_remove(session->private_data->nid_and_session_indexes, providerID); + + if (ok1 || ok2) { session->is_dirty = TRUE; - return 0; + } else { + rc = LASSO_PROFILE_ERROR_MISSING_ASSERTION; } - - return LASSO_PROFILE_ERROR_MISSING_ASSERTION; + return rc; } /** @@ -490,6 +776,35 @@ add_status_childnode(gchar *key, LassoSamlpStatus *value, DumpContext *context) xmlAddChild(t, lasso_node_get_xmlNode(LASSO_NODE(value), TRUE)); } +#define NID_AND_SESSION_INDEX "NidAndSessionIndex" +#define SESSION_INDEX "SessionIndex" +#define PROVIDER_ID "ProviderID" +#define ASSERTION_ID "AssertionID" + +static void +xmlnode_add_assertion_nid_and_session_indexes(gchar *key, GList *nid_and_session_indexes, DumpContext *context) +{ + GList *iter; + + if (! nid_and_session_indexes) { + return; + } + lasso_foreach(iter, nid_and_session_indexes) { + struct _NidAndSessionIndex *nid_and_session_index = iter->data; + xmlNode *node = xmlSecAddChild(context->parent, BAD_CAST NID_AND_SESSION_INDEX, + BAD_CAST LASSO_LASSO_HREF); + + xmlSetProp(node, BAD_CAST PROVIDER_ID, BAD_CAST key); + xmlSetProp(node, BAD_CAST ASSERTION_ID, BAD_CAST nid_and_session_index->assertion_id); + if (nid_and_session_index->session_index) { + xmlSetProp(node, BAD_CAST SESSION_INDEX, + BAD_CAST nid_and_session_index->session_index); + } + xmlSecAddChildNode(node, lasso_node_get_xmlNode(nid_and_session_index->name_id, + FALSE)); + } +} + static xmlNode* get_xmlNode(LassoNode *node, G_GNUC_UNUSED gboolean lasso_dump) { @@ -513,6 +828,10 @@ get_xmlNode(LassoNode *node, G_GNUC_UNUSED gboolean lasso_dump) g_hash_table_foreach(session->private_data->assertions_by_id, (GHFunc)add_assertion_by_id, &context); } + if (g_hash_table_size(session->private_data->nid_and_session_indexes)) { + g_hash_table_foreach(session->private_data->nid_and_session_indexes, + (GHFunc)xmlnode_add_assertion_nid_and_session_indexes, &context); + } #ifdef LASSO_WSF_ENABLED lasso_session_id_wsf2_dump_eprs(session, xmlnode); @@ -547,6 +866,39 @@ cleanup: return ret; } +static void +init_from_xml_nid_and_session_index(LassoNode *node, xmlNode *nid_and_session_index_node) +{ + xmlChar *session_index = NULL; + xmlChar *provider_id = NULL; + xmlChar *assertion_id = NULL; + xmlNode *nid; + LassoNode *name_id; + struct _NidAndSessionIndex *nid_and_session_index; + + provider_id = xmlGetProp(nid_and_session_index_node, BAD_CAST PROVIDER_ID); + if (! provider_id) + goto cleanup; + assertion_id = xmlGetProp(nid_and_session_index_node, BAD_CAST ASSERTION_ID); + if (! assertion_id) + goto cleanup; + nid = xmlSecGetNextElementNode(nid_and_session_index_node->children); + if (! nid) + goto cleanup; + name_id = lasso_node_new_from_xmlNode(nid); + if (! node) + goto cleanup; + session_index = xmlGetProp(nid_and_session_index_node, BAD_CAST SESSION_INDEX); + nid_and_session_index = lasso_new_nid_and_session_index(name_id, (char*)assertion_id, + (char*)session_index); + lasso_session_add_nid_and_session_index((LassoSession*)node, (char*)provider_id, + nid_and_session_index); +cleanup: + lasso_release_xml_string(session_index); + lasso_release_xml_string(provider_id); + lasso_release_xml_string(assertion_id); +} + static int init_from_xml(LassoNode *node, xmlNode *xmlnode) { @@ -573,6 +925,8 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode) assertion = lasso_node_new_from_xmlNode(n); lasso_session_add_assertion_simple(session, (char*)value, assertion); + /* automatic upgrade from old session serialization to the new */ + lasso_session_add_assertion_nid_and_session_index(session, (char*)value, assertion); lasso_release_gobject(assertion); xmlFree(value); } @@ -605,6 +959,10 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode) status); } } + if (xmlSecCheckNodeName(t, BAD_CAST NID_AND_SESSION_INDEX, + BAD_CAST LASSO_LASSO_HREF)) { + init_from_xml_nid_and_session_index(node, t); + } #ifdef LASSO_WSF_ENABLED lasso_session_id_wsf2_init_eprs(session, t); @@ -635,6 +993,7 @@ dispose(GObject *object) lasso_release_ghashtable(session->private_data->status); lasso_release_list_of_strings(session->private_data->providerIDs); lasso_release_ghashtable(session->private_data->assertions_by_id); + lasso_release_ghashtable(session->private_data->nid_and_session_indexes); #ifdef LASSO_WSF_ENABLED lasso_release_ghashtable(session->private_data->eprs); @@ -643,17 +1002,6 @@ dispose(GObject *object) G_OBJECT_CLASS(parent_class)->dispose(object); } -static void -finalize(GObject *object) -{ - LassoSession *session = LASSO_SESSION(object); - - lasso_release(session->private_data); - session->private_data = NULL; - - G_OBJECT_CLASS(parent_class)->finalize(object); -} - /*****************************************************************************/ /* instance and class init functions */ /*****************************************************************************/ @@ -661,7 +1009,7 @@ finalize(GObject *object) static void instance_init(LassoSession *session) { - session->private_data = g_new0 (LassoSessionPrivate, 1); + session->private_data = LASSO_SESSION_GET_PRIVATE(session); session->private_data->dispose_has_run = FALSE; session->private_data->providerIDs = NULL; session->private_data->status = g_hash_table_new_full(g_str_hash, g_str_equal, @@ -671,14 +1019,17 @@ instance_init(LassoSession *session) g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)xmlFree); + session->assertions = g_hash_table_new_full(g_str_hash, g_str_equal, + (GDestroyNotify)g_free, (GDestroyNotify)lasso_node_destroy); + session->is_dirty = FALSE; + session->private_data->nid_and_session_indexes = g_hash_table_new_full(g_str_hash, + g_str_equal, (GDestroyNotify)g_free, + (GDestroyNotify)lasso_release_list_of_nid_an_session_index); #ifdef LASSO_WSF_ENABLED session->private_data->eprs = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref); #endif - session->assertions = g_hash_table_new_full(g_str_hash, g_str_equal, - (GDestroyNotify)g_free, (GDestroyNotify)lasso_node_destroy); - session->is_dirty = FALSE; } static void @@ -692,9 +1043,9 @@ class_init(LassoSessionClass *klass) nclass->node_data = g_new0(LassoNodeClassData, 1); lasso_node_class_set_nodename(nclass, "Session"); lasso_node_class_set_ns(nclass, LASSO_LASSO_HREF, LASSO_LASSO_PREFIX); + g_type_class_add_private(nclass, sizeof(LassoSessionPrivate)); G_OBJECT_CLASS(klass)->dispose = dispose; - G_OBJECT_CLASS(klass)->finalize = finalize; } GType @@ -784,3 +1135,12 @@ void lasso_session_destroy(LassoSession *session) return; lasso_node_destroy(LASSO_NODE(session)); } + +gboolean +lasso_session_has_slo_session(LassoSession *session, const gchar *provider_id) +{ + if (! LASSO_IS_SESSION(session)) + return FALSE; + return g_hash_table_lookup(session->private_data->nid_and_session_indexes, provider_id) != + NULL; +} diff --git a/lasso/id-ff/session.h b/lasso/id-ff/session.h index d6189273..62fe323d 100644 --- a/lasso/id-ff/session.h +++ b/lasso/id-ff/session.h @@ -84,6 +84,13 @@ LASSO_EXPORT LassoNode* lasso_session_get_assertion( LASSO_EXPORT lasso_error_t lasso_session_add_assertion(LassoSession *session, const char *providerID, LassoNode *assertion); +LASSO_EXPORT GList *lasso_session_get_name_ids(LassoSession *session, const gchar *providerID); + +LASSO_EXPORT GList *lasso_session_get_session_indexes(LassoSession *session, + const gchar *providerID, LassoNode *name_id); + +LASSO_EXPORT GList* lasso_session_get_assertion_ids(LassoSession *session, const gchar *providerID); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/id-ff/sessionprivate.h b/lasso/id-ff/sessionprivate.h index a55bbb82..03af335a 100644 --- a/lasso/id-ff/sessionprivate.h +++ b/lasso/id-ff/sessionprivate.h @@ -41,11 +41,15 @@ struct _LassoSessionPrivate GList *providerIDs; GHashTable *status; /* hold temporary response status for sso-art */ GHashTable *assertions_by_id; + GHashTable *nid_and_session_indexes; #ifdef LASSO_WSF_ENABLED GHashTable *eprs; #endif }; +#define LASSO_SESSION_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), LASSO_TYPE_SESSION, LassoSessionPrivate)) + gint lasso_session_add_status(LassoSession *session, const char *providerID, LassoNode *status); gint lasso_session_add_assertion_with_id(LassoSession *session, @@ -62,6 +66,8 @@ gboolean lasso_session_is_dirty(LassoSession *session); void lasso_session_init_provider_ids(LassoSession *session); +gboolean lasso_session_has_slo_session(LassoSession *session, const gchar *provider_id); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/lasso.c b/lasso/lasso.c index 98248dac..3d127f9b 100644 --- a/lasso/lasso.c +++ b/lasso/lasso.c @@ -95,6 +95,8 @@ gboolean lasso_flag_add_signature = TRUE; static void lasso_flag_parse_environment_variable(); /* do not sign messages */ gboolean lasso_flag_sign_messages = TRUE; +/* thin sessions */ +gboolean lasso_flag_thin_sessions = FALSE; #ifndef LASSO_FLAG_ENV_VAR #define LASSO_FLAG_ENV_VAR "LASSO_FLAG" @@ -317,6 +319,9 @@ void lasso_set_flag(char *flag) { lasso_flag_sign_messages = value; continue; } + if (lasso_strisequal(flag,"thin-sessions")) { + lasso_flag_thin_sessions = value; + } } while (FALSE); } diff --git a/lasso/saml-2.0/login.c b/lasso/saml-2.0/login.c index 31343522..7b96868d 100644 --- a/lasso/saml-2.0/login.c +++ b/lasso/saml-2.0/login.c @@ -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; diff --git a/lasso/saml-2.0/logout.c b/lasso/saml-2.0/logout.c index 8cb9da56..2244d566 100644 --- a/lasso/saml-2.0/logout.c +++ b/lasso/saml-2.0/logout.c @@ -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; - - assertion_SessionIndex = _lasso_saml2_assertion_get_session_index(assertion); - lasso_foreach(iter, session_indexes) { - if (lasso_strisequal((char*)iter->data, assertion_SessionIndex)) { + logout_session_indexes = lasso_samlp2_logout_request_get_session_indexes(logout_request); + + 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 */ diff --git a/lasso/xml/lib_logout_request.c b/lasso/xml/lib_logout_request.c index 13124c2e..143ec83e 100644 --- a/lasso/xml/lib_logout_request.c +++ b/lasso/xml/lib_logout_request.c @@ -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; +} diff --git a/lasso/xml/lib_logout_request.h b/lasso/xml/lib_logout_request.h index b61b3bfc..75732309 100644 --- a/lasso/xml/lib_logout_request.h +++ b/lasso/xml/lib_logout_request.h @@ -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 */ diff --git a/lasso/xml/saml_name_identifier.c b/lasso/xml/saml_name_identifier.c index 1d0d1a14..a93c8f7c 100644 --- a/lasso/xml/saml_name_identifier.c +++ b/lasso/xml/saml_name_identifier.c @@ -98,6 +98,20 @@ lasso_saml_name_identifier_get_type() return this_type; } +gboolean +lasso_saml_name_identifier_equals(LassoSamlNameIdentifier *a, + LassoSamlNameIdentifier *b) { + if (a == NULL || b == NULL) + return FALSE; + + if (! LASSO_IS_SAML_NAME_IDENTIFIER(a) && ! LASSO_IS_SAML_NAME_IDENTIFIER(b)) { + return FALSE; + } + return lasso_strisequal(a->NameQualifier, b->NameQualifier) + && lasso_strisequal(a->Format, b->Format) + && lasso_strisequal(a->content, b->content); +} + /** * lasso_saml_name_identifier_new: * diff --git a/lasso/xml/saml_name_identifier.h b/lasso/xml/saml_name_identifier.h index 4902727c..ede9dbab 100644 --- a/lasso/xml/saml_name_identifier.h +++ b/lasso/xml/saml_name_identifier.h @@ -83,6 +83,9 @@ LASSO_EXPORT LassoSamlNameIdentifier* lasso_saml_name_identifier_new(void); LASSO_EXPORT LassoSamlNameIdentifier* lasso_saml_name_identifier_new_from_xmlNode( xmlNode *xmlnode); +LASSO_EXPORT gboolean lasso_saml_name_identifier_equals(LassoSamlNameIdentifier *a, + LassoSamlNameIdentifier *b); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/xml/strings.h b/lasso/xml/strings.h index 391ffb67..7c7be759 100644 --- a/lasso/xml/strings.h +++ b/lasso/xml/strings.h @@ -626,7 +626,7 @@ * LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED: * * <emphasis>Federated</emphasis> name identifier constant, used in - * #LassoNameIdentifier. It implies the name identifier belongs to + * #LassoSamlNameIdentifier. It implies the name identifier belongs to * a federation established between SP and IdP. */ #define LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED "urn:liberty:iff:nameid:federated" @@ -634,14 +634,14 @@ /** * LASSO_LIB_NAME_IDENTIFIER_FORMAT_ONE_TIME: * - * "One-time" name identifier constant, used in #LassoNameIdentifier. + * "One-time" name identifier constant, used in #LassoSamlNameIdentifier. */ #define LASSO_LIB_NAME_IDENTIFIER_FORMAT_ONE_TIME "urn:liberty:iff:nameid:one-time" /** * LASSO_LIB_NAME_IDENTIFIER_FORMAT_ENCRYPTED: * - * "Encrypted" name identifier constant, used in #LassoNameIdentifier. + * "Encrypted" name identifier constant, used in #LassoSamlNameIdentifier. */ #define LASSO_LIB_NAME_IDENTIFIER_FORMAT_ENCRYPTED "urn:liberty:iff:nameid:encrypted" #define LASSO_LIB_NAME_IDENTIFIER_FORMAT_ENTITYID "urn:liberty:iff:nameid:entityID" diff --git a/tests/login_tests.c b/tests/login_tests.c index c432fe9f..c1688b02 100644 --- a/tests/login_tests.c +++ b/tests/login_tests.c @@ -33,7 +33,6 @@ #include "tests.h" #include "../bindings/ghashtable.h" - static char* generateIdentityProviderContextDump() { @@ -151,6 +150,8 @@ START_TEST(test02_serviceProviderLogin) char *spLoginDump; int requestType; char *found; + char *artifact_message; + char *artifact; serviceProviderContextDump = generateServiceProviderContextDump(); spContext = lasso_server_new_from_dump(serviceProviderContextDump); @@ -228,6 +229,12 @@ START_TEST(test02_serviceProviderLogin) serviceProviderId = g_strdup(LASSO_PROFILE(idpLoginContext)->remote_providerID); fail_unless(serviceProviderId != NULL, "lasso_profile_get_remote_providerID shouldn't return NULL"); + if (lasso_flag_thin_sessions) { + /* when using thin sessions, the way artifact message is constructed changes as the + * session no more contains full assertions. */ + artifact = g_strdup(lasso_profile_get_artifact(&idpLoginContext->parent)); + artifact_message = g_strdup(lasso_profile_get_artifact_message(&idpLoginContext->parent)); + } /* Service provider assertion consumer */ lasso_server_destroy(spContext); @@ -262,6 +269,10 @@ START_TEST(test02_serviceProviderLogin) idpLoginContext = lasso_login_new(idpContext); check_true(LASSO_IS_LOGIN(idpLoginContext)); check_good_rc(lasso_login_process_request_msg(idpLoginContext, soapRequestMsg)); + if (lasso_flag_thin_sessions) { + check_str_equals(idpLoginContext->assertionArtifact, artifact); + lasso_profile_set_artifact_message(&idpLoginContext->parent, artifact_message); + } check_good_rc(lasso_profile_set_session_from_dump(LASSO_PROFILE(idpLoginContext), idpSessionContextDump)); check_good_rc(lasso_login_build_response_msg(idpLoginContext, serviceProviderId)); @@ -323,6 +334,8 @@ START_TEST(test03_serviceProviderLogin) char *spIdentityContextDump; char *spSessionDump; int requestType; + char *artifact_message; + char *artifact; serviceProviderContextDump = generateServiceProviderContextDump(); spContext = lasso_server_new_from_dump(serviceProviderContextDump); @@ -366,7 +379,6 @@ START_TEST(test03_serviceProviderLogin) 1, /* authentication_result */ 0 /* is_consent_obtained */ ); - rc = lasso_login_build_assertion(idpLoginContext, LASSO_SAML_AUTHENTICATION_METHOD_PASSWORD, "FIXME: authenticationInstant", @@ -375,7 +387,6 @@ START_TEST(test03_serviceProviderLogin) "FIXME: notOnOrAfter"); rc = lasso_login_build_artifact_msg(idpLoginContext, LASSO_HTTP_METHOD_REDIRECT); fail_unless(rc == 0, "lasso_login_build_artifact_msg failed"); - idpIdentityContextDump = lasso_identity_dump(LASSO_PROFILE(idpLoginContext)->identity); fail_unless(idpIdentityContextDump != NULL, "lasso_identity_dump shouldn't return NULL"); @@ -390,6 +401,12 @@ START_TEST(test03_serviceProviderLogin) serviceProviderId = g_strdup(LASSO_PROFILE(idpLoginContext)->remote_providerID); fail_unless(serviceProviderId != NULL, "lasso_profile_get_remote_providerID shouldn't return NULL"); + if (lasso_flag_thin_sessions) { + /* when using thin sessions, the way artifact message is constructed changes as the + * session no more contains full assertions. */ + artifact = g_strdup(lasso_profile_get_artifact(&idpLoginContext->parent)); + artifact_message = g_strdup(lasso_profile_get_artifact_message(&idpLoginContext->parent)); + } /* Service provider assertion consumer */ lasso_server_destroy(spContext); @@ -417,7 +434,10 @@ START_TEST(test03_serviceProviderLogin) idpLoginContext = lasso_login_new(idpContext); rc = lasso_login_process_request_msg(idpLoginContext, soapRequestMsg); fail_unless(rc == 0, "lasso_login_process_request_msg failed"); - + if (lasso_flag_thin_sessions) { + check_str_equals(idpLoginContext->assertionArtifact, artifact); + lasso_profile_set_artifact_message(&idpLoginContext->parent, artifact_message); + } rc = lasso_profile_set_session_from_dump(LASSO_PROFILE(idpLoginContext), idpSessionContextDump); fail_unless(rc == 0, "lasso_login_set_assertion_from_dump failed"); |
