diff options
author | Frederic Peters <fpeters@entrouvert.com> | 2005-11-21 18:51:52 +0000 |
---|---|---|
committer | Frederic Peters <fpeters@entrouvert.com> | 2005-11-21 18:51:52 +0000 |
commit | 853f46fd9325b7f3eec0bc385c4a9bd763c031d4 (patch) | |
tree | 55a2fcb3a0432cee3d5591b89550871182fb2fb9 | |
parent | ab1e605ce59bba13464c814bc224146875b170ff (diff) | |
download | lasso-853f46fd9325b7f3eec0bc385c4a9bd763c031d4.tar.gz lasso-853f46fd9325b7f3eec0bc385c4a9bd763c031d4.tar.xz lasso-853f46fd9325b7f3eec0bc385c4a9bd763c031d4.zip |
starting SAML 2 logout
29 files changed, 1141 insertions, 125 deletions
diff --git a/lasso/id-ff/defederation.c b/lasso/id-ff/defederation.c index fdb5cc6b..2040e1a7 100644 --- a/lasso/id-ff/defederation.c +++ b/lasso/id-ff/defederation.c @@ -152,6 +152,7 @@ lasso_defederation_init_notification(LassoDefederation *defederation, gchar *rem LassoProvider *remote_provider; LassoFederation *federation; LassoSamlNameIdentifier *nameIdentifier; + LassoNode *nameIdentifier_n; g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); @@ -183,10 +184,11 @@ lasso_defederation_init_notification(LassoDefederation *defederation, gchar *rem } /* get the nameIdentifier to send the federation termination notification */ - nameIdentifier = lasso_profile_get_nameIdentifier(profile); + nameIdentifier_n = lasso_profile_get_nameIdentifier(profile); if (nameIdentifier == NULL) { return critical_error(LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND); } + nameIdentifier = LASSO_SAML_NAME_IDENTIFIER(nameIdentifier_n); if (federation->local_nameIdentifier) { profile->nameIdentifier = g_object_ref(federation->local_nameIdentifier); @@ -393,7 +395,8 @@ lasso_defederation_validate_notification(LassoDefederation *defederation) return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND); } - if (lasso_federation_verify_name_identifier(federation, nameIdentifier) == FALSE) { + if (lasso_federation_verify_name_identifier(federation, + LASSO_NODE(nameIdentifier)) == FALSE) { return critical_error(LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND); } diff --git a/lasso/id-ff/federation.c b/lasso/id-ff/federation.c index dbcc2a71..2f7cbbd9 100644 --- a/lasso/id-ff/federation.c +++ b/lasso/id-ff/federation.c @@ -23,6 +23,9 @@ */ #include <lasso/id-ff/federation.h> +#include <lasso/id-ff/provider.h> + +#include <lasso/xml/saml-2.0/saml2_name_id.h> struct _LassoFederationPrivate { @@ -98,25 +101,44 @@ lasso_federation_destroy(LassoFederation *federation) **/ gboolean lasso_federation_verify_name_identifier(LassoFederation *federation, - LassoSamlNameIdentifier *name_identifier) + LassoNode *name_identifier) { - char *s; + LassoProtocolConformance conformance; + char *s, *content; g_return_val_if_fail(LASSO_IS_FEDERATION(federation), FALSE); g_return_val_if_fail(LASSO_IS_NODE(name_identifier), FALSE); + if (LASSO_IS_SAML_NAME_IDENTIFIER(name_identifier)) { + conformance = LASSO_PROTOCOL_LIBERTY_1_2; + content = LASSO_SAML_NAME_IDENTIFIER(name_identifier)->content; + } else if (LASSO_IS_SAML2_NAME_ID(name_identifier)) { + conformance = LASSO_PROTOCOL_SAML_2_0; + content = LASSO_SAML2_NAME_ID(name_identifier)->content; + } else { + return FALSE; + } + /* verify local name identifier */ if (federation->local_nameIdentifier != NULL) { - s = LASSO_SAML_NAME_IDENTIFIER(federation->local_nameIdentifier)->content; - if (strcmp(s, name_identifier->content) == 0) { + if (conformance == LASSO_PROTOCOL_LIBERTY_1_2) { + s = LASSO_SAML_NAME_IDENTIFIER(federation->local_nameIdentifier)->content; + } else { + s = LASSO_SAML2_NAME_ID(federation->local_nameIdentifier)->content; + } + if (strcmp(s, content) == 0) { return TRUE; } } /* verify remote name identifier */ if (federation->remote_nameIdentifier != NULL) { - s = LASSO_SAML_NAME_IDENTIFIER(federation->remote_nameIdentifier)->content; - if (strcmp(s, name_identifier->content) == 0) { + if (conformance == LASSO_PROTOCOL_LIBERTY_1_2) { + s = LASSO_SAML_NAME_IDENTIFIER(federation->remote_nameIdentifier)->content; + } else { + s = LASSO_SAML2_NAME_ID(federation->remote_nameIdentifier)->content; + } + if (strcmp(s, content) == 0) { return TRUE; } } diff --git a/lasso/id-ff/federation.h b/lasso/id-ff/federation.h index 7b113d0b..e4861503 100644 --- a/lasso/id-ff/federation.h +++ b/lasso/id-ff/federation.h @@ -73,7 +73,7 @@ LASSO_EXPORT void lasso_federation_build_local_name_identifier(LassoFederation * LASSO_EXPORT void lasso_federation_destroy(LassoFederation *federation); LASSO_EXPORT gboolean lasso_federation_verify_name_identifier( - LassoFederation *federation, LassoSamlNameIdentifier *name_identifier); + LassoFederation *federation, LassoNode *name_identifier); #ifdef __cplusplus } diff --git a/lasso/id-ff/login.c b/lasso/id-ff/login.c index 69fad979..489e6afd 100644 --- a/lasso/id-ff/login.c +++ b/lasso/id-ff/login.c @@ -218,8 +218,7 @@ lasso_login_build_assertion(LassoLogin *login, if (profile->identity == NULL) return LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND; - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_build_assertion(login, authenticationMethod, authenticationInstant, reauthenticateOnOrAfter, notBefore, notOnOrAfter); @@ -582,8 +581,7 @@ lasso_login_accept_sso(LassoLogin *login) if (profile->response == NULL) return LASSO_ERROR_UNDEFINED; - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_accept_sso(login); } @@ -671,8 +669,7 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_build_artifact_msg(login, http_method); } @@ -803,8 +800,7 @@ lasso_login_build_authn_request_msg(LassoLogin *login) return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); } - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_build_authn_request_msg(login, remote_provider); } @@ -964,8 +960,7 @@ lasso_login_build_request_msg(LassoLogin *login) profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_build_request_msg(login); } @@ -1007,8 +1002,7 @@ lasso_login_build_response_msg(LassoLogin *login, gchar *remote_providerID) g_return_val_if_fail(LASSO_IS_LOGIN(login), -1); profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_build_response_msg(login, remote_providerID); } @@ -1142,8 +1136,7 @@ lasso_login_init_authn_request(LassoLogin *login, const gchar *remote_providerID if (LASSO_IS_PROVIDER(remote_provider) == FALSE) return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_init_authn_request(login, remote_provider, http_method); } @@ -1213,8 +1206,7 @@ lasso_login_init_request(LassoLogin *login, gchar *response_msg, g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_init_request(login, response_msg, response_http_method); } @@ -1328,8 +1320,7 @@ lasso_login_must_ask_for_consent(LassoLogin *login) { LassoProfile *profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_must_ask_for_consent(login); } @@ -1359,8 +1350,7 @@ lasso_login_must_authenticate(LassoLogin *login) g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_must_authenticate(login); } @@ -1410,8 +1400,7 @@ lasso_login_process_authn_request_msg(LassoLogin *login, const char *authn_reque profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_process_authn_request_msg(login, authn_request_msg); } @@ -1590,8 +1579,7 @@ lasso_login_process_request_msg(LassoLogin *login, gchar *request_msg) g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); g_return_val_if_fail(request_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_process_request_msg(login, request_msg); } @@ -1632,8 +1620,7 @@ lasso_login_process_response_msg(LassoLogin *login, gchar *response_msg) profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_process_response_msg(login, response_msg); } @@ -1916,8 +1903,7 @@ lasso_login_validate_request_msg(LassoLogin *login, gboolean authentication_resu profile = LASSO_PROFILE(login); - if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ - LASSO_PROTOCOL_SAML_2_0) { + IF_SAML2(profile) { return lasso_saml20_login_validate_request_msg(login, authentication_result, is_consent_obtained); } diff --git a/lasso/id-ff/logout.c b/lasso/id-ff/logout.c index f2454220..6a872498 100644 --- a/lasso/id-ff/logout.c +++ b/lasso/id-ff/logout.c @@ -22,19 +22,16 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <lasso/xml/lib_authentication_statement.h> + #include <lasso/id-ff/logout.h> +#include <lasso/id-ff/logoutprivate.h> #include <lasso/id-ff/profileprivate.h> #include <lasso/id-ff/providerprivate.h> #include <lasso/id-ff/sessionprivate.h> -#include <lasso/xml/lib_authentication_statement.h> - -struct _LassoLogoutPrivate -{ - gboolean dispose_has_run; - gboolean all_soap; -}; +#include <lasso/saml-2.0/logoutprivate.h> static void check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile); @@ -86,6 +83,10 @@ lasso_logout_build_request_msg(LassoLogout *logout) return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); } + IF_SAML2(profile) { + return lasso_saml20_logout_build_request_msg(logout, remote_provider); + } + /* build the logout request message */ if (logout->initial_http_request_method == LASSO_HTTP_METHOD_SOAP) { /* build the logout request message */ @@ -158,10 +159,14 @@ lasso_logout_build_response_msg(LassoLogout *logout) LassoProvider *provider; gchar *url, *query; - g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); + g_return_val_if_fail(LASSO_IS_LOGOUT(logout), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); profile = LASSO_PROFILE(logout); + IF_SAML2(profile) { + return lasso_saml20_logout_build_response_msg(logout); + } + if (profile->response == NULL) { if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { profile->response = lasso_lib_logout_response_new_full( @@ -193,7 +198,7 @@ lasso_logout_build_response_msg(LassoLogout *logout) if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { profile->msg_url = NULL; LASSO_SAMLP_RESPONSE_ABSTRACT(profile->response)->private_key_file = - profile->server->private_key; + g_strdup(profile->server->private_key); LASSO_SAMLP_RESPONSE_ABSTRACT(profile->response)->certificate_file = profile->server->certificate; profile->msg_body = lasso_node_export_to_soap(profile->response); @@ -212,7 +217,7 @@ lasso_logout_build_response_msg(LassoLogout *logout) if (url == NULL) { return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL); } - query = lasso_node_export_to_query(LASSO_NODE(profile->response), + query = lasso_node_export_to_query(profile->response, profile->server->signature_method, profile->server->private_key); if (query == NULL) { @@ -293,7 +298,7 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID, LassoProfile *profile; LassoProvider *remote_provider; LassoSamlNameIdentifier *nameIdentifier; - LassoNode *assertion_n; + LassoNode *assertion_n, *name_identifier_n; LassoSamlAssertion *assertion; LassoFederation *federation = NULL; gboolean is_http_redirect_get_method = FALSE; @@ -321,6 +326,17 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID, return critical_error(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID); } + /* get the provider */ + remote_provider = g_hash_table_lookup( + profile->server->providers, profile->remote_providerID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + return critical_error(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) { @@ -353,10 +369,11 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID, return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND); } - nameIdentifier = lasso_profile_get_nameIdentifier(profile); - if (nameIdentifier == NULL) { + 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) { profile->nameIdentifier = g_object_ref(federation->local_nameIdentifier); } else { @@ -366,13 +383,6 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID, profile->nameIdentifier = g_object_ref(nameIdentifier); } - /* get the provider */ - remote_provider = g_hash_table_lookup( - profile->server->providers, profile->remote_providerID); - if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { - return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); - } - /* get / verify http method */ if (http_method == LASSO_HTTP_METHOD_ANY) { http_method = lasso_provider_get_first_http_method( @@ -464,7 +474,8 @@ lasso_logout_init_request(LassoLogout *logout, char *remote_providerID, * * Return value: 0 on success; or a negative value otherwise. **/ -gint lasso_logout_process_request_msg(LassoLogout *logout, char *request_msg) +gint +lasso_logout_process_request_msg(LassoLogout *logout, char *request_msg) { LassoProfile *profile; LassoProvider *remote_provider; @@ -475,6 +486,10 @@ gint lasso_logout_process_request_msg(LassoLogout *logout, char *request_msg) profile = LASSO_PROFILE(logout); + IF_SAML2(profile) { + return lasso_saml20_logout_process_request_msg(logout, request_msg); + } + profile->request = lasso_lib_logout_request_new(); format = lasso_node_init_from_message(LASSO_NODE(profile->request), request_msg); if (format == LASSO_MESSAGE_FORMAT_UNKNOWN || format == LASSO_MESSAGE_FORMAT_ERROR) { @@ -748,6 +763,10 @@ lasso_logout_validate_request(LassoLogout *logout) profile = LASSO_PROFILE(logout); + IF_SAML2(profile) { + return lasso_saml20_logout_validate_request(logout); + } + /* verify logout request */ if (LASSO_IS_LIB_LOGOUT_REQUEST(profile->request) == FALSE) return LASSO_PROFILE_ERROR_MISSING_REQUEST; @@ -830,7 +849,8 @@ lasso_logout_validate_request(LassoLogout *logout) return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND); } - if (lasso_federation_verify_name_identifier(federation, nameIdentifier) == FALSE) { + if (lasso_federation_verify_name_identifier(federation, + LASSO_NODE(nameIdentifier)) == FALSE) { message(G_LOG_LEVEL_WARNING, "No name identifier for %s", profile->remote_providerID); lasso_profile_set_response_status(profile, @@ -898,7 +918,8 @@ static struct XmlSnippet schema_snippets[] = { static LassoNodeClass *parent_class = NULL; -static void check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile) +static void +check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile) { GList *supported_profiles; LassoSamlAssertion *assertion; diff --git a/lasso/id-ff/logoutprivate.h b/lasso/id-ff/logoutprivate.h new file mode 100644 index 00000000..85793234 --- /dev/null +++ b/lasso/id-ff/logoutprivate.h @@ -0,0 +1,43 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004, 2005 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: See AUTHORS file in top-level directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LASSO_LOGOUT_PRIVATE_H__ +#define __LASSO_LOGOUT_PRIVATE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +struct _LassoLogoutPrivate +{ + gboolean dispose_has_run; + gboolean all_soap; +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LASSO_LOGOUT_PRIVATE_H__ */ diff --git a/lasso/id-ff/name_registration.c b/lasso/id-ff/name_registration.c index 33a20d09..ebb733c2 100644 --- a/lasso/id-ff/name_registration.c +++ b/lasso/id-ff/name_registration.c @@ -575,8 +575,8 @@ lasso_name_registration_validate_request(LassoNameRegistration *name_registratio return LASSO_ERROR_UNDEFINED; } - if (lasso_federation_verify_name_identifier(federation, - request->OldProvidedNameIdentifier) == FALSE) { + if (lasso_federation_verify_name_identifier(federation, LASSO_NODE( + request->OldProvidedNameIdentifier)) == FALSE) { message(G_LOG_LEVEL_CRITICAL, "No name identifier"); return LASSO_ERROR_UNDEFINED; } diff --git a/lasso/id-ff/profile.c b/lasso/id-ff/profile.c index 864a68c0..7486d0df 100644 --- a/lasso/id-ff/profile.c +++ b/lasso/id-ff/profile.c @@ -39,16 +39,16 @@ /** * lasso_profile_get_nameIdentifier: - * @profile: a #LassoProifle + * @profile: a #LassoProfile * * Looks up appropriate federation in object and gets the service provider name - * identifier. + * identifier (which is actually a #LassoSamlNameIdentifier in ID-FF 1.2 and + * #LassoSaml2NameID in SAML 2.0). * - * Return value: the name identifier or NULL if none was found. The - * #LassoSamlNameIdentifier object is internally allocated and must not be - * freed by the caller. + * Return value: the name identifier or NULL if none was found. The #LassoNode + * object is internally allocated and must not be * freed by the caller. **/ -LassoSamlNameIdentifier* +LassoNode* lasso_profile_get_nameIdentifier(LassoProfile *profile) { LassoProvider *remote_provider; @@ -71,9 +71,9 @@ lasso_profile_get_nameIdentifier(LassoProfile *profile) return NULL; if (federation->remote_nameIdentifier) - return LASSO_SAML_NAME_IDENTIFIER(federation->remote_nameIdentifier); + return federation->remote_nameIdentifier; - return LASSO_SAML_NAME_IDENTIFIER(federation->local_nameIdentifier); + return federation->local_nameIdentifier; } /** diff --git a/lasso/id-ff/profile.h b/lasso/id-ff/profile.h index de281b5b..62e303c2 100644 --- a/lasso/id-ff/profile.h +++ b/lasso/id-ff/profile.h @@ -131,7 +131,7 @@ LASSO_EXPORT gboolean lasso_profile_is_session_dirty(LassoProfile *profile); LASSO_EXPORT gint lasso_profile_set_identity_from_dump(LassoProfile *profile, const gchar *dump); LASSO_EXPORT gint lasso_profile_set_session_from_dump(LassoProfile *profile, const gchar *dump); -LASSO_EXPORT LassoSamlNameIdentifier* lasso_profile_get_nameIdentifier(LassoProfile *profile); +LASSO_EXPORT LassoNode* lasso_profile_get_nameIdentifier(LassoProfile *profile); LASSO_EXPORT char* lasso_profile_get_artifact(LassoProfile *profile); LASSO_EXPORT char* lasso_profile_get_artifact_message(LassoProfile *profile); diff --git a/lasso/id-ff/provider.c b/lasso/id-ff/provider.c index 650e87ed..291d0542 100644 --- a/lasso/id-ff/provider.c +++ b/lasso/id-ff/provider.c @@ -234,6 +234,12 @@ lasso_provider_accept_http_method(LassoProvider *provider, LassoProvider *remote LassoProviderRole initiating_role; char *protocol_profile; + if (provider->private_data->conformance == LASSO_PROTOCOL_SAML_2_0) { + return lasso_saml20_provider_accept_http_method( + provider, remote_provider, protocol_type, + http_method, initiate_profile); + } + initiating_role = remote_provider->role; if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { provider->role = LASSO_PROVIDER_ROLE_IDP; diff --git a/lasso/id-ff/provider.h b/lasso/id-ff/provider.h index 9cad9124..c41e845b 100644 --- a/lasso/id-ff/provider.h +++ b/lasso/id-ff/provider.h @@ -87,7 +87,7 @@ typedef enum { * Liberty Metadata Type. **/ typedef enum { - LASSO_MD_PROTOCOL_TYPE_FEDERATION_TERMINATION = 0, + LASSO_MD_PROTOCOL_TYPE_FEDERATION_TERMINATION, LASSO_MD_PROTOCOL_TYPE_NAME_IDENTIFIER_MAPPING, LASSO_MD_PROTOCOL_TYPE_REGISTER_NAME_IDENTIFIER, LASSO_MD_PROTOCOL_TYPE_SINGLE_LOGOUT, diff --git a/lasso/id-ff/session.c b/lasso/id-ff/session.c index 2089956a..4432a621 100644 --- a/lasso/id-ff/session.c +++ b/lasso/id-ff/session.c @@ -333,8 +333,9 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode) while (n && n->type != XML_ELEMENT_NODE) n = n->next; if (n) { - LassoLibAssertion *assertion; - assertion = LASSO_LIB_ASSERTION(lasso_node_new_from_xmlNode(n)); + LassoNode *assertion; + + assertion = lasso_node_new_from_xmlNode(n); g_hash_table_insert(session->assertions, xmlGetProp(t, (xmlChar*)"RemoteProviderID"), assertion); diff --git a/lasso/saml-2.0/Makefile.am b/lasso/saml-2.0/Makefile.am index 49e4f418..ccd913ab 100644 --- a/lasso/saml-2.0/Makefile.am +++ b/lasso/saml-2.0/Makefile.am @@ -12,12 +12,14 @@ liblasso_saml_20_la_SOURCES = \ federation.c \ profile.c \ provider.c \ - login.c + login.c \ + logout.c lasso_private_h_sources = \ federationprivate.h \ profileprivate.h \ providerprivate.h \ - loginprivate.h + loginprivate.h \ + logoutprivate.h EXTRA_DIST = $(lasso_private_h_sources) diff --git a/lasso/saml-2.0/login.c b/lasso/saml-2.0/login.c index 6315343d..836c5dc6 100644 --- a/lasso/saml-2.0/login.c +++ b/lasso/saml-2.0/login.c @@ -133,9 +133,9 @@ lasso_saml20_login_build_authn_request_msg(LassoLogin *login, LassoProvider *rem /* POST and Artifact-GET|POST */ if (must_sign) { LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->private_key_file = - profile->server->private_key; + g_strdup(profile->server->private_key); LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->certificate_file = - profile->server->certificate; + g_strdup(profile->server->certificate); } if (login->http_method == LASSO_HTTP_METHOD_POST) { @@ -189,6 +189,7 @@ lasso_saml20_login_process_authn_request_msg(LassoLogin *login, const char *auth LASSO_PROVIDER(profile->server)->ProviderID)); response->IssueInstant = lasso_get_current_time(); response->InResponseTo = g_strdup(LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID); + /* XXX: adds signature */ return 0; } @@ -485,9 +486,9 @@ lasso_saml20_login_build_request_msg(LassoLogin *login) profile->msg_body = lasso_node_export_to_soap(profile->request); LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->private_key_file = - profile->server->private_key; + g_strdup(profile->server->private_key); LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->certificate_file = - profile->server->certificate; + g_strdup(profile->server->certificate); profile->msg_body = lasso_node_export_to_soap(profile->request); remote_provider = g_hash_table_lookup(profile->server->providers, diff --git a/lasso/saml-2.0/logout.c b/lasso/saml-2.0/logout.c new file mode 100644 index 00000000..efe96108 --- /dev/null +++ b/lasso/saml-2.0/logout.c @@ -0,0 +1,482 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004, 2005 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: See AUTHORS file in top-level directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <lasso/saml-2.0/providerprivate.h> +#include <lasso/saml-2.0/logoutprivate.h> +#include <lasso/saml-2.0/profileprivate.h> +#include <lasso/saml-2.0/federationprivate.h> + +#include <lasso/id-ff/providerprivate.h> +#include <lasso/id-ff/logout.h> +#include <lasso/id-ff/logoutprivate.h> +#include <lasso/id-ff/identityprivate.h> +#include <lasso/id-ff/sessionprivate.h> +#include <lasso/id-ff/profileprivate.h> + +#include <lasso/xml/saml-2.0/samlp2_logout_request.h> +#include <lasso/xml/saml-2.0/samlp2_logout_response.h> +#include <lasso/xml/saml-2.0/saml2_assertion.h> + +static void check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile); + +int +lasso_saml20_logout_init_request(LassoLogout *logout, LassoProvider *remote_provider, + LassoHttpMethod http_method) +{ + LassoProfile *profile = LASSO_PROFILE(logout); + LassoNode *assertion_n, *name_id_n; + LassoSaml2Assertion *assertion; + LassoSaml2NameID *name_id; + LassoFederation *federation; + LassoSession *session; + LassoSamlp2RequestAbstract *request; + + /* 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) { + message(G_LOG_LEVEL_CRITICAL, "Assertion not found"); + return LASSO_ERROR_UNDEFINED; + } + + assertion = LASSO_SAML2_ASSERTION(assertion_n); + + if (assertion->Subject == NULL) { + return LASSO_ERROR_UNDEFINED; + } + + name_id = assertion->Subject->NameID; + if (name_id->Format && strcmp(name_id->Format, + LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT) == 0) { + 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_id_n = lasso_profile_get_nameIdentifier(profile); + if (name_id_n == NULL) { + return critical_error(LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND); + } + if (federation->local_nameIdentifier) { + profile->nameIdentifier = g_object_ref(federation->local_nameIdentifier); + } else { + profile->nameIdentifier = g_object_ref(name_id_n); + } + + } else { + profile->nameIdentifier = g_object_ref(name_id); + } + + if (http_method == LASSO_HTTP_METHOD_ANY) { + http_method = lasso_provider_get_first_http_method( + LASSO_PROVIDER(profile->server), + remote_provider, + LASSO_MD_PROTOCOL_TYPE_SINGLE_LOGOUT); + } else { + if (lasso_provider_accept_http_method(LASSO_PROVIDER(profile->server), + remote_provider, + LASSO_MD_PROTOCOL_TYPE_SINGLE_LOGOUT, + http_method, + TRUE) == FALSE) { + if (http_method == LASSO_HTTP_METHOD_REDIRECT) { + /* it was probably used as last resort, and + * failed, since the remote provider doesn't + * support any logout. remove assertion + * unconditionnaly. */ + lasso_session_remove_assertion(profile->session, + profile->remote_providerID); + if (logout->initial_remote_providerID && logout->initial_request) { + g_free(profile->remote_providerID); + profile->remote_providerID = g_strdup( + logout->initial_remote_providerID); + /* XXX: create response + profile->response = lasso_lib_logout_response_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + LASSO_SAML_STATUS_CODE_SUCCESS, + LASSO_LIB_LOGOUT_REQUEST(logout->initial_request), + LASSO_SIGNATURE_TYPE_NONE, + 0); + */ + } + } + return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } + } + + /* free profile->request if it was already set */ + if (LASSO_IS_NODE(profile->request)) { + lasso_node_destroy(profile->request); + profile->request = NULL; + } + + profile->request = lasso_samlp2_logout_request_new(); + request = LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request); + request->ID = lasso_build_unique_id(32); + request->Version = g_strdup("2.0"); + request->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string( + LASSO_PROVIDER(profile->server)->ProviderID)); + request->IssueInstant = lasso_get_current_time(); + + LASSO_SAMLP2_LOGOUT_REQUEST(request)->NameID = g_object_ref(profile->nameIdentifier); + + /* XXX: SessionIndex */ + + logout->initial_http_request_method = http_method; + + return 0; +} + + +int +lasso_saml20_logout_build_request_msg(LassoLogout *logout, LassoProvider *remote_provider) +{ + LassoProfile *profile = LASSO_PROFILE(logout); + + LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->private_key_file = + g_strdup(profile->server->private_key); + LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->certificate_file = + g_strdup(profile->server->certificate); + + if (logout->initial_http_request_method == LASSO_HTTP_METHOD_SOAP) { + profile->msg_url = lasso_provider_get_metadata_one(remote_provider, + "SingleLogoutService SOAP"); + profile->msg_body = lasso_node_export_to_soap(profile->request); + return 0; + } + + if (logout->initial_http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + char *url, *query; + url = lasso_provider_get_metadata_one(remote_provider, + "SingleLogoutService HTTP-Redirect"); + if (url == NULL) { + return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL); + } + query = lasso_node_export_to_query(profile->request, + profile->server->signature_method, + profile->server->private_key); + if (query == NULL) { + g_free(url); + return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED); + } + profile->msg_url = g_strdup_printf("%s?%s", url, query); + return 0; + } + + /* XXX: artifact support */ + + return critical_error(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD); +} + +int +lasso_saml20_logout_process_request_msg(LassoLogout *logout, char *request_msg) +{ + LassoProfile *profile = LASSO_PROFILE(logout); + LassoProvider *remote_provider; + LassoMessageFormat format; + + profile->request = lasso_samlp2_logout_request_new(); + format = lasso_node_init_from_message(LASSO_NODE(profile->request), request_msg); + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN || format == LASSO_MESSAGE_FORMAT_ERROR) { + return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); + } + + + remote_provider = g_hash_table_lookup(profile->server->providers, + LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); + } + + /* verify signatures */ + profile->signature_status = lasso_provider_verify_signature( + remote_provider, request_msg, "ID", format); + + if (format == LASSO_MESSAGE_FORMAT_SOAP) + profile->http_request_method = LASSO_HTTP_METHOD_SOAP; + if (format == LASSO_MESSAGE_FORMAT_QUERY) + profile->http_request_method = LASSO_HTTP_METHOD_REDIRECT; + + profile->nameIdentifier = g_object_ref( + LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->NameID); + + return profile->signature_status; +} + +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; + LassoFederation *federation; + + if (LASSO_IS_SAMLP2_LOGOUT_REQUEST(profile->request) == FALSE) + return LASSO_PROFILE_ERROR_MISSING_REQUEST; + + profile->remote_providerID = g_strdup( + LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content); + + /* get the provider */ + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); + } + + if (profile->response) { + lasso_node_destroy(profile->response); + } + + profile->response = lasso_samlp2_logout_response_new(); + response = LASSO_SAMLP2_STATUS_RESPONSE(profile->response); + response->ID = lasso_build_unique_id(32); + response->Version = g_strdup("2.0"); + response->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string( + LASSO_PROVIDER(profile->server)->ProviderID)); + response->IssueInstant = lasso_get_current_time(); + response->InResponseTo = g_strdup(LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID); + + response->sign_method = LASSO_SIGNATURE_METHOD_RSA_SHA1; + if (profile->server->certificate) { + response->sign_type = LASSO_SIGNATURE_TYPE_WITHX509; + } else { + response->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE; + } + response->private_key_file = g_strdup(profile->server->private_key); + response->certificate_file = g_strdup(profile->server->certificate); + + /* verify signature status */ + if (profile->signature_status != 0) { + /* XXX: which SAML2 Status Code ? */ + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_INVALID_SIGNATURE); + return profile->signature_status; + } + + /* Get the name identifier */ + name_id = LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->NameID; + if (name_id == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Name identifier not found in logout request"); + /* XXX: which status code in SAML 2.0 ? */ + lasso_profile_set_response_status( + profile, LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND; + } + + if (profile->session == NULL) { + lasso_profile_set_response_status(profile, LASSO_SAML2_STATUS_CODE_REQUEST_DENIED); + return critical_error(LASSO_PROFILE_ERROR_SESSION_NOT_FOUND); + } + + /* verify authentication */ + assertion_n = lasso_session_get_assertion(profile->session, profile->remote_providerID); + if (assertion_n == NULL) { + message(G_LOG_LEVEL_WARNING, "%s has no assertion", profile->remote_providerID); + lasso_profile_set_response_status(profile, LASSO_SAML2_STATUS_CODE_REQUEST_DENIED); + return LASSO_ERROR_UNDEFINED; + } + + assertion = LASSO_SAML2_ASSERTION(assertion_n); + + /* If name identifier is federated, then verify federation */ + if (strcmp(name_id->Format, LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT) == 0) { + if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { + /* XXX: which SAML 2 status code ? */ + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND); + } + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (LASSO_IS_FEDERATION(federation) == FALSE) { + /* XXX: which status code in SAML 2 ? */ + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND); + } + + if (lasso_federation_verify_name_identifier(federation, + LASSO_NODE(name_id)) == FALSE) { + message(G_LOG_LEVEL_WARNING, "No name identifier for %s", + profile->remote_providerID); + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return LASSO_ERROR_UNDEFINED; + } + } + + /* if SOAP request method at IDP then verify all the remote service providers support + SOAP protocol profile. + If one remote authenticated principal service provider doesn't support SOAP + then return UnsupportedProfile to original service provider */ + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP && + profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { + + logout->private_data->all_soap = TRUE; + g_hash_table_foreach(profile->server->providers, + (GHFunc)check_soap_support, profile); + + if (logout->private_data->all_soap == FALSE) { + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_UNSUPPORTED_PROFILE); + return LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE; + } + } + + /* authentication is ok, federation is ok, propagation support is ok, remove assertion */ + lasso_session_remove_assertion(profile->session, profile->remote_providerID); + + /* if at IDP and nb sp logged > 1, then backup remote provider id, + * request and response + */ + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP && + g_hash_table_size(profile->session->assertions) >= 1) { + logout->initial_remote_providerID = profile->remote_providerID; + logout->initial_request = LASSO_NODE(profile->request); + logout->initial_response = LASSO_NODE(profile->response); + + profile->remote_providerID = NULL; + profile->request = NULL; + profile->response = NULL; + } + + return 0; + + +} + +static void +check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile) +{ + 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 (assertion_n == NULL) + return; /* not authenticated with this provider */ + assertion = LASSO_SAML2_ASSERTION(assertion_n); + + supported_profiles = lasso_provider_get_metadata_list(provider, + "SingleLogoutService SOAP"); + + if (supported_profiles) + return; /* provider support profile */ + + LASSO_LOGOUT(profile)->private_data->all_soap = FALSE; +} + +int +lasso_saml20_logout_build_response_msg(LassoLogout *logout) +{ + LassoProfile *profile = LASSO_PROFILE(logout); + LassoSamlp2StatusResponse *response; + LassoProvider *provider; + char *url, *query; + + if (profile->response == NULL) { + /* no response set here means request denied */ + profile->response = lasso_samlp2_logout_response_new(); + response = LASSO_SAMLP2_STATUS_RESPONSE(profile->response); + response->ID = lasso_build_unique_id(32); + response->Version = g_strdup("2.0"); + response->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string( + LASSO_PROVIDER(profile->server)->ProviderID)); + response->IssueInstant = lasso_get_current_time(); + response->InResponseTo = g_strdup( + LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID); + lasso_profile_set_response_status(profile, + LASSO_SAML2_STATUS_CODE_REQUEST_DENIED); + + response->sign_method = LASSO_SIGNATURE_METHOD_RSA_SHA1; + if (profile->server->certificate) { + response->sign_type = LASSO_SIGNATURE_TYPE_WITHX509; + } else { + response->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE; + } + response->private_key_file = g_strdup(profile->server->private_key); + response->certificate_file = g_strdup(profile->server->certificate); + } + + if (profile->remote_providerID == NULL || profile->response == NULL) { + /* no remote provider id set or no response set, this means + * this function got called before validate_request, probably + * because there were no active session */ + return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); + } + + /* build logout response message */ + if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { + profile->msg_url = NULL; + profile->msg_body = lasso_node_export_to_soap(profile->response); + return 0; + } + + if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + /* get the provider */ + provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (provider == NULL) { + return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND); + } + + url = lasso_provider_get_metadata_one(provider, + "SingleLogoutService HTTP-Redirect ResponseLocation"); + if (url == NULL) { + url = lasso_provider_get_metadata_one(provider, + "SingleLogoutService HTTP-Redirect"); + if (url == NULL) { + return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL); + } + } + query = lasso_node_export_to_query(LASSO_NODE(profile->response), + profile->server->signature_method, + profile->server->private_key); + if (query == NULL) { + g_free(url); + return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED); + } + profile->msg_url = g_strdup_printf("%s?%s", url, query); + profile->msg_body = NULL; + g_free(url); + g_free(query); + return 0; + } + + return LASSO_PROFILE_ERROR_MISSING_REQUEST; + + +} + diff --git a/lasso/saml-2.0/logoutprivate.h b/lasso/saml-2.0/logoutprivate.h new file mode 100644 index 00000000..e4cd0e2f --- /dev/null +++ b/lasso/saml-2.0/logoutprivate.h @@ -0,0 +1,49 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004, 2005 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: See AUTHORS file in top-level directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LASSO_SAML20_LOGOUT_PRIVATE_H__ +#define __LASSO_SAML20_LOGOUT_PRIVATE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <lasso/id-ff/logout.h> + +int lasso_saml20_logout_init_request(LassoLogout *logout, + LassoProvider *remote_provider, LassoHttpMethod http_method); + +int lasso_saml20_logout_build_request_msg(LassoLogout *logout, LassoProvider *remote_provider); + +int lasso_saml20_logout_process_request_msg(LassoLogout *logout, char *request_msg); + +int lasso_saml20_logout_validate_request(LassoLogout *logout); + +int lasso_saml20_logout_build_response_msg(LassoLogout *logout); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LASSO_SAML20_LOGOUT_PRIVATE_H__ */ diff --git a/lasso/saml-2.0/profile.c b/lasso/saml-2.0/profile.c index f6041e4b..24d88b86 100644 --- a/lasso/saml-2.0/profile.c +++ b/lasso/saml-2.0/profile.c @@ -250,8 +250,8 @@ lasso_saml20_profile_build_artifact_response(LassoProfile *profile) } else { response->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE; } - response->private_key_file = profile->server->private_key; - response->certificate_file = profile->server->certificate; + response->private_key_file = g_strdup(profile->server->private_key); + response->certificate_file = g_strdup(profile->server->certificate); profile->response = LASSO_NODE(response); lasso_saml20_profile_set_response_status(profile, LASSO_SAML2_STATUS_CODE_SUCCESS); diff --git a/lasso/saml-2.0/provider.c b/lasso/saml-2.0/provider.c index 3a473cf5..aa6afb3a 100644 --- a/lasso/saml-2.0/provider.c +++ b/lasso/saml-2.0/provider.c @@ -27,6 +27,17 @@ #include <lasso/saml-2.0/providerprivate.h> #include <lasso/id-ff/providerprivate.h> +const char *profile_names[] = { + "", /* No fedterm in SAML 2.0 */ + "NameIDMappingService", + "", /* No rni in SAML 2.0 */ + "SingleLogoutService", + "SingleSignOnService", + "ArtifactResolutionService", + "ManageNameIDService", + "AssertionIDRequestService", + NULL +}; static void load_descriptor(xmlNode *xmlnode, GHashTable *descriptor, LassoProvider *provider) @@ -35,8 +46,8 @@ load_descriptor(xmlNode *xmlnode, GHashTable *descriptor, LassoProvider *provide int i; xmlNode *t; GList *elements; - char *name, *binding; - xmlChar *value; + char *name, *binding, *response_name; + xmlChar *value, *response_value; t = xmlnode->children; while (t) { @@ -91,6 +102,15 @@ load_descriptor(xmlNode *xmlnode, GHashTable *descriptor, LassoProvider *provide name = g_strdup_printf("%s %s", t->name, binding_s); } xmlFree(binding); + + response_value = xmlGetProp(t, (xmlChar*)"ResponseLocation"); + if (response_value) { + response_name = g_strdup_printf("%s ResponseLocation", name); + elements = g_hash_table_lookup(descriptor, response_name); + elements = g_list_append(elements, g_strdup((char*)response_value)); + g_hash_table_insert(descriptor, response_name, elements); + xmlFree(response_value); + } } else { name = g_strdup((char*)t->name); value = xmlNodeGetContent(t); @@ -183,18 +203,7 @@ lasso_saml20_provider_get_first_http_method(LassoProvider *provider, LassoHttpMethod method_bindings[] = { LASSO_HTTP_METHOD_SOAP, LASSO_HTTP_METHOD_REDIRECT, LASSO_HTTP_METHOD_POST }; - const char *profiles[] = { - "", /* No fedterm in SAML 2.0 */ - "NameIDMappingService", - "", /* No rni in SAML 2.0 */ - "SingleLogoutService", - "SingleSignOnService", - "ArtifactResolutionService", - "ManageNameIDService", - "AssertionIDRequestService", - NULL - }; - + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) provider->role = LASSO_PROVIDER_ROLE_IDP; if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) @@ -204,7 +213,7 @@ lasso_saml20_provider_get_first_http_method(LassoProvider *provider, char *s; GList *l1, *l2; - s = g_strdup_printf("%s %s", profiles[protocol_type], possible_bindings[i]); + s = g_strdup_printf("%s %s", profile_names[protocol_type], possible_bindings[i]); l1 = lasso_provider_get_metadata_list(provider, s); l2 = lasso_provider_get_metadata_list(remote_provider, s); if (l1 && l2) { @@ -252,3 +261,45 @@ lasso_saml20_provider_get_assertion_consumer_service_url(LassoProvider *provider return NULL; } +gboolean +lasso_saml20_provider_accept_http_method(LassoProvider *provider, LassoProvider *remote_provider, + LassoMdProtocolType protocol_type, LassoHttpMethod http_method, + gboolean initiate_profile) +{ + LassoProviderRole initiating_role; + char *protocol_profile; + char *http_methods[] = { + NULL, + NULL, + NULL, + NULL, + "HTTP-Post", + "HTTP-Redirect", + "SOAP", + "HTTP-Artifact", + NULL + }; + + + initiating_role = remote_provider->role; + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { + provider->role = LASSO_PROVIDER_ROLE_IDP; + } + if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) { + provider->role = LASSO_PROVIDER_ROLE_SP; + } + if (initiate_profile) + initiating_role = provider->role; + + protocol_profile = g_strdup_printf("%s %s", profile_names[protocol_type], + http_methods[http_method+1]); + + if (lasso_provider_get_metadata_list(provider, protocol_profile) && + lasso_provider_get_metadata_list(remote_provider, protocol_profile)) { + return TRUE; + } + + return FALSE; +} + + diff --git a/lasso/saml-2.0/providerprivate.h b/lasso/saml-2.0/providerprivate.h index 7e47dbf4..9660dc7a 100644 --- a/lasso/saml-2.0/providerprivate.h +++ b/lasso/saml-2.0/providerprivate.h @@ -37,6 +37,10 @@ gboolean lasso_saml20_provider_load_metadata(LassoProvider *provider, xmlNode *r LassoHttpMethod lasso_saml20_provider_get_first_http_method(LassoProvider *provider, LassoProvider *remote_provider, LassoMdProtocolType protocol_type); +gboolean lasso_saml20_provider_accept_http_method(LassoProvider *provider, + LassoProvider *remote_provider, LassoMdProtocolType protocol_type, + LassoHttpMethod http_method, gboolean initiate_profile); + char* lasso_saml20_provider_build_artifact(LassoProvider *provider); gchar* lasso_saml20_provider_get_assertion_consumer_service_url(LassoProvider *provider, diff --git a/lasso/xml/private.h b/lasso/xml/private.h index 2f54e733..e614d954 100644 --- a/lasso/xml/private.h +++ b/lasso/xml/private.h @@ -162,6 +162,10 @@ static inline void message(GLogLevelFlags level, const char *format, ...) #define critical_error(rc) error_code(G_LOG_LEVEL_CRITICAL, rc) +#define IF_SAML2(profile) \ + if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \ + LASSO_PROTOCOL_SAML_2_0) + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/xml/saml-2.0/Makefile.am b/lasso/xml/saml-2.0/Makefile.am index b2761909..2b04dd6f 100644 --- a/lasso/xml/saml-2.0/Makefile.am +++ b/lasso/xml/saml-2.0/Makefile.am @@ -43,7 +43,9 @@ liblasso_xml_saml2_la_SOURCES = \ samlp2_idp_entry.c \ samlp2_idp_list.c \ samlp2_logout_request.c \ + samlp2_logout_response.c \ samlp2_manage_name_id_request.c \ + samlp2_manage_name_id_response.c \ samlp2_name_id_mapping_request.c \ samlp2_name_id_mapping_response.c \ samlp2_name_id_policy.c \ @@ -93,7 +95,9 @@ liblassoinclude_HEADERS = \ samlp2_idp_entry.h \ samlp2_idp_list.h \ samlp2_logout_request.h \ + samlp2_logout_response.h \ samlp2_manage_name_id_request.h \ + samlp2_manage_name_id_response.h \ samlp2_name_id_mapping_request.h \ samlp2_name_id_mapping_response.h \ samlp2_name_id_policy.h \ diff --git a/lasso/xml/saml-2.0/samlp2_artifact_resolve.c b/lasso/xml/saml-2.0/samlp2_artifact_resolve.c index 522ed196..28295a0e 100644 --- a/lasso/xml/saml-2.0/samlp2_artifact_resolve.c +++ b/lasso/xml/saml-2.0/samlp2_artifact_resolve.c @@ -52,32 +52,6 @@ static struct XmlSnippet schema_snippets[] = { static LassoNodeClass *parent_class = NULL; -static gchar* -build_query(LassoNode *node) -{ - char *ret, *deflated_message; - - deflated_message = lasso_node_build_deflated_query(node); - ret = g_strdup_printf("SAMLRequest=%s", deflated_message); - /* XXX: must support RelayState (which profiles?) */ - g_free(deflated_message); - return ret; -} - - -static gboolean -init_from_query(LassoNode *node, char **query_fields) -{ - gboolean rc; - char *relay_state = NULL; - rc = lasso_node_init_from_saml2_query_fields(node, query_fields, &relay_state); - if (rc && relay_state != NULL) { - /* XXX: support RelayState? */ - } - return rc; -} - - /*****************************************************************************/ /* instance and class init functions */ /*****************************************************************************/ @@ -94,8 +68,6 @@ class_init(LassoSamlp2ArtifactResolveClass *klass) LassoNodeClass *nclass = LASSO_NODE_CLASS(klass); parent_class = g_type_class_peek_parent(klass); - nclass->build_query = build_query; - nclass->init_from_query = init_from_query; nclass->node_data = g_new0(LassoNodeClassData, 1); lasso_node_class_set_nodename(nclass, "ArtifactResolve"); lasso_node_class_set_ns(nclass, LASSO_SAML2_PROTOCOL_HREF, LASSO_SAML2_PROTOCOL_PREFIX); diff --git a/lasso/xml/saml-2.0/samlp2_logout_response.c b/lasso/xml/saml-2.0/samlp2_logout_response.c new file mode 100644 index 00000000..12c775ec --- /dev/null +++ b/lasso/xml/saml-2.0/samlp2_logout_response.c @@ -0,0 +1,129 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004, 2005 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: See AUTHORS file in top-level directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "samlp2_logout_response.h" + +/* + * Schema fragment (saml-schema-protocol-2.0.xsd): + * + * <element name="LogoutResponse" type="samlp:StatusResponseType"/> + */ + +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ + + +static struct XmlSnippet schema_snippets[] = { + {NULL, 0, 0} +}; + +static LassoNodeClass *parent_class = NULL; + + +static gchar* +build_query(LassoNode *node) +{ + char *ret, *deflated_message; + + deflated_message = lasso_node_build_deflated_query(node); + ret = g_strdup_printf("SAMLResponse=%s", deflated_message); + /* XXX: must support RelayState (which profiles?) */ + g_free(deflated_message); + return ret; +} + + +static gboolean +init_from_query(LassoNode *node, char **query_fields) +{ + gboolean rc; + char *relay_state = NULL; + rc = lasso_node_init_from_saml2_query_fields(node, query_fields, &relay_state); + if (rc && relay_state != NULL) { + /* XXX: support RelayState? */ + } + return rc; +} + + +/*****************************************************************************/ +/* instance and class init functions */ +/*****************************************************************************/ + +static void +instance_init(LassoSamlp2LogoutResponse *node) +{ +} + +static void +class_init(LassoSamlp2LogoutResponseClass *klass) +{ + LassoNodeClass *nclass = LASSO_NODE_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + nclass->build_query = build_query; + nclass->init_from_query = init_from_query; + nclass->node_data = g_new0(LassoNodeClassData, 1); + lasso_node_class_set_nodename(nclass, "LogoutResponse"); + lasso_node_class_set_ns(nclass, LASSO_SAML2_PROTOCOL_HREF, LASSO_SAML2_PROTOCOL_PREFIX); + lasso_node_class_add_snippets(nclass, schema_snippets); +} + +GType +lasso_samlp2_logout_response_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoSamlp2LogoutResponseClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoSamlp2LogoutResponse), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_SAMLP2_STATUS_RESPONSE, + "LassoSamlp2LogoutResponse", &this_info, 0); + } + return this_type; +} + +/** + * lasso_samlp2_logout_response_new: + * + * Creates a new #LassoSamlp2LogoutResponse object. + * + * Return value: a newly created #LassoSamlp2LogoutResponse object + **/ +LassoNode* +lasso_samlp2_logout_response_new() +{ + return g_object_new(LASSO_TYPE_SAMLP2_LOGOUT_RESPONSE, NULL); +} diff --git a/lasso/xml/saml-2.0/samlp2_manage_name_id_response.c b/lasso/xml/saml-2.0/samlp2_manage_name_id_response.c new file mode 100644 index 00000000..59d2d0e3 --- /dev/null +++ b/lasso/xml/saml-2.0/samlp2_manage_name_id_response.c @@ -0,0 +1,129 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004, 2005 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: See AUTHORS file in top-level directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "samlp2_manage_name_id_response.h" + +/* + * Schema fragment (saml-schema-protocol-2.0.xsd): + * + * <element name="ManageNameIDResponse" type="samlp:StatusResponseType"/> + */ + +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ + + +static struct XmlSnippet schema_snippets[] = { + {NULL, 0, 0} +}; + +static LassoNodeClass *parent_class = NULL; + + +static gchar* +build_query(LassoNode *node) +{ + char *ret, *deflated_message; + + deflated_message = lasso_node_build_deflated_query(node); + ret = g_strdup_printf("SAMLResponse=%s", deflated_message); + /* XXX: must support RelayState (which profiles?) */ + g_free(deflated_message); + return ret; +} + + +static gboolean +init_from_query(LassoNode *node, char **query_fields) +{ + gboolean rc; + char *relay_state = NULL; + rc = lasso_node_init_from_saml2_query_fields(node, query_fields, &relay_state); + if (rc && relay_state != NULL) { + /* XXX: support RelayState? */ + } + return rc; +} + + +/*****************************************************************************/ +/* instance and class init functions */ +/*****************************************************************************/ + +static void +instance_init(LassoSamlp2ManageNameIDResponse *node) +{ +} + +static void +class_init(LassoSamlp2ManageNameIDResponseClass *klass) +{ + LassoNodeClass *nclass = LASSO_NODE_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + nclass->build_query = build_query; + nclass->init_from_query = init_from_query; + nclass->node_data = g_new0(LassoNodeClassData, 1); + lasso_node_class_set_nodename(nclass, "ManageNameIDResponse"); + lasso_node_class_set_ns(nclass, LASSO_SAML2_PROTOCOL_HREF, LASSO_SAML2_PROTOCOL_PREFIX); + lasso_node_class_add_snippets(nclass, schema_snippets); +} + +GType +lasso_samlp2_manage_name_id_response_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoSamlp2ManageNameIDResponseClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoSamlp2ManageNameIDResponse), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_SAMLP2_STATUS_RESPONSE, + "LassoSamlp2ManageNameIDResponse", &this_info, 0); + } + return this_type; +} + +/** + * lasso_samlp2_manage_name_id_response_new: + * + * Creates a new #LassoSamlp2ManageNameIDResponse object. + * + * Return value: a newly created #LassoSamlp2ManageNameIDResponse object + **/ +LassoNode* +lasso_samlp2_manage_name_id_response_new() +{ + return g_object_new(LASSO_TYPE_SAMLP2_MANAGE_NAME_ID_RESPONSE, NULL); +} diff --git a/lasso/xml/saml-2.0/samlp2_name_id_mapping_response.c b/lasso/xml/saml-2.0/samlp2_name_id_mapping_response.c index bc497df6..8ed1966a 100644 --- a/lasso/xml/saml-2.0/samlp2_name_id_mapping_response.c +++ b/lasso/xml/saml-2.0/samlp2_name_id_mapping_response.c @@ -56,6 +56,32 @@ static struct XmlSnippet schema_snippets[] = { static LassoNodeClass *parent_class = NULL; +static gchar* +build_query(LassoNode *node) +{ + char *ret, *deflated_message; + + deflated_message = lasso_node_build_deflated_query(node); + ret = g_strdup_printf("SAMLResponse=%s", deflated_message); + /* XXX: must support RelayState (which profiles?) */ + g_free(deflated_message); + return ret; +} + + +static gboolean +init_from_query(LassoNode *node, char **query_fields) +{ + gboolean rc; + char *relay_state = NULL; + rc = lasso_node_init_from_saml2_query_fields(node, query_fields, &relay_state); + if (rc && relay_state != NULL) { + /* XXX: support RelayState? */ + } + return rc; +} + + /*****************************************************************************/ /* instance and class init functions */ /*****************************************************************************/ @@ -73,6 +99,8 @@ class_init(LassoSamlp2NameIDMappingResponseClass *klass) LassoNodeClass *nclass = LASSO_NODE_CLASS(klass); parent_class = g_type_class_peek_parent(klass); + nclass->build_query = build_query; + nclass->init_from_query = init_from_query; nclass->node_data = g_new0(LassoNodeClassData, 1); lasso_node_class_set_nodename(nclass, "NameIDMappingResponse"); lasso_node_class_set_ns(nclass, LASSO_SAML2_PROTOCOL_HREF, LASSO_SAML2_PROTOCOL_PREFIX); diff --git a/lasso/xml/saml-2.0/samlp2_request_abstract.c b/lasso/xml/saml-2.0/samlp2_request_abstract.c index 6957e736..cfa7a1f7 100644 --- a/lasso/xml/saml-2.0/samlp2_request_abstract.c +++ b/lasso/xml/saml-2.0/samlp2_request_abstract.c @@ -68,6 +68,17 @@ static struct XmlSnippet schema_snippets[] = { G_STRUCT_OFFSET(LassoSamlp2RequestAbstract, Consent) }, { "Signature", SNIPPET_SIGNATURE, G_STRUCT_OFFSET(LassoSamlp2RequestAbstract, ID) }, + + /* hidden fields; used in lasso dumps */ + { "SignType", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2RequestAbstract, sign_type) }, + { "SignMethod", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2RequestAbstract, sign_method) }, + { "PrivateKeyFile", SNIPPET_CONTENT | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2RequestAbstract, private_key_file) }, + { "CertificateFile", SNIPPET_CONTENT | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2RequestAbstract, certificate_file) }, + {NULL, 0, 0} }; diff --git a/lasso/xml/saml-2.0/samlp2_response.c b/lasso/xml/saml-2.0/samlp2_response.c index b2bf27f8..e32616f7 100644 --- a/lasso/xml/saml-2.0/samlp2_response.c +++ b/lasso/xml/saml-2.0/samlp2_response.c @@ -55,6 +55,32 @@ static struct XmlSnippet schema_snippets[] = { static LassoNodeClass *parent_class = NULL; +static gchar* +build_query(LassoNode *node) +{ + char *ret, *deflated_message; + + deflated_message = lasso_node_build_deflated_query(node); + ret = g_strdup_printf("SAMLResponse=%s", deflated_message); + /* XXX: must support RelayState (which profiles?) */ + g_free(deflated_message); + return ret; +} + + +static gboolean +init_from_query(LassoNode *node, char **query_fields) +{ + gboolean rc; + char *relay_state = NULL; + rc = lasso_node_init_from_saml2_query_fields(node, query_fields, &relay_state); + if (rc && relay_state != NULL) { + /* XXX: support RelayState? */ + } + return rc; +} + + /*****************************************************************************/ /* instance and class init functions */ /*****************************************************************************/ @@ -72,6 +98,8 @@ class_init(LassoSamlp2ResponseClass *klass) LassoNodeClass *nclass = LASSO_NODE_CLASS(klass); parent_class = g_type_class_peek_parent(klass); + nclass->build_query = build_query; + nclass->init_from_query = init_from_query; nclass->node_data = g_new0(LassoNodeClassData, 1); lasso_node_class_set_nodename(nclass, "Response"); lasso_node_class_set_ns(nclass, LASSO_SAML2_PROTOCOL_HREF, LASSO_SAML2_PROTOCOL_PREFIX); diff --git a/lasso/xml/saml-2.0/samlp2_status_response.c b/lasso/xml/saml-2.0/samlp2_status_response.c index 2fa79fb3..5cf70a1d 100644 --- a/lasso/xml/saml-2.0/samlp2_status_response.c +++ b/lasso/xml/saml-2.0/samlp2_status_response.c @@ -74,12 +74,49 @@ static struct XmlSnippet schema_snippets[] = { G_STRUCT_OFFSET(LassoSamlp2StatusResponse, Consent) }, { "Signature", SNIPPET_SIGNATURE, G_STRUCT_OFFSET(LassoSamlp2StatusResponse, ID) }, + + /* hidden fields; used in lasso dumps */ + { "SignType", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2StatusResponse, sign_type) }, + { "SignMethod", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2StatusResponse, sign_method) }, + { "PrivateKeyFile", SNIPPET_CONTENT | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2StatusResponse, private_key_file) }, + { "CertificateFile", SNIPPET_CONTENT | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlp2StatusResponse, certificate_file) }, + {NULL, 0, 0} }; static LassoNodeClass *parent_class = NULL; +static gchar* +build_query(LassoNode *node) +{ + char *ret, *deflated_message; + + deflated_message = lasso_node_build_deflated_query(node); + ret = g_strdup_printf("SAMLResponse=%s", deflated_message); + /* XXX: must support RelayState (which profiles?) */ + g_free(deflated_message); + return ret; +} + + +static gboolean +init_from_query(LassoNode *node, char **query_fields) +{ + gboolean rc; + char *relay_state = NULL; + rc = lasso_node_init_from_saml2_query_fields(node, query_fields, &relay_state); + if (rc && relay_state != NULL) { + /* XXX: support RelayState? */ + } + return rc; +} + + static xmlNode* get_xmlNode(LassoNode *node, gboolean lasso_dump) @@ -125,6 +162,8 @@ class_init(LassoSamlp2StatusResponseClass *klass) LassoNodeClass *nclass = LASSO_NODE_CLASS(klass); parent_class = g_type_class_peek_parent(klass); + nclass->build_query = build_query; + nclass->init_from_query = init_from_query; nclass->get_xmlNode = get_xmlNode; nclass->node_data = g_new0(LassoNodeClassData, 1); lasso_node_class_set_nodename(nclass, "StatusResponse"); diff --git a/lasso/xml/xml.c b/lasso/xml/xml.c index ff07cc2f..6ae2a7e5 100644 --- a/lasso/xml/xml.c +++ b/lasso/xml/xml.c @@ -1121,6 +1121,7 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, case SNIPPET_LASSO_DUMP: case SNIPPET_OPTIONAL: case SNIPPET_OPTIONAL_NEG: + case SNIPPET_ANY: g_assert_not_reached(); } if (snippet->type & SNIPPET_INTEGER) |