diff options
author | Frederic Peters <fpeters@entrouvert.com> | 2004-10-27 09:49:13 +0000 |
---|---|---|
committer | Frederic Peters <fpeters@entrouvert.com> | 2004-10-27 09:49:13 +0000 |
commit | f13772d62deb599c1c475f5b842ac76bdefc7e2f (patch) | |
tree | 3b217e851e54b477ecbf4df2cb6ded611574b1aa /lasso/id-ff | |
parent | c411dbc31f0938f513c4fb4ccc3b12a7b4ce6617 (diff) | |
download | lasso-f13772d62deb599c1c475f5b842ac76bdefc7e2f.tar.gz lasso-f13772d62deb599c1c475f5b842ac76bdefc7e2f.tar.xz lasso-f13772d62deb599c1c475f5b842ac76bdefc7e2f.zip |
Done with the move to structures and the removal of protocols/ (lasso branched
on October 2nd; occasional merges since then).
- Compatible with current souk test suites.
- Missing memory management for everything in xml/
- Missing xmlsec support for SOAP messages.
Diffstat (limited to 'lasso/id-ff')
-rw-r--r-- | lasso/id-ff/Makefile.am | 4 | ||||
-rw-r--r-- | lasso/id-ff/defederation.c | 907 | ||||
-rw-r--r-- | lasso/id-ff/defederation.h | 19 | ||||
-rw-r--r-- | lasso/id-ff/federation.c | 306 | ||||
-rw-r--r-- | lasso/id-ff/federation.h | 89 | ||||
-rw-r--r-- | lasso/id-ff/identity.c | 539 | ||||
-rw-r--r-- | lasso/id-ff/identity.h | 52 | ||||
-rw-r--r-- | lasso/id-ff/lecp.c | 81 | ||||
-rw-r--r-- | lasso/id-ff/lecp.h | 20 | ||||
-rw-r--r-- | lasso/id-ff/login.c | 2482 | ||||
-rw-r--r-- | lasso/id-ff/login.h | 64 | ||||
-rw-r--r-- | lasso/id-ff/logout.c | 1607 | ||||
-rw-r--r-- | lasso/id-ff/logout.h | 37 | ||||
-rw-r--r-- | lasso/id-ff/name_identifier_mapping.c | 875 | ||||
-rw-r--r-- | lasso/id-ff/name_identifier_mapping.h | 24 | ||||
-rw-r--r-- | lasso/id-ff/name_registration.c | 1325 | ||||
-rw-r--r-- | lasso/id-ff/name_registration.h | 31 | ||||
-rw-r--r-- | lasso/id-ff/profile.c | 745 | ||||
-rw-r--r-- | lasso/id-ff/profile.h | 90 | ||||
-rw-r--r-- | lasso/id-ff/provider.c | 517 | ||||
-rw-r--r-- | lasso/id-ff/provider.h | 111 | ||||
-rw-r--r-- | lasso/id-ff/server.c | 704 | ||||
-rw-r--r-- | lasso/id-ff/server.h | 49 | ||||
-rw-r--r-- | lasso/id-ff/session.c | 559 | ||||
-rw-r--r-- | lasso/id-ff/session.h | 45 |
25 files changed, 5276 insertions, 6006 deletions
diff --git a/lasso/id-ff/Makefile.am b/lasso/id-ff/Makefile.am index c9c7e99a..79a35ab2 100644 --- a/lasso/id-ff/Makefile.am +++ b/lasso/id-ff/Makefile.am @@ -11,6 +11,7 @@ noinst_LTLIBRARIES = liblasso-environs.la liblasso_environs_la_SOURCES = \ defederation.c \ + federation.c \ identity.c \ lecp.c \ login.c \ @@ -18,11 +19,13 @@ liblasso_environs_la_SOURCES = \ name_identifier_mapping.c \ name_registration.c \ profile.c \ + provider.c \ server.c \ session.c liblassoinclude_HEADERS = \ defederation.h \ + federation.h \ identity.h \ lecp.h \ login.h \ @@ -30,5 +33,6 @@ liblassoinclude_HEADERS = \ name_identifier_mapping.h \ name_registration.h \ profile.h \ + provider.h \ server.h \ session.h diff --git a/lasso/id-ff/defederation.c b/lasso/id-ff/defederation.c index 4b61771e..2f42778e 100644 --- a/lasso/id-ff/defederation.c +++ b/lasso/id-ff/defederation.c @@ -30,11 +30,9 @@ #include <lasso/environs/defederation.h> #include <lasso/xml/errors.h> -static GObjectClass *parent_class = NULL; - struct _LassoDefederationPrivate { - gboolean dispose_has_run; + gboolean dispose_has_run; }; /*****************************************************************************/ @@ -47,116 +45,88 @@ struct _LassoDefederationPrivate * * This method builds the federation termination notification message. * - * It gets the federation termination notification protocol profile and : - * if it is a SOAP method, then it builds the federation termination notification SOAP message, - * optionaly signs the notification node, set the msg_body attribute, gets the SoapEndpoint - * url and set the msg_url attribute of the federation termination object. + * It gets the federation termination notification protocol profile and: + * + * - if it is a SOAP method, then it builds the federation termination + * notification SOAP message, optionaly signs the notification node, set the + * msg_body attribute, gets the SoapEndpoint url and set the msg_url + * attribute of the federation termination object. * - * if it is a HTTP-Redirect method, then it builds the federation termination notification QUERY message - * ( optionaly signs the notification message ), builds the federation termination notification url - * with federation termination service url, set the msg_url attribute of the federation termination object, - * set the msg_body to NULL + * - if it is a HTTP-Redirect method, then it builds the federation termination + * notification QUERY message (optionaly signs the notification message), + * builds the federation termination notification url with federation + * termination service url, set the msg_url attribute of the federation + * termination object, set the msg_body to NULL * * Return value: O of OK else < 0 **/ gint lasso_defederation_build_notification_msg(LassoDefederation *defederation) { - LassoProfile *profile; - LassoProvider *provider; - xmlChar *protocolProfile = NULL; - gchar *url = NULL, *query = NULL; - lassoProviderType remote_provider_type; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), -1); - - profile = LASSO_PROFILE(defederation); - - /* set the remote provider type and get the remote provider object */ - if (profile->provider_type == lassoProviderTypeSp) { - remote_provider_type = lassoProviderTypeIdp; - } - else if (profile->provider_type == lassoProviderTypeIdp) { - remote_provider_type = lassoProviderTypeSp; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - provider = lasso_server_get_provider_ref(profile->server, - profile->remote_providerID, - NULL); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Provider %s not found\n", profile->remote_providerID); - ret = -1; - goto done; - } - - /* get the prototocol profile of the logout request */ - protocolProfile = lasso_provider_get_singleLogoutProtocolProfile(provider, - remote_provider_type, - NULL); - if (protocolProfile == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Single logout protocol profile not found\n"); - ret = -1; - goto done; - } - - /* build the federation termination notification message (SOAP or HTTP-Redirect) */ - if (xmlStrEqual(protocolProfile, lassoLibProtocolProfileSloSpSoap) || \ - xmlStrEqual(protocolProfile, lassoLibProtocolProfileSloIdpSoap)) { - /* optionaly sign the notification node */ - if ( (profile->server->private_key != NULL) && (profile->server->signature_method && profile->server->certificate) ) { - lasso_samlp_request_abstract_set_signature(LASSO_SAMLP_REQUEST_ABSTRACT(profile->request), - profile->server->signature_method, - profile->server->private_key, - profile->server->certificate); - } - /* build the message */ - profile->msg_url = lasso_provider_get_soapEndpoint(provider, - remote_provider_type, - NULL); - profile->msg_body = lasso_node_export_to_soap(profile->request); - } - else if (xmlStrEqual(protocolProfile,lassoLibProtocolProfileSloSpHttp) || \ - xmlStrEqual(protocolProfile,lassoLibProtocolProfileSloIdpHttp)) { - /* build and optionaly sign the query message and build the federation termination notification url */ - url = lasso_provider_get_federationTerminationServiceURL(provider, - remote_provider_type, - NULL); - query = lasso_node_export_to_query(profile->request, - profile->server->signature_method, - profile->server->private_key); - - if ( (url == NULL) || (query == NULL) ) { - message(G_LOG_LEVEL_CRITICAL, "%d, Url %s or QUERY %s is NULL\n", remote_provider_type, url, query); - ret = -1; - goto done; - } - - profile->msg_url = g_strdup_printf("%s?%s", url, query); - profile->msg_body = NULL; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid federation termination notification protocol profile\n"); - ret = -1; - goto done; - } - - done: - if (protocolProfile != NULL) { - xmlFree(protocolProfile); - } - if (url != NULL) { - xmlFree(url); - } - if (query != NULL) { - xmlFree(query); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + gchar *url = NULL, *query = NULL; + + g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(defederation); + + /* get the remote provider object */ + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Provider %s not found", profile->remote_providerID); + return -1; + } + + /* get the protocol profile type */ + + /* build the federation termination notification message (SOAP or HTTP-Redirect) */ + if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { +#if 0 /* XXX: signatures are done differently */ + /* sign the request message */ + lasso_samlp_request_abstract_sign_signature_tmpl( + LASSO_SAMLP_REQUEST_ABSTRACT(profile->request), + profile->server->private_key, + profile->server->certificate); +#endif + + /* build the logout request message */ + profile->msg_url = lasso_provider_get_metadata_one(remote_provider, "SoapEndpoint"); + profile->msg_body = lasso_node_export_to_soap(profile->request); + } + if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + /* build and optionaly sign the query message and build the + * federation termination notification url */ + url = lasso_provider_get_metadata_one(remote_provider, + "FederationTerminationServiceURL"); + if (url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Unknown profile service URL"); + return -1; + } + query = lasso_node_export_to_query(profile->request, + profile->server->signature_method, + profile->server->private_key); + + if (query == NULL) { + g_free(url); + message(G_LOG_LEVEL_CRITICAL, "Error while building request QUERY url"); + return -1; + } + + profile->msg_url = g_strdup_printf("%s?%s", url, query); + g_free(url); + g_free(query); + profile->msg_body = NULL; + } + + if (profile->msg_url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Invalid http method\n"); + return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; + } + + return 0; } /** @@ -169,14 +139,14 @@ lasso_defederation_build_notification_msg(LassoDefederation *defederation) void lasso_defederation_destroy(LassoDefederation *defederation) { - g_object_unref(G_OBJECT(defederation)); + g_object_unref(G_OBJECT(defederation)); } /** * lasso_defederation_init_notification: * @defederation: the federation termination object - * @remote_providerID: the provider id of the federation termination notified provider. - * If it is set to NULL, then gets the default first remote provider id. + * @remote_providerID: the provider id of the federation termination notified + * provider. * * It sets a new federation termination notification to the remote provider id * with the provider id of the requester (from the server object ) @@ -185,250 +155,180 @@ lasso_defederation_destroy(LassoDefederation *defederation) * Return value: 0 if OK else < 0 **/ gint -lasso_defederation_init_notification(LassoDefederation *defederation, - gchar *remote_providerID, - lassoHttpMethod notification_method) +lasso_defederation_init_notification(LassoDefederation *defederation, gchar *remote_providerID, + lassoHttpMethod http_method) { - LassoProfile *profile; - LassoProvider *provider; - LassoFederation *federation = NULL; - LassoNode *nameIdentifier = NULL; - xmlChar *content = NULL, *nameQualifier = NULL, *format = NULL; - xmlChar *federationTerminationProtocolProfile; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), -1); - - profile = LASSO_PROFILE(defederation); - - /* set the remote provider id */ - if (remote_providerID == NULL) { - profile->remote_providerID = lasso_identity_get_first_providerID(profile->identity); - } - else { - profile->remote_providerID = g_strdup(remote_providerID); - } - if (profile->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "No remote provider id to build the federation termination notification\n"); - ret = -1; - goto done; - } - - /* get federation */ - federation = lasso_identity_get_federation(profile->identity, profile->remote_providerID); - if (federation == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Federation not found for %s\n", profile->remote_providerID); - ret = -1; - goto done; - } - - /* get the name identifier (!!! depend on the provider type : SP or IDP !!!) */ - switch (profile->provider_type) { - case lassoProviderTypeSp: - nameIdentifier = LASSO_NODE(lasso_federation_get_local_nameIdentifier(federation)); - if (!nameIdentifier) { - nameIdentifier = LASSO_NODE(lasso_federation_get_remote_nameIdentifier(federation)); - } - break; - case lassoProviderTypeIdp: - nameIdentifier = LASSO_NODE(lasso_federation_get_remote_nameIdentifier(federation)); - if (!nameIdentifier) { - nameIdentifier = LASSO_NODE(lasso_federation_get_local_nameIdentifier(federation)); - } - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - } - - if (!nameIdentifier) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier not found for %s\n", profile->remote_providerID); - ret = -1; - goto done; - } - - /* Get the content, name qualifier and the format of the name identifier */ - /* WARNING : Don't free content, it will be backed up in nameIdentifier attribute of LassoDefederation object */ - content = lasso_node_get_content(nameIdentifier, NULL); - nameQualifier = lasso_node_get_attr_value(nameIdentifier, "NameQualifier", NULL); - format = lasso_node_get_attr_value(nameIdentifier, "Format", NULL); - if (content == NULL) { - message(G_LOG_LEVEL_CRITICAL, "NameIdentifier has no content\n"); - ret = -1; - goto done; - } - - /* get the protocol profile and set a new federation termination notification object */ - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, NULL); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Provider %s not found\n", profile->remote_providerID); - ret = -1; - goto done; - } - - if (profile->provider_type == lassoProviderTypeIdp) { - federationTerminationProtocolProfile = lasso_provider_get_federationTerminationNotificationProtocolProfile(provider, - lassoProviderTypeSp, - NULL); - } - else if (profile->provider_type == lassoProviderTypeSp) { - federationTerminationProtocolProfile = lasso_provider_get_federationTerminationNotificationProtocolProfile(provider, - lassoProviderTypeIdp, - NULL); - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - - if (federationTerminationProtocolProfile == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Federation termination notification protocol profile not found\n"); - ret = -1; - goto done; - } - - /* build the request */ - if (xmlStrEqual(federationTerminationProtocolProfile, lassoLibProtocolProfileFedTermSpSoap) || \ - xmlStrEqual(federationTerminationProtocolProfile, lassoLibProtocolProfileFedTermIdpSoap)) { - profile->request = lasso_federation_termination_notification_new(profile->server->providerID, - content, - nameQualifier, - format, - lassoSignatureTypeWithX509, - lassoSignatureMethodRsaSha1); - } - else if (xmlStrEqual(federationTerminationProtocolProfile, lassoLibProtocolProfileFedTermSpHttp) || \ - xmlStrEqual(federationTerminationProtocolProfile, lassoLibProtocolProfileFedTermIdpHttp)) { - profile->request = lasso_federation_termination_notification_new(profile->server->providerID, - content, - nameQualifier, - format, - lassoSignatureTypeNone, - 0); - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid federation termination notification protocol profile\n"); - ret = -1; - goto done; - } - if (profile->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Error while creating the federation termination notification\n"); - ret = -1; - goto done; - } - - /* Set the nameIdentifier attribute from content local variable */ - profile->nameIdentifier = content; - content = NULL; - - /* remove federation with remote provider id */ - if (profile->identity == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Identity not found\n"); - ret = -1; - goto done; - } - lasso_identity_remove_federation(profile->identity, profile->remote_providerID); - - /* remove assertion from session */ - if (profile->session != NULL) { - lasso_session_remove_assertion(profile->session, profile->remote_providerID); - } - - done: - if (nameIdentifier != NULL) { - lasso_node_destroy(nameIdentifier); - } - if (federation!=NULL) { - lasso_federation_destroy(federation); - } - if (content != NULL) { - xmlFree(content); - } - if (nameQualifier != NULL) { - xmlFree(nameQualifier); - } - if (format != NULL) { - xmlFree(format); - } - - return ret; + LassoProfile*profile; + LassoProvider *remote_provider; + LassoFederation *federation; + LassoSamlNameIdentifier *nameIdentifier = NULL; + + g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(defederation); + + /* set the remote provider id */ + profile->remote_providerID = g_strdup(remote_providerID); + + if (profile->remote_providerID == NULL) { + message(G_LOG_LEVEL_CRITICAL, + "No remote provider id to send the defederation request"); + return -1; + } + + + remote_provider = g_hash_table_lookup( + profile->server->providers, profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Remote provider not found"); + return -1; + } + + /* get federation */ + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (federation == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found for %s", + profile->remote_providerID); + return -1; + } + + /* get the nameIdentifier to send the federation termination notification */ + nameIdentifier = lasso_profile_get_nameIdentifier(profile); + if (nameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Name identifier not found for %s", + profile->remote_providerID); + return -1; + } + + /* get / verify http method */ + 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_FEDERATION_TERMINATION); + } else { + if (lasso_provider_accept_http_method(LASSO_PROVIDER(profile->server), + remote_provider, + LASSO_MD_PROTOCOL_TYPE_FEDERATION_TERMINATION, + http_method, + TRUE) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "This provider can't initiate this profile"); + return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } + } + + /* build the request */ + if (http_method == LASSO_HTTP_METHOD_SOAP) { + profile->request = lasso_lib_federation_termination_notification_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + nameIdentifier, + LASSO_SIGNATURE_TYPE_WITHX509, + LASSO_SIGNATURE_METHOD_RSA_SHA1); + } + if (http_method == LASSO_HTTP_METHOD_REDIRECT) { + profile->request = lasso_lib_federation_termination_notification_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + nameIdentifier, + LASSO_SIGNATURE_TYPE_NONE, + 0); + } + if (LASSO_IS_LIB_FEDERATION_TERMINATION_NOTIFICATION(profile->request) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Error while building the request"); + return -1; + } + + /* Set the nameIdentifier attribute from content local variable */ + profile->nameIdentifier = g_strdup(nameIdentifier->content); + + /* remove federation with remote provider id */ + if (profile->identity == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + return -1; + } + lasso_identity_remove_federation(profile->identity, profile->remote_providerID); + + /* remove assertion from session */ + if (profile->session) + lasso_session_remove_assertion(profile->session, profile->remote_providerID); + + /* Save notification method */ + profile->http_request_method = http_method; + + return 0; } /** * lasso_defederation_process_notification_msg: * @defederation: the federation termination object * @notification_msg: the federation termination notification message - * @notification_method: the federation termination notification method * * Process the federation termination notification. - * If it is a SOAP notification method then it builds the federation termination object - * from the SOAP message and optionaly verify the signature. + * + * - if it is a SOAP notification method then it builds the federation + * termination object from the SOAP message and optionaly verify the + * signature. * - * if it is a HTTP-Redirect notification method then it builds the federation termination notication - * object from the QUERY message and optionaly verify the signature. + * - if it is a HTTP-Redirect notification method then it builds the + * federation termination notication object from the QUERY message and + * optionaly verify the signature. * - * Set the msg_nameIdentifier attribute with the NameIdentifier content of the notification object and - * optionaly set the msg_relayState attribute with the RelayState content of the notifcation object + * Set the msg_nameIdentifier attribute with the NameIdentifier content of the + * notification object and optionaly set the msg_relayState attribute with the + * RelayState content of the notification object * * Return value: 0 on success or a negative value otherwise. **/ gint -lasso_defederation_process_notification_msg(LassoDefederation *defederation, - gchar *notification_msg, - lassoHttpMethod notification_method) +lasso_defederation_process_notification_msg(LassoDefederation *defederation, char *request_msg) { - LassoProfile *profile; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), -1); - g_return_val_if_fail(notification_msg!=NULL, -1); - - profile = LASSO_PROFILE(defederation); - - switch (notification_method) { - case lassoHttpMethodSoap: - debug("Build a federation termination notification from soap msg\n"); - profile->request = lasso_federation_termination_notification_new_from_export(notification_msg, lassoNodeExportTypeSoap); - if (LASSO_IS_FEDERATION_TERMINATION_NOTIFICATION(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG)); - ret = LASSO_PROFILE_ERROR_INVALID_SOAP_MSG; - goto done; - } - break; - case lassoHttpMethodRedirect: - debug("Build a federation termination notification from query msg\n"); - profile->request = lasso_federation_termination_notification_new_from_export(notification_msg, lassoNodeExportTypeQuery); - if (LASSO_IS_FEDERATION_TERMINATION_NOTIFICATION(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_QUERY)); - ret = LASSO_PROFILE_ERROR_INVALID_QUERY; - goto done; - } - break; - default: - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - ret = LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - goto done; - } - - /* set the http request method */ - profile->http_request_method = notification_method; - - /* get the NameIdentifier */ - profile->nameIdentifier = lasso_node_get_child_content(profile->request, - "NameIdentifier", NULL, NULL); - if (profile->nameIdentifier==NULL) { - message(G_LOG_LEVEL_CRITICAL, "NameIdentifier not found\n"); - ret = -1; - goto done; - } - - /* get the RelayState */ - profile->msg_relayState = lasso_node_get_child_content(profile->request, - "RelayState", NULL, NULL); - - done: - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoMessageFormat format; + + g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(request_msg != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(defederation); + + profile->request = lasso_lib_federation_termination_notification_new(); + format = lasso_node_init_from_message(profile->request, request_msg); + + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_INVALID_MSG; + } + + profile->remote_providerID = g_strdup(LASSO_LIB_FEDERATION_TERMINATION_NOTIFICATION( + profile->request)->ProviderID); + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Unknown provider"); + return -1; + } + + profile->signature_status = lasso_provider_verify_signature( + remote_provider, request_msg, "RequestID"); + + /* set the http request method */ + 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_strdup(LASSO_LIB_FEDERATION_TERMINATION_NOTIFICATION( + profile->request)->NameIdentifier->content); + + /* get the RelayState */ + + /* XXX: not in schema; some mention in 3.4.1.1.5 (Step 5: Redirecting + * to the Identity Provider Return URL) + */ + + return profile->signature_status; } /** @@ -436,165 +336,132 @@ lasso_defederation_process_notification_msg(LassoDefederation *defederation, * @defederation: the federation termination object * * Validate the federation termination notification : - * verifies the ProviderID - * if HTTP-Redirect method, set msg_url with the federation termination service return url - * verifies the federation - * verifies the authentication + * - verifies the ProviderID + * - if HTTP-Redirect method, set msg_url with the federation termination + * service return url + * - verifies the federation + * - verifies the authentication * * Return value: O if OK else < 0 **/ gint lasso_defederation_validate_notification(LassoDefederation *defederation) { - LassoProfile *profile; - LassoProvider *provider; - LassoFederation *federation = NULL; - LassoNode *nameIdentifier = NULL; - gint ret = 0; - gint remote_provider_type; - - profile = LASSO_PROFILE(defederation); - - /* verify the federation termination notification */ - if (profile->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Request not found\n"); - ret = -1; - goto done; - } - - /* set the remote provider id from the request */ - profile->remote_providerID = lasso_node_get_child_content(profile->request, - "ProviderID", - NULL, - NULL); - if (profile->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Remote provider id not found\n"); - ret = -1; - goto done; - } - - /* get the remote provider type */ - if (profile->provider_type == lassoProviderTypeSp) { - remote_provider_type = lassoProviderTypeIdp; - } - else if (profile->provider_type == lassoProviderTypeIdp) { - remote_provider_type = lassoProviderTypeSp; - } - else { - message(G_LOG_LEVEL_CRITICAL, "invalid provider type\n"); - ret = -1; - goto done; - } - - /* If SOAP notification, then msg_url and msg_body are NULL */ - /* if HTTP-Redirect notification, set msg_url with the federation termination service return url, - and set msg_body to NULL */ - profile->msg_url = NULL; - profile->msg_body = NULL; - if (profile->http_request_method == lassoHttpMethodRedirect) { - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, NULL); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Provider not found\n"); - ret = -1; - goto done; - } - - /* build the QUERY and the url. Dont need to sign the query, only the relay state is optinaly added and it is crypted by the notifier */ - profile->msg_url = lasso_provider_get_federationTerminationServiceReturnURL(provider, - remote_provider_type, - NULL); - - if (profile->msg_url == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Federation termination service return url not found\n"); - ret = -1; - goto done; - } - - /* if a relay state, then build the query part */ - if (profile->msg_relayState != NULL) { - gchar *url; - url = g_strdup_printf("%s?RelayState=%s", profile->msg_url, profile->msg_relayState); - xmlFree(profile->msg_url); - profile->msg_url = url; - } - } - - /* get the name identifier */ - nameIdentifier = lasso_node_get_child(profile->request, - "NameIdentifier", - NULL, - NULL); - if (nameIdentifier == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier not found in request\n"); - ret = -1; - goto done; - } - - /* Verify federation */ - if (profile->identity == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Identity not found\n"); - ret = -1; - goto done; - } - - federation = lasso_identity_get_federation(profile->identity, profile->remote_providerID); - if (federation == NULL) { - message(G_LOG_LEVEL_CRITICAL, "No federation for %s\n", profile->remote_providerID); - ret = -1; - goto done; - } - - if (lasso_federation_verify_nameIdentifier(federation, nameIdentifier) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "No name identifier for %s\n", profile->remote_providerID); - ret = -1; - goto done; - } - - /* remove federation of the remote provider */ - lasso_identity_remove_federation(profile->identity, profile->remote_providerID); - - /* if defederation has a session and if there is an assertion for remote provider id, then remove assertion too */ - if (profile->session != NULL) { - lasso_session_remove_assertion(profile->session, profile->remote_providerID); - } - - done: - if (federation != NULL) { - lasso_federation_destroy(federation); - } - if (nameIdentifier != NULL) { - lasso_node_destroy(nameIdentifier); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoFederation *federation = NULL; + LassoSamlNameIdentifier *nameIdentifier; + + g_return_val_if_fail(LASSO_IS_DEFEDERATION(defederation), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(defederation); + + /* verify the federation termination notification */ + if (LASSO_IS_LIB_FEDERATION_TERMINATION_NOTIFICATION(profile->request) == FALSE) + return LASSO_PROFILE_ERROR_MISSING_REQUEST; + + /* If SOAP notification, then msg_url and msg_body are NULL */ + /* if HTTP-Redirect notification, set msg_url with the federation + * termination service return url, and set msg_body to NULL */ + profile->msg_url = NULL; + profile->msg_body = NULL; + + if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Provider not found\n"); + return -1; + } + + /* build the QUERY and the url. Dont need to sign the query, + * only the relay state is optinaly added and it is crypted + * by the notifier */ + profile->msg_url = lasso_provider_get_metadata_one(remote_provider, + "FederationTerminationServiceReturnURL"); + if (profile->msg_url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Unknown profile service return URL"); + return -1; + } + + /* if a relay state, then build the query part */ + if (profile->msg_relayState) { + gchar *url; + url = g_strdup_printf("%s?RelayState=%s", + profile->msg_url, profile->msg_relayState); + g_free(profile->msg_url); + profile->msg_url = url; + } + } + + /* get the name identifier */ + nameIdentifier = LASSO_LIB_FEDERATION_TERMINATION_NOTIFICATION( + profile->request)->NameIdentifier; + if (nameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Name identifier not found in request"); + return -1; + } + + /* Verify federation */ + if (profile->identity == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + return -1; + } + + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (federation == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + return -1; + } + + if (lasso_federation_verify_nameIdentifier(federation, nameIdentifier) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "No name identifier for %s\n", + profile->remote_providerID); + return -1; + } + + /* remove federation of the remote provider */ + lasso_identity_remove_federation(profile->identity, profile->remote_providerID); + + /* if defederation has a session and if there is an assertion for remote provider id, + then remove assertion too */ + if (profile->session != NULL) { + lasso_session_remove_assertion(profile->session, profile->remote_providerID); + } + + return 0; } + + /*****************************************************************************/ /* overrided parent class methods */ /*****************************************************************************/ +static LassoNodeClass *parent_class = NULL; + static void -lasso_defederation_dispose(LassoDefederation *defederation) +dispose(GObject *object) { - if (defederation->private->dispose_has_run == TRUE) { - return; - } - defederation->private->dispose_has_run = TRUE; - - /* unref reference counted objects */ - parent_class->dispose(G_OBJECT(defederation)); - - debug("Defederation object 0x%x disposed ...\n", defederation); + LassoDefederation *defederation = LASSO_DEFEDERATION(object); + if (defederation->private->dispose_has_run == TRUE) { + return; + } + defederation->private->dispose_has_run = TRUE; + debug("Defederation object 0x%x disposed ...\n", defederation); + + G_OBJECT_CLASS(parent_class)->dispose(object); } static void -lasso_defederation_finalize(LassoDefederation *defederation) +finalize(GObject *object) { - g_free (defederation->private); - - parent_class->finalize(G_OBJECT(defederation)); - - debug("Defederation object 0x%x finalized ...\n", defederation); + LassoDefederation *defederation = LASSO_DEFEDERATION(object); + debug("Defederation object 0x%x finalized ...\n", defederation); + g_free (defederation->private); + G_OBJECT_CLASS(parent_class)->finalize(object); } /*****************************************************************************/ @@ -602,47 +469,48 @@ lasso_defederation_finalize(LassoDefederation *defederation) /*****************************************************************************/ static void -lasso_defederation_instance_init(GTypeInstance *instance, - gpointer g_class) +instance_init(LassoDefederation *defederation) { - LassoDefederation *defederation = LASSO_DEFEDERATION(instance); - - defederation->private = g_new (LassoDefederationPrivate, 1); - defederation->private->dispose_has_run = FALSE; + defederation->private = g_new (LassoDefederationPrivate, 1); + defederation->private->dispose_has_run = FALSE; } static void -lasso_defederation_class_init(LassoDefederationClass *class) +class_init(LassoDefederationClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); + parent_class = g_type_class_peek_parent(klass); - parent_class = g_type_class_peek_parent(class); - /* override parent class methods */ - gobject_class->dispose = (void *)lasso_defederation_dispose; - gobject_class->finalize = (void *)lasso_defederation_finalize; + /* no dump needed + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + */ + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; } -GType lasso_defederation_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoDefederationClass), - NULL, - NULL, - (GClassInitFunc) lasso_defederation_class_init, - NULL, - NULL, - sizeof(LassoDefederation), - 0, - (GInstanceInitFunc) lasso_defederation_instance_init, - }; - - this_type = g_type_register_static(LASSO_TYPE_PROFILE, - "LassoDefederation", - &this_info, 0); - } - return this_type; +GType +lasso_defederation_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoDefederationClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoDefederation), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_PROFILE, + "LassoDefederation", &this_info, 0); + } + return this_type; } /** @@ -666,18 +534,15 @@ GType lasso_defederation_get_type() { * Return value: a new instance of federation termination object or NULL **/ LassoDefederation* -lasso_defederation_new(LassoServer *server, - lassoProviderType provider_type) +lasso_defederation_new(LassoServer *server) { - LassoDefederation *defederation; + LassoDefederation *defederation; - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); + g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - /* set the defederation object */ - defederation = g_object_new(LASSO_TYPE_DEFEDERATION, - "server", lasso_server_copy(server), - "provider_type", provider_type, - NULL); + defederation = g_object_new(LASSO_TYPE_DEFEDERATION, NULL); + LASSO_PROFILE(defederation)->server = server; - return defederation; + return defederation; } + diff --git a/lasso/id-ff/defederation.h b/lasso/id-ff/defederation.h index 75633ea9..5254ed0b 100644 --- a/lasso/id-ff/defederation.h +++ b/lasso/id-ff/defederation.h @@ -31,7 +31,7 @@ extern "C" { #endif /* __cplusplus */ #include <lasso/environs/profile.h> -#include <lasso/protocols/federation_termination_notification.h> +#include <lasso/xml/lib_federation_termination_notification.h> #define LASSO_TYPE_DEFEDERATION (lasso_defederation_get_type()) #define LASSO_DEFEDERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_DEFEDERATION, LassoDefederation)) @@ -45,22 +45,18 @@ typedef struct _LassoDefederationClass LassoDefederationClass; typedef struct _LassoDefederationPrivate LassoDefederationPrivate; struct _LassoDefederation { - LassoProfile parent; - - /*< private >*/ - - LassoDefederationPrivate *private; + LassoProfile parent; + /*< private >*/ + LassoDefederationPrivate *private; }; struct _LassoDefederationClass { - LassoProfileClass parent; - + LassoProfileClass parent; }; LASSO_EXPORT GType lasso_defederation_get_type (void); -LASSO_EXPORT LassoDefederation *lasso_defederation_new (LassoServer *server, - lassoProviderType provider_type); +LASSO_EXPORT LassoDefederation *lasso_defederation_new (LassoServer *server); LASSO_EXPORT gint lasso_defederation_build_notification_msg (LassoDefederation *defederation); @@ -72,8 +68,7 @@ LASSO_EXPORT gint lasso_defederation_init_notification (LassoDefederation lassoHttpMethod notification_method); LASSO_EXPORT gint lasso_defederation_process_notification_msg (LassoDefederation *defederation, - gchar *notification_msg, - lassoHttpMethod notification_method); + gchar *notification_msg); LASSO_EXPORT gint lasso_defederation_validate_notification (LassoDefederation *defederation); diff --git a/lasso/id-ff/federation.c b/lasso/id-ff/federation.c new file mode 100644 index 00000000..8f57ad59 --- /dev/null +++ b/lasso/id-ff/federation.c @@ -0,0 +1,306 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: Nicolas Clapies <nclapies@entrouvert.com> + * Valery Febvre <vfebvre@easter-eggs.com> + * + * 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/environs/federation.h> + +struct _LassoFederationPrivate +{ + gboolean dispose_has_run; +}; + +/*****************************************************************************/ +/* static methods/functions */ +/*****************************************************************************/ + +static LassoSamlNameIdentifier* +lasso_federation_build_nameIdentifier(const gchar *nameQualifier, + const gchar *format, + const gchar *content) +{ + LassoSamlNameIdentifier *nameIdentifier; + + if (content == NULL) { + nameIdentifier = LASSO_SAML_NAME_IDENTIFIER(lasso_saml_name_identifier_new()); + nameIdentifier->content = lasso_build_unique_id(32); + } else { + nameIdentifier = LASSO_SAML_NAME_IDENTIFIER(lasso_saml_name_identifier_new()); + nameIdentifier->content = g_strdup(content); + } + nameIdentifier->NameQualifier = g_strdup(nameQualifier); + nameIdentifier->Format = g_strdup(format); + + return nameIdentifier; +} + +/*****************************************************************************/ +/* public methods */ +/*****************************************************************************/ + +void +lasso_federation_build_local_nameIdentifier(LassoFederation *federation, + const gchar *nameQualifier, + const gchar *format, + const gchar *content) +{ + federation->local_nameIdentifier = lasso_federation_build_nameIdentifier( + nameQualifier, format, content); +} + +void +lasso_federation_set_local_name_identifier(LassoFederation *federation, + LassoSamlNameIdentifier *name_identifier) +{ + if (federation->local_nameIdentifier) + g_object_unref(federation->local_nameIdentifier); + federation->local_nameIdentifier = g_object_ref(name_identifier); +} +void +lasso_federation_set_remote_name_identifier(LassoFederation *federation, + LassoSamlNameIdentifier *name_identifier) +{ + if (federation->remote_nameIdentifier) + g_object_unref(federation->remote_nameIdentifier); + federation->remote_nameIdentifier = g_object_ref(name_identifier); +} + +void +lasso_federation_destroy(LassoFederation *federation) +{ + g_object_unref(G_OBJECT(federation)); +} + +gboolean +lasso_federation_verify_nameIdentifier(LassoFederation *federation, + LassoSamlNameIdentifier *nameIdentifier) +{ + char *s; + /* XXX: verify_nameIdentifier only checks content; what about Format + * and NameQualifier ? */ + + g_return_val_if_fail(LASSO_IS_FEDERATION(federation), FALSE); + g_return_val_if_fail(LASSO_IS_NODE(nameIdentifier), FALSE); + + /* verify local name identifier */ + if (federation->local_nameIdentifier != NULL) { + s = federation->local_nameIdentifier->content; + if (strcmp(s, nameIdentifier->content) == 0) { + return TRUE; + } + } + + /* verify remote name identifier */ + if (federation->remote_nameIdentifier != NULL) { + s = federation->remote_nameIdentifier->content; + if (strcmp(s, nameIdentifier->content) == 0) { + return TRUE; + } + } + + return FALSE; +} + + +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ + +static LassoNodeClass *parent_class = NULL; + +static xmlNode* +get_xmlNode(LassoNode *node) +{ + xmlNode *xmlnode, *t; + LassoFederation *federation = LASSO_FEDERATION(node); + + xmlnode = xmlNewNode(NULL, "Federation"); + xmlSetNs(xmlnode, xmlNewNs(xmlnode, LASSO_LASSO_HREF, NULL)); + xmlSetProp(xmlnode, "Version", "2"); + + if (federation->remote_providerID) + xmlNewTextChild(xmlnode, NULL, "RemoteProviderID", federation->remote_providerID); + + if (federation->local_nameIdentifier) { + t = xmlNewTextChild(xmlnode, NULL, "LocalNameIdentifier", NULL); + xmlAddChild(t, lasso_node_get_xmlNode( + LASSO_NODE(federation->local_nameIdentifier))); + } + + if (federation->remote_nameIdentifier) { + t = xmlNewTextChild(xmlnode, NULL, "RemoteNameIdentifier", NULL); + xmlAddChild(t, lasso_node_get_xmlNode( + LASSO_NODE(federation->remote_nameIdentifier))); + } + + return xmlnode; +} + +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) +{ + LassoFederation *federation = LASSO_FEDERATION(node); + xmlNode *t, *n; + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + + if (strcmp(t->name, "RemoteProviderID") == 0) + federation->remote_providerID = xmlNodeGetContent(t); + + if (strcmp(t->name, "LocalNameIdentifier") == 0) { + n = t->children; + while (n && n->type != XML_ELEMENT_NODE) n = n->next; + if (n) { + federation->local_nameIdentifier = LASSO_SAML_NAME_IDENTIFIER( + lasso_node_new_from_xmlNode(n)); + } + } + + if (strcmp(t->name, "RemoteNameIdentifier") == 0) { + n = t->children; + while (n && n->type != XML_ELEMENT_NODE) n = n->next; + if (n) { + federation->remote_nameIdentifier = LASSO_SAML_NAME_IDENTIFIER( + lasso_node_new_from_xmlNode(n)); + } + } + + t = t->next; + } +} + +/*****************************************************************************/ +/* overrided parent class methods */ +/*****************************************************************************/ + +static void +dispose(GObject *object) +{ + LassoFederation *federation = LASSO_FEDERATION(object); + if (federation->private->dispose_has_run) { + return; + } + federation->private->dispose_has_run = TRUE; + + debug("Federation object 0x%x disposed ...\n", federation); + + /* unref reference counted objects */ + lasso_node_destroy(LASSO_NODE(federation->local_nameIdentifier)); + lasso_node_destroy(LASSO_NODE(federation->remote_nameIdentifier)); + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + +static void +finalize(GObject *object) +{ + LassoFederation *federation = LASSO_FEDERATION(object); + debug("Federation object 0x%x finalized ...\n", federation); + + g_free(federation->remote_providerID); + g_free(federation->private); + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +/*****************************************************************************/ +/* instance and class init functions */ +/*****************************************************************************/ + +static void +instance_init(LassoFederation *federation) +{ + federation->private = g_new (LassoFederationPrivate, 1); + federation->private->dispose_has_run = FALSE; + + federation->remote_providerID = NULL; + federation->local_nameIdentifier = NULL; + federation->remote_nameIdentifier = NULL; +} + +static void +class_init(LassoFederationClass *klass) +{ + parent_class = g_type_class_peek_parent(klass); + + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; +} + +GType +lasso_federation_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoFederationClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoFederation), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_NODE, + "LassoFederation", &this_info, 0); + } + return this_type; +} + +LassoFederation* +lasso_federation_new(gchar *remote_providerID) +{ + LassoFederation *federation; + + g_return_val_if_fail(remote_providerID != NULL, NULL); + + federation = LASSO_FEDERATION(g_object_new(LASSO_TYPE_FEDERATION, NULL)); + + federation->remote_providerID = g_strdup(remote_providerID); + + return federation; +} + +LassoFederation* +lasso_federation_new_from_dump(gchar *dump) +{ + LassoFederation *federation; + + g_return_val_if_fail(dump != NULL, NULL); + + federation = LASSO_FEDERATION(g_object_new(LASSO_TYPE_FEDERATION, NULL)); + + return federation; +} diff --git a/lasso/id-ff/federation.h b/lasso/id-ff/federation.h new file mode 100644 index 00000000..faf59dff --- /dev/null +++ b/lasso/id-ff/federation.h @@ -0,0 +1,89 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: Nicolas Clapies <nclapies@entrouvert.com> + * Valery Febvre <vfebvre@easter-eggs.com> + * + * 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_FEDERATION_H__ +#define __LASSO_FEDERATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <lasso/xml/xml.h> +#include <lasso/xml/saml_name_identifier.h> + +#define LASSO_TYPE_FEDERATION (lasso_federation_get_type()) +#define LASSO_FEDERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_FEDERATION, LassoFederation)) +#define LASSO_FEDERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), LASSO_TYPE_FEDERATION, LassoFederationClass)) +#define LASSO_IS_FEDERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), LASSO_TYPE_FEDERATION)) +#define LASSO_IS_FEDERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LASSO_TYPE_FEDERATION)) +#define LASSO_FEDERATION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), LASSO_TYPE_FEDERATION, LassoFederationClass)) + +#define LASSO_FEDERATION_NODE "Federation" +#define LASSO_FEDERATION_REMOTE_PROVIDERID_NODE "RemoteProviderID" +#define LASSO_FEDERATION_LOCAL_NAME_IDENTIFIER_NODE "LocalNameIdentifier" +#define LASSO_FEDERATION_REMOTE_NAME_IDENTIFIER_NODE "RemoteNameIdentifier" + +typedef struct _LassoFederation LassoFederation; +typedef struct _LassoFederationClass LassoFederationClass; +typedef struct _LassoFederationPrivate LassoFederationPrivate; + +struct _LassoFederation { + LassoNode parent; + + gchar *remote_providerID; + + LassoSamlNameIdentifier *local_nameIdentifier; + LassoSamlNameIdentifier *remote_nameIdentifier; + + /*< private >*/ + LassoFederationPrivate *private; +}; + +struct _LassoFederationClass { + LassoNodeClass parent; +}; + +LASSO_EXPORT GType lasso_federation_get_type(void); + +LASSO_EXPORT LassoFederation* lasso_federation_new(gchar *remote_providerID); + +LASSO_EXPORT void lasso_federation_build_local_nameIdentifier(LassoFederation *federation, + const gchar *nameQualifier, const gchar *format, const gchar *content); + +LASSO_EXPORT void lasso_federation_set_local_name_identifier(LassoFederation *federation, + LassoSamlNameIdentifier *name_identifier); +LASSO_EXPORT void lasso_federation_set_remote_name_identifier(LassoFederation *federation, + LassoSamlNameIdentifier *name_identifier); + +LASSO_EXPORT void lasso_federation_destroy(LassoFederation *federation); + +LASSO_EXPORT gboolean lasso_federation_verify_nameIdentifier( + LassoFederation *federation, LassoSamlNameIdentifier *nameIdentifier); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LASSO_FEDERATION_H__ */ diff --git a/lasso/id-ff/identity.c b/lasso/id-ff/identity.c index 36363f9b..82508eab 100644 --- a/lasso/id-ff/identity.c +++ b/lasso/id-ff/identity.c @@ -25,292 +25,133 @@ #include <lasso/environs/identity.h> -#include <lasso/lasso_config.h> - -#define LASSO_IDENTITY_NODE "Identity" -#define LASSO_IDENTITY_FEDERATIONS_NODE "Federations" -#define LASSO_IDENTITY_FEDERATION_NODE "Federation" -#define LASSO_IDENTITY_REMOTE_PROVIDERID_ATTR "RemoteProviderID" - struct _LassoIdentityPrivate { - gboolean dispose_has_run; + gboolean dispose_has_run; }; -static GObjectClass *parent_class = NULL; - -/*****************************************************************************/ -/* private functions */ -/*****************************************************************************/ - -static void -lasso_identity_copy_federation(gpointer key, - gpointer value, - gpointer federations) -{ - g_hash_table_insert((GHashTable *)federations, g_strdup((gchar *)key), - lasso_federation_copy(LASSO_FEDERATION(value))); -} - -static void -lasso_identity_dump_federation(gpointer key, - gpointer value, - LassoNode *federations) -{ - LassoNode *federation_node; - LassoNodeClass *federation_class; - xmlChar *dump; - - dump = lasso_federation_dump(LASSO_FEDERATION(value)); - federation_node = lasso_node_new_from_dump(dump); - xmlFree(dump); - federation_class = LASSO_NODE_GET_CLASS(federation_node); - federation_class->add_child(federations, federation_node, TRUE); - lasso_node_destroy(federation_node); -} - /*****************************************************************************/ /* public methods */ /*****************************************************************************/ gint -lasso_identity_add_federation(LassoIdentity *identity, - gchar *remote_providerID, - LassoFederation *federation) +lasso_identity_add_federation(LassoIdentity *identity, LassoFederation *federation) { - gboolean found = FALSE; - int i; - - g_return_val_if_fail(LASSO_IS_IDENTITY(identity), -1); - g_return_val_if_fail(remote_providerID != NULL, -2); - g_return_val_if_fail(LASSO_IS_FEDERATION(federation), -3); - - /* add the remote provider id if not already saved */ - for (i = 0; i<identity->providerIDs->len; i++) { - if(xmlStrEqual(remote_providerID, g_ptr_array_index(identity->providerIDs, i))) { - found = TRUE; - break; - } - } - if (found == TRUE) { - debug("A federation existed already for this providerID, it was replaced by the new one.\n"); - } - else { - g_ptr_array_add(identity->providerIDs, g_strdup(remote_providerID)); - } - - /* add the federation, replace if one already exists */ - g_hash_table_insert(identity->federations, g_strdup(remote_providerID), - lasso_federation_copy(federation)); - - identity->is_dirty = TRUE; - - return 0; + g_return_val_if_fail(LASSO_IS_IDENTITY(identity), -1); + g_return_val_if_fail(LASSO_IS_FEDERATION(federation), -3); + + /* add the federation, replace if one already exists */ + g_hash_table_insert(identity->federations, + g_strdup(federation->remote_providerID), federation); + identity->is_dirty = TRUE; + + return 0; } -LassoIdentity* -lasso_identity_copy(LassoIdentity *identity) +gint +lasso_identity_remove_federation(LassoIdentity *identity, char *remote_providerID) { - LassoIdentity *copy; - guint i; - - if (identity == NULL) { - return NULL; - } - - copy = LASSO_IDENTITY(g_object_new(LASSO_TYPE_IDENTITY, NULL)); - - copy->providerIDs = g_ptr_array_new(); - for(i=0; i<identity->providerIDs->len; i++) { - g_ptr_array_add(copy->providerIDs, - g_strdup(g_ptr_array_index(identity->providerIDs, i))); - } - copy->federations = g_hash_table_new_full(g_str_hash, g_str_equal, - (GDestroyNotify)g_free, - (GDestroyNotify)lasso_node_destroy); - g_hash_table_foreach(identity->federations, (GHFunc)lasso_identity_copy_federation, - (gpointer)copy->federations); - copy->is_dirty = identity->is_dirty; - - return copy; + if (g_hash_table_remove(identity->federations, remote_providerID) == FALSE) { + debug("Failed to remove federation for remote Provider %s", remote_providerID); + return -1; + } + identity->is_dirty = TRUE; + return 0; } void lasso_identity_destroy(LassoIdentity *identity) { - if (LASSO_IS_IDENTITY(identity)) { - g_object_unref(G_OBJECT(identity)); - } -} - -gchar* -lasso_identity_dump(LassoIdentity *identity) -{ - LassoNode *identity_node, *federations_node; - int table_size; - gchar *dump; - - g_return_val_if_fail(identity != NULL, NULL); - - identity_node = lasso_node_new(); - LASSO_NODE_GET_CLASS(identity_node)->set_name(identity_node, LASSO_IDENTITY_NODE); - LASSO_NODE_GET_CLASS(identity_node)->set_ns(identity_node, lassoLassoHRef, NULL); - - /* Add lasso version in the xml node */ - LASSO_NODE_GET_CLASS(identity_node)->set_prop(LASSO_NODE(identity_node), "version", PACKAGE_VERSION); - - /* dump the federations */ - table_size = g_hash_table_size(identity->federations); - if (table_size > 0) { - federations_node = lasso_node_new(); - LASSO_NODE_GET_CLASS(federations_node)->set_name(federations_node, - LASSO_IDENTITY_FEDERATIONS_NODE); - g_hash_table_foreach(identity->federations, (GHFunc)lasso_identity_dump_federation, - federations_node); - LASSO_NODE_GET_CLASS(identity_node)->add_child(identity_node, federations_node, FALSE); - lasso_node_destroy(federations_node); - } - - dump = lasso_node_export(identity_node); - - lasso_node_destroy(identity_node); - - return dump; + if (LASSO_IS_IDENTITY(identity)) { + g_object_unref(G_OBJECT(identity)); + } } -LassoFederation* -lasso_identity_get_federation(LassoIdentity *identity, - gchar *remote_providerID) -{ - LassoFederation *federation; - - g_return_val_if_fail(identity != NULL, NULL); - g_return_val_if_fail(remote_providerID != NULL, NULL); - - federation = lasso_identity_get_federation_ref(identity, remote_providerID); - if (federation != NULL) { - return lasso_federation_copy(federation); - } +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ - return NULL; -} +static LassoNodeClass *parent_class = NULL; -LassoFederation* -lasso_identity_get_federation_ref(LassoIdentity *identity, - gchar *remote_providerID) +static void +add_federation_childnode(gchar *key, LassoFederation *value, xmlNode *xmlnode) { - LassoFederation *federation; - - g_return_val_if_fail(identity != NULL, NULL); - g_return_val_if_fail(remote_providerID != NULL, NULL); - - federation = (LassoFederation *)g_hash_table_lookup(identity->federations, - remote_providerID); - if (federation == NULL) { - debug("No Federation found with remote ProviderID = %s\n", remote_providerID); - return NULL; - } - - return federation; + xmlAddChild(xmlnode, lasso_node_get_xmlNode(LASSO_NODE(value))); } -gchar* -lasso_identity_get_first_providerID(LassoIdentity *identity) +static xmlNode* +get_xmlNode(LassoNode *node) { - gchar *remote_providerID; - - g_return_val_if_fail(identity!=NULL, NULL); + xmlNode *xmlnode; + LassoIdentity *identity = LASSO_IDENTITY(node); - if (identity->providerIDs->len == 0) { - return NULL; - } + xmlnode = xmlNewNode(NULL, "Identity"); + xmlSetNs(xmlnode, xmlNewNs(xmlnode, LASSO_LASSO_HREF, NULL)); + xmlSetProp(xmlnode, "Version", "2"); - remote_providerID = g_strdup(g_ptr_array_index(identity->providerIDs, 0)); + if (g_hash_table_size(identity->federations)) + g_hash_table_foreach(identity->federations, + (GHFunc)add_federation_childnode, xmlnode); - return remote_providerID; + return xmlnode; } -gchar* -lasso_identity_get_next_federation_remote_providerID(LassoIdentity *identity) -{ - /* FIXME ABI : lasso_identity_get_next_federation_remote_providerID method is obsolete, use lasso_identity_get_first_providerID instead */ - - return lasso_identity_get_first_providerID(identity); +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) +{ + LassoIdentity *identity = LASSO_IDENTITY(node); + xmlNode *t; + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + + if (strcmp(t->name, "Federation") == 0) { + LassoFederation *federation; + federation = LASSO_FEDERATION(lasso_node_new_from_xmlNode(t)); + g_hash_table_insert( + identity->federations, + g_strdup(federation->remote_providerID), federation); + } + + t = t->next; + } } -gint -lasso_identity_remove_federation(LassoIdentity *identity, - gchar *remote_providerID) -{ - LassoFederation *federation; - int i; - - g_return_val_if_fail(identity != NULL, -1); - g_return_val_if_fail(remote_providerID != NULL, -2); - - /* remove the federation */ - federation = lasso_identity_get_federation(identity, remote_providerID); - if (federation != NULL) { - g_hash_table_remove(identity->federations, remote_providerID); - lasso_federation_destroy(federation); - } - else { - debug("Failed to remove federation for remote Provider %s\n", remote_providerID); - } - - /* remove the federation remote provider id */ - for (i = 0; i<identity->providerIDs->len; i++) { - if (xmlStrEqual(remote_providerID, g_ptr_array_index(identity->providerIDs, i))) { - debug("Remove federation of %s\n", remote_providerID); - g_ptr_array_remove_index(identity->providerIDs, i); - break; - } - } - - identity->is_dirty = TRUE; - - return 0; -} /*****************************************************************************/ /* overrided parent class methods */ /*****************************************************************************/ static void -lasso_identity_dispose(LassoIdentity *identity) +dispose(GObject *object) { - if (identity->private->dispose_has_run == TRUE) { - return; - } - identity->private->dispose_has_run = TRUE; + LassoIdentity *identity = LASSO_IDENTITY(object); + + if (identity->private->dispose_has_run == TRUE) { + return; + } + identity->private->dispose_has_run = TRUE; - debug("Identity object 0x%x disposed ...\n", identity); + debug("Identity object 0x%x disposed ...\n", identity); - g_hash_table_destroy(identity->federations); - identity->federations = NULL; + /* XXX: here or in finalize ? + * g_hash_table_destroy(identity->federations); */ - parent_class->dispose(G_OBJECT(identity)); + G_OBJECT_CLASS(parent_class)->dispose(object); } static void -lasso_identity_finalize(LassoIdentity *identity) +finalize(GObject *object) { - gint i; + LassoIdentity *identity = LASSO_IDENTITY(object); - debug("Identity object 0x%x finalized ...\n", identity); - - /* free allocated memory for providerIDs array */ - for (i=0; i<identity->providerIDs->len; i++) { - g_free(identity->providerIDs->pdata[i]); - identity->providerIDs->pdata[i] = NULL; - } - g_ptr_array_free(identity->providerIDs, TRUE); - identity->providerIDs = NULL; - - g_free(identity->private); - identity->private = NULL; - - parent_class->finalize(G_OBJECT(identity)); + debug("Identity object 0x%x finalized ...\n", identity); + identity->private = NULL; + G_OBJECT_CLASS(parent_class)->finalize(object); } /*****************************************************************************/ @@ -318,191 +159,79 @@ lasso_identity_finalize(LassoIdentity *identity) /*****************************************************************************/ static void -lasso_identity_instance_init(LassoIdentity *identity) +instance_init(LassoIdentity *identity) { - identity->private = g_new (LassoIdentityPrivate, 1); - identity->private->dispose_has_run = FALSE; - - identity->providerIDs = g_ptr_array_new(); - identity->federations = g_hash_table_new_full(g_str_hash, g_str_equal, - (GDestroyNotify)g_free, - (GDestroyNotify)lasso_federation_destroy); - identity->is_dirty = FALSE; + identity->private = g_new (LassoIdentityPrivate, 1); + identity->private->dispose_has_run = FALSE; + + identity->federations = g_hash_table_new_full(g_str_hash, g_str_equal, + (GDestroyNotify)g_free, + (GDestroyNotify)lasso_federation_destroy); + identity->is_dirty = FALSE; } static void -lasso_identity_class_init(LassoIdentityClass *class) +class_init(LassoIdentityClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - /* override parent class methods */ - gobject_class->dispose = (void *)lasso_identity_dispose; - gobject_class->finalize = (void *)lasso_identity_finalize; -} + parent_class = g_type_class_peek_parent(klass); -GType lasso_identity_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoIdentityClass), - NULL, - NULL, - (GClassInitFunc) lasso_identity_class_init, - NULL, - NULL, - sizeof(LassoIdentity), - 0, - (GInstanceInitFunc) lasso_identity_instance_init, - }; - - this_type = g_type_register_static(G_TYPE_OBJECT, - "LassoIdentity", - &this_info, 0); - } - return this_type; + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; } -LassoIdentity* -lasso_identity_new() +GType +lasso_identity_get_type() { - LassoIdentity *identity; + static GType this_type = 0; - identity = LASSO_IDENTITY(g_object_new(LASSO_TYPE_IDENTITY, NULL)); + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoIdentityClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoIdentity), + 0, + (GInstanceInitFunc) instance_init, + }; - return identity; + this_type = g_type_register_static(LASSO_TYPE_NODE, + "LassoIdentity", &this_info, 0); + } + return this_type; } LassoIdentity* -lasso_identity_new_from_dump(gchar *dump) +lasso_identity_new() { - LassoNode *identity_node; - LassoNode *federations_node, *federation_node; - LassoNode *nis, *ni, *nameIdentifier; - - LassoNodeClass *federations_class; - - xmlNodePtr federations_xmlNode, federation_xmlNode; - - LassoIdentity *identity; - LassoFederation *federation; - xmlChar *str, *remote_providerID; - GError *err = NULL; - - g_return_val_if_fail(dump != NULL, NULL); - - /* new object */ - identity = LASSO_IDENTITY(g_object_new(LASSO_TYPE_IDENTITY, NULL)); - - /* get identity */ - identity_node = lasso_node_new_from_dump(dump); - if (identity_node == NULL) { - message(G_LOG_LEVEL_WARNING, "Can't create a identity from dump\n"); - return NULL; - } - - /* federations */ - federations_node = lasso_node_get_child(identity_node, - LASSO_IDENTITY_FEDERATIONS_NODE, - lassoLassoHRef, NULL); - if (federations_node != NULL) { - federations_class = LASSO_NODE_GET_CLASS(federations_node); - federations_xmlNode = federations_class->get_xmlNode(federations_node); - federation_xmlNode = federations_xmlNode->children; - - while (federation_xmlNode != NULL) { - if (federation_xmlNode->type==XML_ELEMENT_NODE && \ - xmlStrEqual(federation_xmlNode->name, LASSO_IDENTITY_FEDERATION_NODE)) { - federation_node = lasso_node_new_from_xmlNode(federation_xmlNode); - remote_providerID = lasso_node_get_attr_value(federation_node, - LASSO_FEDERATION_REMOTE_PROVIDERID_NODE, &err); - if (remote_providerID == NULL) { - message(G_LOG_LEVEL_WARNING, err->message); - g_error_free(err); - lasso_node_destroy(federation_node); - federation_xmlNode = federation_xmlNode->next; - continue; - } - - /* new federation */ - federation = lasso_federation_new(remote_providerID); - - /* local name identifier */ - nis = lasso_node_get_child(federation_node, - LASSO_FEDERATION_LOCAL_NAME_IDENTIFIER_NODE, - lassoLassoHRef, NULL); - if (nis != NULL) { - ni = lasso_node_get_child(nis, "NameIdentifier", NULL, NULL); - if (ni != NULL) { - /* content */ - str = lasso_node_get_content(ni, NULL); - nameIdentifier = lasso_saml_name_identifier_new(str); - xmlFree(str); - /* NameQualifier */ - str = lasso_node_get_attr_value(ni, "NameQualifier", NULL); - if (str != NULL) { - lasso_saml_name_identifier_set_nameQualifier(LASSO_SAML_NAME_IDENTIFIER(nameIdentifier), str); - xmlFree(str); - } - /* format */ - str = lasso_node_get_attr_value(ni, "Format", NULL); - if (str != NULL) { - lasso_saml_name_identifier_set_format(LASSO_SAML_NAME_IDENTIFIER(nameIdentifier), str); - xmlFree(str); - } - lasso_federation_set_local_nameIdentifier(federation, nameIdentifier); - lasso_node_destroy(ni); - lasso_node_destroy(nameIdentifier); - } - lasso_node_destroy(nis); - } - - /* remote name identifier */ - nis = lasso_node_get_child(federation_node, - LASSO_FEDERATION_REMOTE_NAME_IDENTIFIER_NODE, - lassoLassoHRef, NULL); - if (nis != NULL) { - ni = lasso_node_get_child(nis, "NameIdentifier", NULL, NULL); - if (ni != NULL) { - /* content */ - str = lasso_node_get_content(ni, NULL); - nameIdentifier = lasso_saml_name_identifier_new(str); - xmlFree(str); - /* NameQualifier */ - str = lasso_node_get_attr_value(ni, "NameQualifier", NULL); - if (str != NULL) { - lasso_saml_name_identifier_set_nameQualifier(LASSO_SAML_NAME_IDENTIFIER(nameIdentifier), str); - xmlFree(str); - } - /* format */ - str = lasso_node_get_attr_value(ni, "Format", NULL); - if (str != NULL) { - lasso_saml_name_identifier_set_format(LASSO_SAML_NAME_IDENTIFIER(nameIdentifier), str); - xmlFree(str); - } - lasso_federation_set_remote_nameIdentifier(federation, nameIdentifier); - lasso_node_destroy(ni); - lasso_node_destroy(nameIdentifier); - } - lasso_node_destroy(nis); - } - - debug("Add federation for %s\n", remote_providerID); - lasso_identity_add_federation(identity, remote_providerID, federation); + return g_object_new(LASSO_TYPE_IDENTITY, NULL); +} - xmlFree(remote_providerID); - lasso_node_destroy(federation_node); - lasso_federation_destroy(federation); - } +LassoIdentity* +lasso_identity_new_from_dump(const gchar *dump) +{ + LassoIdentity *identity; + xmlDoc *doc; - federation_xmlNode = federation_xmlNode->next; - } + identity = lasso_identity_new(); + doc = xmlParseMemory(dump, strlen(dump)); + init_from_xml(LASSO_NODE(identity), xmlDocGetRootElement(doc)); + xmlFreeDoc(doc); - lasso_node_destroy(federations_node); - } + return identity; +} - lasso_node_destroy(identity_node); +gchar* +lasso_identity_dump(LassoIdentity *identity) +{ + if (g_hash_table_size(identity->federations) == 0) + return g_strdup(""); - return identity; + return lasso_node_dump(LASSO_NODE(identity), NULL, 1); } + diff --git a/lasso/id-ff/identity.h b/lasso/id-ff/identity.h index b33d9996..5b4ab055 100644 --- a/lasso/id-ff/identity.h +++ b/lasso/id-ff/identity.h @@ -31,7 +31,7 @@ extern "C" { #endif /* __cplusplus */ #include <lasso/xml/xml.h> -#include <lasso/protocols/federation.h> +#include <lasso/environs/federation.h> #define LASSO_TYPE_IDENTITY (lasso_identity_get_type()) #define LASSO_IDENTITY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_IDENTITY, LassoIdentity)) @@ -45,50 +45,32 @@ typedef struct _LassoIdentityClass LassoIdentityClass; typedef struct _LassoIdentityPrivate LassoIdentityPrivate; struct _LassoIdentity { - GObject parent; + LassoNode parent; - /*< public >*/ - GPtrArray *providerIDs; /* list of the remote provider ids for federations hash table */ - GHashTable *federations; /* hash for federations with remote ProviderID as key */ + /*< public >*/ + GHashTable *federations; /* hash for federations with remote ProviderID as key */ + gboolean is_dirty; - gboolean is_dirty; - - /*< private >*/ - LassoIdentityPrivate *private; + /*< private >*/ + LassoIdentityPrivate *private; }; struct _LassoIdentityClass { - GObjectClass parent; + LassoNodeClass parent; }; -LASSO_EXPORT GType lasso_identity_get_type (void); - -LASSO_EXPORT LassoIdentity* lasso_identity_new (void); - -LASSO_EXPORT LassoIdentity* lasso_identity_new_from_dump (gchar *dump); - -LASSO_EXPORT gint lasso_identity_add_federation (LassoIdentity *identity, - gchar *remote_providerID, - LassoFederation *federation); - -LASSO_EXPORT LassoIdentity* lasso_identity_copy (LassoIdentity *identity); - -LASSO_EXPORT void lasso_identity_destroy (LassoIdentity *identity); - -LASSO_EXPORT gchar* lasso_identity_dump (LassoIdentity *identity); - -LASSO_EXPORT LassoFederation* lasso_identity_get_federation (LassoIdentity *identity, - gchar *remote_providerID); - -LASSO_EXPORT LassoFederation* lasso_identity_get_federation_ref (LassoIdentity *identity, - gchar *remote_providerID); +LASSO_EXPORT GType lasso_identity_get_type(void); +LASSO_EXPORT LassoIdentity* lasso_identity_new(void); -LASSO_EXPORT gchar* lasso_identity_get_first_providerID (LassoIdentity *identity); +LASSO_EXPORT gint lasso_identity_add_federation(LassoIdentity *identity, + LassoFederation *federation); +LASSO_EXPORT gint lasso_identity_remove_federation(LassoIdentity *identity, + char *remote_providerID); -LASSO_EXPORT gchar* lasso_identity_get_next_federation_remote_providerID (LassoIdentity *identity); +LASSO_EXPORT void lasso_identity_destroy(LassoIdentity *identity); -LASSO_EXPORT gint lasso_identity_remove_federation (LassoIdentity *identity, - gchar *remote_providerID); +LASSO_EXPORT gchar* lasso_identity_dump(LassoIdentity *identity); +LASSO_EXPORT LassoIdentity* lasso_identity_new_from_dump(const gchar *dump); #ifdef __cplusplus } diff --git a/lasso/id-ff/lecp.c b/lasso/id-ff/lecp.c index 09d19c77..8f3d2623 100644 --- a/lasso/id-ff/lecp.c +++ b/lasso/id-ff/lecp.c @@ -41,9 +41,8 @@ lasso_lecp_build_authn_request_envelope_msg(LassoLecp *lecp) profile = LASSO_PROFILE(lecp); - assertionConsumerServiceURL = lasso_provider_get_assertionConsumerServiceURL(LASSO_PROVIDER(profile->server), - lassoProviderTypeSp, - NULL); + assertionConsumerServiceURL = lasso_provider_get_metadata_one( + LASSO_PROVIDER(profile->server), "AssertionConsumerServiceURL"); if (assertionConsumerServiceURL == NULL) { message(G_LOG_LEVEL_CRITICAL, "AssertionConsumerServiceURL not found\n"); return -1; @@ -54,15 +53,20 @@ lasso_lecp_build_authn_request_envelope_msg(LassoLecp *lecp) return -1; } - lecp->authnRequestEnvelope = lasso_authn_request_envelope_new(LASSO_AUTHN_REQUEST(profile->request), - profile->server->providerID, - assertionConsumerServiceURL); +#if 0 + lecp->authnRequestEnvelope = lasso_authn_request_envelope_new( + LASSO_LIB_AUTHN_REQUEST(profile->request), + LASSO_PROVIDER(profile->server)->ProviderID, + assertionConsumerServiceURL); +#endif if (lecp->authnRequestEnvelope == NULL) { message(G_LOG_LEVEL_CRITICAL, "Error while building AuthnRequestEnvelope\n"); return -1; } +#if 0 /* XXX: dump to xml ? */ profile->msg_body = lasso_node_export(lecp->authnRequestEnvelope); +#endif if (profile->msg_body == NULL) { message(G_LOG_LEVEL_CRITICAL, "Error while exporting the AuthnRequestEnvelope to POST msg\n"); return -1; @@ -99,11 +103,9 @@ lasso_lecp_build_authn_request_msg(LassoLecp *lecp, profile->remote_providerID = g_strdup(remote_providerID); } - remote_provider = lasso_server_get_provider_ref(profile->server, - profile->remote_providerID, - NULL); + remote_provider = g_hash_table_lookup(profile->server->providers, profile->remote_providerID); - profile->msg_url = lasso_provider_get_singleSignOnServiceURL(remote_provider, NULL); + profile->msg_url = lasso_provider_get_metadata_one(remote_provider, "SingleSignOnServiceURL"); profile->msg_body = lasso_node_export_to_soap(profile->request); if (profile->msg_body == NULL) { message(G_LOG_LEVEL_CRITICAL, "Error while building the AuthnRequest SOAP message\n"); @@ -136,11 +138,14 @@ lasso_lecp_build_authn_response_msg(LassoLecp *lecp) } gint -lasso_lecp_build_authn_response_envelope_msg(LassoLecp *lecp, - gint authentication_result, - gboolean is_consent_obtained, - const gchar *authenticationMethod, - const gchar *reauthenticateOnOrAfter) +lasso_lecp_build_authn_response_envelope_msg(LassoLecp *lecp, + gint authentication_result, + gboolean is_consent_obtained, + const char *authenticationMethod, + const char *authenticationInstant, + const char *reauthenticateOnOrAfter, + const char *notBefore, + const char *notOnOrAfter) { LassoProfile *profile; LassoProvider *provider; @@ -150,14 +155,12 @@ lasso_lecp_build_authn_response_envelope_msg(LassoLecp *lecp, profile = LASSO_PROFILE(lecp); - if (LASSO_IS_AUTHN_RESPONSE(profile->response) == FALSE) { + if (LASSO_IS_LIB_AUTHN_RESPONSE(profile->response) == FALSE) { message(G_LOG_LEVEL_CRITICAL, "AuthnResponse not found\n"); return -1; } - provider = lasso_server_get_provider_ref(profile->server, - profile->remote_providerID, - NULL); + provider = g_hash_table_lookup(profile->server->providers, profile->remote_providerID); if (provider == NULL) { message(G_LOG_LEVEL_CRITICAL, "Provider %s not found\n", profile->remote_providerID); return -1; @@ -168,11 +171,13 @@ lasso_lecp_build_authn_response_envelope_msg(LassoLecp *lecp, authentication_result, is_consent_obtained, authenticationMethod, - reauthenticateOnOrAfter); + authenticationInstant, + reauthenticateOnOrAfter, + notBefore, + notOnOrAfter); - assertionConsumerServiceURL = lasso_provider_get_assertionConsumerServiceURL(provider, - lassoProviderTypeSp, - NULL); + assertionConsumerServiceURL = lasso_provider_get_metadata_one( + provider, "AssertionConsumerServiceURL"); if (assertionConsumerServiceURL == NULL) { message(G_LOG_LEVEL_CRITICAL, "AssertionConsumerServiceURL not found\n"); return -1; @@ -182,8 +187,9 @@ lasso_lecp_build_authn_response_envelope_msg(LassoLecp *lecp, LASSO_PROFILE(lecp)->msg_body = NULL; xmlFree(LASSO_PROFILE(lecp)->msg_url); LASSO_PROFILE(lecp)->msg_url = NULL; - lecp->authnResponseEnvelope = lasso_authn_response_envelope_new(LASSO_AUTHN_RESPONSE(profile->response), - assertionConsumerServiceURL); + lecp->authnResponseEnvelope = lasso_lib_authn_response_envelope_new( + LASSO_LIB_AUTHN_RESPONSE(profile->response), + assertionConsumerServiceURL); LASSO_PROFILE(lecp)->msg_body = lasso_node_export_to_soap(lecp->authnResponseEnvelope); if (LASSO_PROFILE(lecp)->msg_body == NULL) { @@ -204,26 +210,26 @@ lasso_lecp_init_authn_request(LassoLecp *lecp) /* FIXME : BAD usage of http_method using POST method so that the lib:AuthnRequest is initialize with a signature template */ - res = lasso_login_init_authn_request(LASSO_LOGIN(lecp), lassoHttpMethodPost); + res = lasso_login_init_authn_request(LASSO_LOGIN(lecp), LASSO_HTTP_METHOD_POST); return res; } gint lasso_lecp_process_authn_request_msg(LassoLecp *lecp, - gchar *authn_request_msg, - lassoHttpMethod authn_request_method) + gchar *authn_request_msg) { + lassoHttpMethod authn_request_method = 0; /* XXX: update to CVS */ gint res; g_return_val_if_fail(LASSO_IS_LECP(lecp), -1); g_return_val_if_fail(authn_request_msg!=NULL, -1); - if (authn_request_method != lassoHttpMethodSoap) { + if (authn_request_method != LASSO_HTTP_METHOD_SOAP) { message(G_LOG_LEVEL_CRITICAL, "Invalid authentication request method\n"); return -1; } - res = lasso_login_process_authn_request_msg(LASSO_LOGIN(lecp), authn_request_msg, authn_request_method); + res = lasso_login_process_authn_request_msg(LASSO_LOGIN(lecp), authn_request_msg); return res; } @@ -234,13 +240,17 @@ lasso_lecp_process_authn_request_envelope_msg(LassoLecp *lecp, g_return_val_if_fail(LASSO_IS_LECP(lecp), -1); g_return_val_if_fail(request_msg!=NULL, -1); - lecp->authnRequestEnvelope = lasso_authn_request_envelope_new_from_export(request_msg, lassoNodeExportTypeXml); +#if 0 /* XXX */ + lecp->authnRequestEnvelope = lasso_authn_request_envelope_new_from_export(request_msg, LASSO_NODE_EXPORT_TYPE_XML); +#endif if (lecp->authnRequestEnvelope == NULL) { message(G_LOG_LEVEL_CRITICAL, "Error while building the authentication request envelope\n"); return -1; } +#if 0 LASSO_PROFILE(lecp)->request = lasso_authn_request_envelope_get_authnRequest(LASSO_AUTHN_REQUEST_ENVELOPE(lecp->authnRequestEnvelope)); +#endif if (LASSO_PROFILE(lecp)->request == NULL) { message(G_LOG_LEVEL_CRITICAL, "AuthnRequest not found\n"); return -1; @@ -260,24 +270,29 @@ lasso_lecp_process_authn_response_envelope_msg(LassoLecp *lecp, profile = LASSO_PROFILE(lecp); - lecp->authnResponseEnvelope = lasso_authn_response_envelope_new_from_export(response_msg, lassoNodeExportTypeSoap); + lecp->authnResponseEnvelope = lasso_lib_authn_response_envelope_new(NULL, NULL); + lasso_node_init_from_message(lecp->authnResponseEnvelope, response_msg); if (lecp->authnResponseEnvelope == NULL) { message(G_LOG_LEVEL_CRITICAL, "Error while building AuthnResponseEnvelope\n"); return -1; } +#if 0 /* XXX */ profile->response = lasso_authn_response_envelope_get_authnResponse(LASSO_AUTHN_RESPONSE_ENVELOPE(lecp->authnResponseEnvelope)); if (profile->response == NULL) { message(G_LOG_LEVEL_CRITICAL, "AuthnResponse not found\n"); return -1; } +#endif +#if 0 /* XXX */ lecp->assertionConsumerServiceURL = lasso_authn_response_envelope_get_assertionConsumerServiceURL( LASSO_AUTHN_RESPONSE_ENVELOPE(lecp->authnResponseEnvelope)); if (lecp->assertionConsumerServiceURL == NULL){ message(G_LOG_LEVEL_CRITICAL, "AssertionConsumerServiceURL not found\n"); return -1; } +#endif return 0; } @@ -355,7 +370,7 @@ lasso_lecp_new(LassoServer *server) if (LASSO_IS_SERVER(server)) { debug("Add server to lecp object\n"); - LASSO_PROFILE(lecp)->server = lasso_server_copy(server); + /* XXX LASSO_PROFILE(lecp)->server = lasso_server_copy(server); */ } diff --git a/lasso/id-ff/lecp.h b/lasso/id-ff/lecp.h index 93ff6d08..0316d6e5 100644 --- a/lasso/id-ff/lecp.h +++ b/lasso/id-ff/lecp.h @@ -32,8 +32,8 @@ extern "C" { #include <lasso/xml/xml.h> -#include <lasso/protocols/authn_request_envelope.h> -#include <lasso/protocols/authn_response_envelope.h> +#include <lasso/xml/lib_authn_request_envelope.h> +#include <lasso/xml/lib_authn_response_envelope.h> #include <lasso/environs/login.h> @@ -74,19 +74,21 @@ LASSO_EXPORT gint lasso_lecp_build_authn_request_msg (LassoLec LASSO_EXPORT gint lasso_lecp_build_authn_response_msg (LassoLecp *lecp); -LASSO_EXPORT gint lasso_lecp_build_authn_response_envelope_msg (LassoLecp *lecp, - gint authentication_result, - gboolean is_consent_obtained, - const gchar *authenticationMethod, - const gchar *reauthenticateOnOrAfter); +LASSO_EXPORT gint lasso_lecp_build_authn_response_envelope_msg(LassoLecp *lecp, + gint authentication_result, + gboolean is_consent_obtained, + const char *authenticationMethod, + const char *authenticationInstant, + const char *reauthenticateOnOrAfter, + const char *notBefore, + const char *notOnOrAfter); LASSO_EXPORT void lasso_lecp_destroy (LassoLecp *lecp); LASSO_EXPORT gint lasso_lecp_init_authn_request (LassoLecp *lecp); LASSO_EXPORT gint lasso_lecp_process_authn_request_msg (LassoLecp *lecp, - gchar *authn_request_msg, - lassoHttpMethod authn_request_method); + gchar *authn_request_msg); LASSO_EXPORT gint lasso_lecp_process_authn_request_envelope_msg (LassoLecp *lecp, gchar *request_msg); diff --git a/lasso/id-ff/login.c b/lasso/id-ff/login.c index 56b3d6e0..ca3878b1 100644 --- a/lasso/id-ff/login.c +++ b/lasso/id-ff/login.c @@ -1,4 +1,4 @@ - /* $Id$ +/* $Id$ * * Lasso - A free implementation of the Liberty Alliance specifications. * @@ -6,7 +6,7 @@ * http://lasso.entrouvert.org * * Authors: Nicolas Clapies <nclapies@entrouvert.com> - * Valery Febvre <vfebvre@easter-eggs.com> + * Valery Febvre <vfebvre@easter-eggs.com> * * 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 @@ -15,12 +15,12 @@ * * 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 + * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <string.h> @@ -29,122 +29,117 @@ #include <lasso/xml/errors.h> -#include <lasso/protocols/artifact.h> -#include <lasso/protocols/provider.h> -#include <lasso/protocols/elements/authentication_statement.h> - #include <lasso/environs/login.h> - -static GObjectClass *parent_class = NULL; +#include <lasso/environs/provider.h> struct _LassoLoginPrivate { - gboolean dispose_has_run; + gboolean dispose_has_run; }; /*****************************************************************************/ -/* static methods/functions */ +/* static methods/functions */ /*****************************************************************************/ /** * lasso_login_build_assertion: * @login: a Login - * @federation: the Federation - * @authenticationMethod: the authentication method - * @reauthenticateOnOrAfter: the reauthenticate on or after time + * @federation: a federation or NULL + * @authenticationMethod: the authentication method. + * @authenticationInstant: the time at which the authentication took place or NULL. + * @reauthenticateOnOrAfter: the time at, or after which the service provider + * reauthenticates the Principal with the identity provider or NULL. + * @notBefore: the earliest time instant at which the assertion is valid or NULL. + * @notOnOrAfter: the time instant at which the assertion has expired or NULL. * * Builds an assertion. * Assertion is stored in session property. If session property is NULL, a new * session is build before. * The NameIdentifier of the assertion is stored into nameIdentifier proprerty. - * + * If @authenticationInstant is NULL, the current time will be set. + * Time values must be encoded in UTC. + * * Return value: 0 on success or a negative value otherwise. **/ static gint -lasso_login_build_assertion(LassoLogin *login, - LassoFederation *federation, - const gchar *authenticationMethod, - const gchar *reauthenticateOnOrAfter) +lasso_login_build_assertion(LassoLogin *login, + LassoFederation *federation, + const char *authenticationMethod, + const char *authenticationInstant, + const char *reauthenticateOnOrAfter, + const char *notBefore, + const char *notOnOrAfter) { - LassoNode *assertion = NULL, *nameIdentifier, *as; - xmlChar *id, *requestID; - GError *err = NULL; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - /* federation MAY be NULL */ - - /* - get RequestID to build Assertion - it may be NULL when the Identity provider initiates SSO. - in this case, no InResponseTo will be added in assertion - */ - requestID = lasso_node_get_attr_value(LASSO_NODE(LASSO_PROFILE(login)->request), - "RequestID", NULL); - assertion = lasso_assertion_new(LASSO_PROFILE(login)->server->providerID, - requestID); - if (requestID != NULL) { - xmlFree(requestID); - } - - if (xmlStrEqual(login->nameIDPolicy, lassoLibNameIDPolicyTypeOneTime)) { - /* if NameIDPolicy is 'onetime', don't use a federation */ - id = lasso_build_unique_id(32); - nameIdentifier = lasso_saml_name_identifier_new(id); - xmlFree(id); - lasso_saml_name_identifier_set_nameQualifier(LASSO_SAML_NAME_IDENTIFIER(nameIdentifier), - LASSO_PROFILE(login)->server->providerID); - lasso_saml_name_identifier_set_format(LASSO_SAML_NAME_IDENTIFIER(nameIdentifier), - lassoLibNameIdentifierFormatOneTime); - as = lasso_authentication_statement_new(authenticationMethod, - reauthenticateOnOrAfter, - NULL, - LASSO_SAML_NAME_IDENTIFIER(nameIdentifier)); - LASSO_PROFILE(login)->nameIdentifier = lasso_node_get_content(nameIdentifier, NULL); - lasso_node_destroy(nameIdentifier); - } - else { - as = lasso_authentication_statement_new(authenticationMethod, - reauthenticateOnOrAfter, - LASSO_SAML_NAME_IDENTIFIER(federation->remote_nameIdentifier), - LASSO_SAML_NAME_IDENTIFIER(federation->local_nameIdentifier)); - } - if (as != NULL) { - lasso_saml_assertion_add_authenticationStatement(LASSO_SAML_ASSERTION(assertion), - LASSO_SAML_AUTHENTICATION_STATEMENT(as)); - } - else { - ret = -2; - goto done; - } - - /* FIXME : How to know if the assertion must be signed or unsigned ? */ - /* signature should be added at end */ - ret = lasso_saml_assertion_set_signature(LASSO_SAML_ASSERTION(assertion), - LASSO_PROFILE(login)->server->signature_method, - LASSO_PROFILE(login)->server->private_key, - LASSO_PROFILE(login)->server->certificate); - - if (ret == 0) { - if (login->protocolProfile == lassoLoginProtocolProfileBrwsPost) { - /* only add assertion if response is an AuthnResponse */ - lasso_samlp_response_add_assertion(LASSO_SAMLP_RESPONSE(LASSO_PROFILE(login)->response), - assertion); - } - /* store assertion in session object */ - if (LASSO_PROFILE(login)->session == NULL) { - LASSO_PROFILE(login)->session = lasso_session_new(); - } - lasso_session_add_assertion(LASSO_PROFILE(login)->session, - LASSO_PROFILE(login)->remote_providerID, - assertion); - } - - done: - lasso_node_destroy(as); - lasso_node_destroy(assertion); - - return ret; + LassoLibAssertion *assertion; + LassoLibAuthenticationStatement *as; + LassoSamlNameIdentifier *nameIdentifier; + LassoProfile *profile; + gint ret = 0; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + /* federation MAY be NULL */ + + profile = LASSO_PROFILE(login); + + /* + get RequestID to build Assertion + it may be NULL when the Identity provider initiates SSO. + in this case, no InResponseTo will be added in assertion + (XXX: what does that mean ? would profile->request also be NULL?) + */ + assertion = lasso_lib_assertion_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + LASSO_SAMLP_REQUEST_ABSTRACT(profile->request)->RequestID, + profile->remote_providerID, + notBefore, notOnOrAfter); + + if (strcmp(login->nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_ONE_TIME) == 0) { + /* if NameIDPolicy is 'onetime', don't use a federation */ + nameIdentifier = LASSO_SAML_NAME_IDENTIFIER(lasso_saml_name_identifier_new()); + nameIdentifier->content = lasso_build_unique_id(32); + nameIdentifier->NameQualifier = LASSO_PROVIDER(profile->server)->ProviderID; + nameIdentifier->Format = LASSO_LIB_NAME_IDENTIFIER_FORMAT_ONE_TIME; + + as = lasso_lib_authentication_statement_new_full(authenticationMethod, + authenticationInstant, reauthenticateOnOrAfter, + NULL, nameIdentifier); + profile->nameIdentifier = g_strdup(nameIdentifier->content); + } else { + as = lasso_lib_authentication_statement_new_full(authenticationMethod, + authenticationInstant, reauthenticateOnOrAfter, + federation->remote_nameIdentifier, + federation->local_nameIdentifier); + } + + if (as == NULL) { + return -2; + } + + LASSO_SAML_ASSERTION(assertion)->AuthenticationStatement = + LASSO_SAML_AUTHENTICATION_STATEMENT(as); + + /* FIXME : How to know if the assertion must be signed or unsigned ? */ + /* signature should be added at end */ + ret = lasso_saml_assertion_set_signature(LASSO_SAML_ASSERTION(assertion), + profile->server->signature_method, + profile->server->private_key, + profile->server->certificate); + if (ret) + return ret; + + if (login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST) { + /* only add assertion if response is an AuthnResponse */ + LASSO_SAMLP_RESPONSE(profile->response)->Assertion = LASSO_SAML_ASSERTION(assertion); + } + /* store assertion in session object */ + if (profile->session == NULL) { + profile->session = lasso_session_new(); + } + lasso_session_add_assertion( + profile->session, + profile->remote_providerID, + LASSO_SAML_ASSERTION(assertion)); + return 0; } /** @@ -159,68 +154,57 @@ lasso_login_build_assertion(LassoLogin *login, static gboolean lasso_login_must_ask_for_consent_private(LassoLogin *login) { - xmlChar *nameIDPolicy, *consent; - LassoFederation *federation = NULL; - gboolean ret; - - nameIDPolicy = lasso_node_get_child_content(LASSO_PROFILE(login)->request, - "NameIDPolicy", lassoLibHRef, NULL); - - if (xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeNone) || nameIDPolicy == NULL) { - ret = FALSE; - } - else if (xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeOneTime)) { - ret = FALSE; - } - else if (xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeFederated) || \ - xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeAny)) { - if (LASSO_PROFILE(login)->identity != NULL) { - federation = lasso_identity_get_federation(LASSO_PROFILE(login)->identity, - LASSO_PROFILE(login)->remote_providerID); - } - if (federation != NULL) { - ret = FALSE; - } - else { - consent = lasso_node_get_attr_value(LASSO_PROFILE(login)->request, - "consent", NULL); - if (consent != NULL) { - if (xmlStrEqual(consent, lassoLibConsentObtained) || \ - xmlStrEqual(consent, lassoLibConsentObtainedPrior) || \ - xmlStrEqual(consent, lassoLibConsentObtainedCurrentImplicit) || \ - xmlStrEqual(consent, lassoLibConsentObtainedCurrentExplicit)) { - ret = FALSE; - } - else if (xmlStrEqual(consent, lassoLibConsentUnavailable) || \ - xmlStrEqual(consent, lassoLibConsentInapplicable)) { - ret = TRUE; + xmlChar *nameIDPolicy, *consent; + LassoProfile *profile = LASSO_PROFILE(login); + LassoFederation *federation = NULL; + + nameIDPolicy = LASSO_LIB_AUTHN_REQUEST(profile->request)->NameIDPolicy; + + if (nameIDPolicy == NULL || strcmp(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_NONE) == 0) + return FALSE; + + if (strcmp(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_ONE_TIME) == 0) + return FALSE; + + if (strcmp(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_FEDERATED) != 0 && + strcmp(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_ANY) != 0) { + message(G_LOG_LEVEL_CRITICAL, "Unknown NameIDPolicy : %s\n", nameIDPolicy); + /* we consider NameIDPolicy as empty (none value) if its value is unknown/invalid */ + return TRUE; } - else { - message(G_LOG_LEVEL_CRITICAL, "Unknown consent value : %s\n", consent); - /* we consider consent as empty if its value is unknown/invalid */ - ret = TRUE; + + if (profile->identity != NULL) { + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (federation) + return FALSE; } - xmlFree(consent); - } - else { - /* no consent */ - ret = TRUE; - } - } - } - else { - message(G_LOG_LEVEL_CRITICAL, "Unknown NameIDPolicy : %s\n", nameIDPolicy); - /* we consider NameIDPolicy as empty (none value) if its value is unknown/invalid */ - ret = TRUE; - } - - done: - if (federation != NULL) { - lasso_federation_destroy(federation); - } - xmlFree(nameIDPolicy); - - return ret; + + consent = LASSO_LIB_AUTHN_REQUEST(profile->request)->consent; + if (consent == NULL) + return TRUE; + + if (strcmp(consent, LASSO_LIB_CONSENT_OBTAINED) == 0) + return FALSE; + + if (strcmp(consent, LASSO_LIB_CONSENT_OBTAINED_PRIOR) == 0) + return FALSE; + + if (strcmp(consent, LASSO_LIB_CONSENT_OBTAINED_CURRENT_IMPLICIT) == 0) + return FALSE; + + if (strcmp(consent, LASSO_LIB_CONSENT_OBTAINED_CURRENT_EXPLICIT) == 0) + return FALSE; + + if (strcmp(consent, LASSO_LIB_CONSENT_UNAVAILABLE) == 0) + return TRUE; + + if (strcmp(consent, LASSO_LIB_CONSENT_INAPPLICABLE) == 0) + return TRUE; + + message(G_LOG_LEVEL_CRITICAL, "Unknown consent value : %s\n", consent); + /* we consider consent as empty if its value is unknown/invalid */ + return TRUE; } /** @@ -231,194 +215,157 @@ lasso_login_must_ask_for_consent_private(LassoLogin *login) * Return value: a positive value on success or a negative if an error occurs. **/ static gint -lasso_login_process_federation(LassoLogin *login, - gboolean is_consent_obtained) +lasso_login_process_federation(LassoLogin *login, gboolean is_consent_obtained) { - LassoFederation *federation = NULL; - xmlChar *nameIDPolicy; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - /* verify if identity already exists else create it */ - if (LASSO_PROFILE(login)->identity == NULL) { - LASSO_PROFILE(login)->identity = lasso_identity_new(); - } - /* get nameIDPolicy in lib:AuthnRequest */ - nameIDPolicy = lasso_node_get_child_content(LASSO_PROFILE(login)->request, - "NameIDPolicy", lassoLibHRef, NULL); - login->nameIDPolicy = g_strdup(nameIDPolicy); - - /* if nameIDPolicy is 'onetime' => nothing to do */ - if (xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeOneTime)) { - goto done; - } - - /* search a federation in the identity */ - federation = lasso_identity_get_federation(LASSO_PROFILE(login)->identity, - LASSO_PROFILE(login)->remote_providerID); - - if ((nameIDPolicy == NULL || xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeNone))) { - /* a federation MUST exist */ - if (federation == NULL) { - /* - if protocolProfile is lassoLoginProtocolProfileBrwsPost - set StatusCode to FederationDoesNotExist in lib:AuthnResponse - */ - if (login->protocolProfile == lassoLoginProtocolProfileBrwsPost) { - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoLibStatusCodeFederationDoesNotExist); - } - ret = LASSO_LOGIN_ERROR_FEDERATION_NOT_FOUND; - goto done; - } - } - else if (xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeFederated) || \ - xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeAny)) { - /* - consent is necessary, it should be obtained via consent attribute - in lib:AuthnRequest or IDP should ask the Principal - */ - if (lasso_login_must_ask_for_consent_private(login) == TRUE && is_consent_obtained == FALSE) { - if (xmlStrEqual(nameIDPolicy, lassoLibNameIDPolicyTypeAny)) { - /* - if the NameIDPolicy element is 'any' and if the policy for the - Principal forbids federation, then evaluation MAY proceed as if the - value were onetime. - */ - g_free(login->nameIDPolicy); - login->nameIDPolicy = g_strdup(lassoLibNameIDPolicyTypeOneTime); - goto done; - } - else { - /* - if protocolProfile is lassoLoginProtocolProfileBrwsPost - set StatusCode to FederationDoesNotExist in lib:AuthnResponse - */ - /* FIXME : is it the correct value for the StatusCode */ - if (login->protocolProfile == lassoLoginProtocolProfileBrwsPost) { - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoLibStatusCodeFederationDoesNotExist); + LassoFederation *federation = NULL; + LassoProfile *profile = LASSO_PROFILE(login); + xmlChar *nameIDPolicy; + gint ret = 0; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + /* verify if identity already exists else create it */ + if (profile->identity == NULL) { + profile->identity = lasso_identity_new(); + } + /* get nameIDPolicy in lib:AuthnRequest */ + nameIDPolicy = LASSO_LIB_AUTHN_REQUEST(profile->request)->NameIDPolicy; + login->nameIDPolicy = g_strdup(nameIDPolicy); + + /* if nameIDPolicy is 'onetime' => nothing to do */ + if (xmlStrEqual(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_ONE_TIME)) { + goto done; + } + + /* search a federation in the identity */ + federation = g_hash_table_lookup(LASSO_PROFILE(login)->identity->federations, + LASSO_PROFILE(login)->remote_providerID); + + if ((nameIDPolicy == NULL || xmlStrEqual(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_NONE))) { + /* a federation MUST exist */ + if (federation == NULL) { + /* + if protocolProfile is LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST + set StatusCode to FederationDoesNotExist in lib:AuthnResponse + */ + if (login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST) { + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + } + ret = LASSO_LOGIN_ERROR_FEDERATION_NOT_FOUND; + goto done; + } + } + else if (xmlStrEqual(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_FEDERATED) || \ + xmlStrEqual(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_ANY)) { + /* + consent is necessary, it should be obtained via consent attribute + in lib:AuthnRequest or IDP should ask the Principal + */ + if (lasso_login_must_ask_for_consent_private(login) == TRUE && is_consent_obtained == FALSE) { + if (xmlStrEqual(nameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_ANY)) { + /* + if the NameIDPolicy element is 'any' and if the policy for the + Principal forbids federation, then evaluation MAY proceed as if the + value were onetime. + */ + g_free(login->nameIDPolicy); + login->nameIDPolicy = g_strdup(LASSO_LIB_NAMEID_POLICY_TYPE_ONE_TIME); + goto done; + } + else { + /* + if protocolProfile is LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST + set StatusCode to FederationDoesNotExist in lib:AuthnResponse + */ + /* FIXME : is it the correct value for the StatusCode */ + if (login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST) { + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + } + ret = LASSO_LOGIN_ERROR_CONSENT_NOT_OBTAINED; + goto done; + } + } + if (federation == NULL) { + federation = lasso_federation_new(LASSO_PROFILE(login)->remote_providerID); + lasso_federation_build_local_nameIdentifier(federation, + LASSO_PROVIDER(LASSO_PROFILE(login)->server)->ProviderID, + LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED, + NULL); + + lasso_identity_add_federation(LASSO_PROFILE(login)->identity, federation); + } + } + else { + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_LOGIN_ERROR_INVALID_NAMEIDPOLICY), nameIDPolicy); + ret = LASSO_LOGIN_ERROR_INVALID_NAMEIDPOLICY; + goto done; } - ret = LASSO_LOGIN_ERROR_CONSENT_NOT_OBTAINED; - goto done; - } - } - if (federation == NULL) { - federation = lasso_federation_new(LASSO_PROFILE(login)->remote_providerID); - lasso_federation_build_local_nameIdentifier(federation, - LASSO_PROFILE(login)->server->providerID, - lassoLibNameIdentifierFormatFederated, - NULL); - - lasso_identity_add_federation(LASSO_PROFILE(login)->identity, - LASSO_PROFILE(login)->remote_providerID, - federation); - } - } - else { - message(G_LOG_LEVEL_CRITICAL, - lasso_strerror(LASSO_LOGIN_ERROR_INVALID_NAMEIDPOLICY), nameIDPolicy); - ret = LASSO_LOGIN_ERROR_INVALID_NAMEIDPOLICY; - goto done; - } - - done: - /* store the IDP name identifier if a federation exists */ - if (federation != NULL) { - LASSO_PROFILE(login)->nameIdentifier = lasso_node_get_content(federation->local_nameIdentifier, NULL); - lasso_federation_destroy(federation); - } - xmlFree(nameIDPolicy); - - return ret; + +done: + /* store the IDP name identifier if a federation exists */ + if (federation != NULL) { + LASSO_PROFILE(login)->nameIdentifier = + LASSO_SAML_NAME_IDENTIFIER(federation->local_nameIdentifier)->content; + } + + return ret; } static gint lasso_login_process_response_status_and_assertion(LassoLogin *login) { - LassoNode *assertion = NULL, *status = NULL, *statusCode = NULL; - LassoProvider *idp = NULL; - gchar *statusCode_value = NULL; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - /* check StatusCode value */ - status = lasso_node_get_child(LASSO_PROFILE(login)->response, - "Status", lassoSamlProtocolHRef, &err); - if (status == NULL) { - ret = -1; - goto done; - } - statusCode = lasso_node_get_child(status, "StatusCode", lassoSamlProtocolHRef, &err); - if (statusCode == NULL) { - ret = -1; - goto done; - } - statusCode_value = lasso_node_get_attr_value(statusCode, "Value", &err); - if (statusCode_value != NULL) { - if (!xmlStrEqual(statusCode_value, lassoSamlStatusCodeSuccess)) { - ret = -7; - goto done; - } - } - - /* check assertion */ - assertion = lasso_node_get_child(LASSO_PROFILE(login)->response, - "Assertion", - NULL, /* lassoLibHRef, FIXME changed for SourceID */ - NULL); - - if (assertion != NULL) { - idp = lasso_server_get_provider_ref(LASSO_PROFILE(login)->server, - LASSO_PROFILE(login)->remote_providerID, - &err); - /* verify signature */ - if (idp != NULL) { - /* FIXME detect X509Data ? */ - ret = lasso_node_verify_signature(assertion, idp->public_key, idp->ca_cert_chain); - if (ret < 0) { - goto done; - } - } - else { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - /* store NameIdentifier */ - LASSO_PROFILE(login)->nameIdentifier = lasso_node_get_child_content(assertion, "NameIdentifier", - NULL, &err); - if (LASSO_PROFILE(login)->nameIdentifier == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_clear_error(&err); - /* we continue */ - } - } - - done: - if (err != NULL) { - if (err->code < 0) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_clear_error(&err); - } - } - xmlFree(statusCode_value); - lasso_node_destroy(statusCode); - lasso_node_destroy(status); - lasso_node_destroy(assertion); - - return ret; + LassoProvider *idp = NULL; + LassoSamlpResponse *response; + char *status_value; + int ret; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + response = LASSO_SAMLP_RESPONSE(LASSO_PROFILE(login)->response); + + if (response->Status == NULL || ! LASSO_IS_SAMLP_STATUS(response->Status)) + return -1; + + if (response->Status->StatusCode == NULL) + return -1; + + status_value = response->Status->StatusCode->Value; + if (status_value == NULL) { + /* XXX ? was ignored before ? */ + } + if (status_value && strcmp(status_value, LASSO_SAML_STATUS_CODE_SUCCESS) != 0) { + return -7; /* FIXME: proper error code */ + } + + if (response->Assertion) { + LassoProfile *profile = LASSO_PROFILE(login); + idp = g_hash_table_lookup(profile->server->providers, profile->remote_providerID); + if (idp == NULL) + return LASSO_ERROR_UNDEFINED; + + /* verify signature */ + /* FIXME detect X509Data ? */ + ret = lasso_node_verify_signature(LASSO_NODE(response->Assertion), + idp->public_key, idp->ca_cert_chain); + if (ret < 0) + return ret; + + /* store NameIdentifier */ + /* XXX: in AuthenticationStatement */ + profile->nameIdentifier = LASSO_SAML_SUBJECT_STATEMENT_ABSTRACT( + response->Assertion->AuthenticationStatement)->Subject->NameIdentifier->content; + + if (LASSO_PROFILE(login)->nameIdentifier == NULL) + return LASSO_ERROR_UNDEFINED; + } + + return 0; } /*****************************************************************************/ -/* public methods */ +/* public methods */ /*****************************************************************************/ /** @@ -435,206 +382,183 @@ lasso_login_process_response_status_and_assertion(LassoLogin *login) { gint lasso_login_accept_sso(LassoLogin *login) { - LassoNode *assertion = NULL; - LassoNode *ni = NULL; - LassoNode *idp_ni, *idp_ni_copy = NULL; - LassoFederation *federation = NULL; - xmlChar *nameIdentifier_format; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - if(LASSO_PROFILE(login)->identity == NULL) { - LASSO_PROFILE(login)->identity = lasso_identity_new(); - } - if(LASSO_PROFILE(login)->session == NULL) { - LASSO_PROFILE(login)->session = lasso_session_new(); - } - - if (LASSO_PROFILE(login)->response != NULL) { - assertion = lasso_node_get_child(LASSO_PROFILE(login)->response, - "Assertion", - NULL, /* lassoLibHRef, FIXME changed for SourceID */ - &err); - if (assertion == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - /* put response assertion in session object */ - lasso_session_add_assertion(LASSO_PROFILE(login)->session, - LASSO_PROFILE(login)->remote_providerID, - assertion); - - /* get the 2 NameIdentifiers and put them in identity object */ - ni = lasso_node_get_child(assertion, "NameIdentifier", - lassoSamlAssertionHRef, &err); - /* 1 - the saml:NameIdentifier SHOULD exists */ - if (ni == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - /* get the format of the nameIdentifier */ - nameIdentifier_format = lasso_node_get_attr_value(LASSO_NODE(ni), "Format", NULL); - /* FIXME : check nameIdentifier_format */ - - /* 2 - the lib:IDPProvidedNameIdentifier */ - idp_ni = lasso_node_get_child(assertion, "IDPProvidedNameIdentifier", - lassoLibHRef, &err); - if (idp_ni != NULL) { - idp_ni_copy = lasso_node_copy(idp_ni); - lasso_node_destroy(idp_ni); - /* transform the lib:IDPProvidedNameIdentifier into a saml:NameIdentifier */ - LASSO_NODE_GET_CLASS(idp_ni_copy)->set_name(idp_ni_copy, "NameIdentifier"); - LASSO_NODE_GET_CLASS(idp_ni_copy)->set_ns(idp_ni_copy, - lassoSamlAssertionHRef, - lassoSamlAssertionPrefix); - } - - /* create federation, only if nameidentifier format is Federated */ - if (xmlStrEqual(nameIdentifier_format, lassoLibNameIdentifierFormatFederated)) { - federation = lasso_federation_new(LASSO_PROFILE(login)->remote_providerID); - if (ni != NULL && idp_ni_copy != NULL) { - lasso_federation_set_local_nameIdentifier(federation, ni); - lasso_federation_set_remote_nameIdentifier(federation, idp_ni_copy); - } - else { - lasso_federation_set_remote_nameIdentifier(federation, ni); - } - /* add federation in identity */ - lasso_identity_add_federation(LASSO_PROFILE(login)->identity, - LASSO_PROFILE(login)->remote_providerID, - federation); - lasso_federation_destroy(federation); - } - xmlFree(nameIdentifier_format); - } - else { - message(G_LOG_LEVEL_CRITICAL, "response attribute is empty.\n"); - } - - done: - lasso_node_destroy(ni); - lasso_node_destroy(idp_ni_copy); - lasso_node_destroy(assertion); - - return ret; + LassoSamlAssertion *assertion = NULL; + LassoSamlNameIdentifier *ni = NULL; + LassoSamlNameIdentifier *idp_ni = NULL; + LassoFederation *federation = NULL; + LassoSamlSubjectStatementAbstract *authentication_statement; + LassoProfile *profile; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(login); + + if (profile->identity == NULL) + profile->identity = lasso_identity_new(); + + if (profile->session == NULL) + profile->session = lasso_session_new(); + + if (profile->response == NULL) + return -1; + + assertion = LASSO_SAMLP_RESPONSE(profile->response)->Assertion; + if (assertion == NULL) + return -1; + + lasso_session_add_assertion(profile->session, profile->remote_providerID, assertion); + + authentication_statement = LASSO_SAML_SUBJECT_STATEMENT_ABSTRACT( + LASSO_SAMLP_RESPONSE(profile->response)->Assertion->AuthenticationStatement); + ni = authentication_statement->Subject->NameIdentifier; + + if (ni == NULL) + return -1; + + if (LASSO_IS_LIB_SUBJECT(authentication_statement->Subject)) { + idp_ni = LASSO_LIB_SUBJECT(authentication_statement->Subject)->IDPProvidedNameIdentifier; + } + + /* create federation, only if nameidentifier format is Federated */ + if (strcmp(ni->Format, LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED) == 0) { + federation = lasso_federation_new(LASSO_PROFILE(login)->remote_providerID); + if (ni != NULL && idp_ni != NULL) { + federation->local_nameIdentifier = ni; + federation->remote_nameIdentifier = idp_ni; + } else { + federation->remote_nameIdentifier = ni; + } + /* add federation in identity */ + lasso_identity_add_federation(LASSO_PROFILE(login)->identity, federation); + } + + return 0; } /** * lasso_login_build_artifact_msg: * @login: a LassoLogin - * @authentication_result: the authentication result + * @authentication_result: whether the principal is authenticated. + * @is_consent_obtained: whether the principal consents to be federated. * @authenticationMethod: the authentication method + * @authenticationInstant: the time at which the authentication took place * @reauthenticateOnOrAfter: the time at, or after which the service provider - * reauthenticates the Principal with the identity provider + * reauthenticates the Principal with the identity provider or NULL + * @notBefore: the earliest time instant at which the assertion is valid + * @notOnOrAfter: the time instant at which the assertion has expired + * * @http_method: the HTTP method to send the artifact (REDIRECT or POST) * * Builds an artifact. Depending of the HTTP method, the data for the sending of * the artifact are stored in msg_url (REDIRECT) or msg_url, msg_body and * msg_relayState (POST). + * + * @authenticationMethod, @authenticationInstant, @reauthenticateOnOrAfter, + * @notBefore, @notOnOrAfter should be NULL if @authentication_result is FALSE. + * If @authenticationInstant is NULL, the current time will be set. + * + * Time values must be encoded in UTC. * * Return value: 0 on success and a negative value otherwise. **/ gint -lasso_login_build_artifact_msg(LassoLogin *login, - gboolean authentication_result, - gboolean is_consent_obtained, - const gchar *authenticationMethod, - const gchar *reauthenticateOnOrAfter, - lassoHttpMethod http_method) +lasso_login_build_artifact_msg(LassoLogin *login, + gboolean authentication_result, + gboolean is_consent_obtained, + const char *authenticationMethod, + const char *authenticationInstant, + const char *reauthenticateOnOrAfter, + const char *notBefore, + const char *notOnOrAfter, + lassoHttpMethod http_method) { - LassoFederation *federation = NULL; - LassoProvider *remote_provider; - gchar *url; - xmlSecByte samlArt[42], *b64_samlArt, *relayState; - xmlChar *assertionHandle, *identityProviderSuccinctID; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(authenticationMethod != NULL && reauthenticateOnOrAfter != NULL, - LASSO_PARAM_ERROR_INVALID_VALUE); - - if (http_method != lassoHttpMethodRedirect && http_method != lassoHttpMethodPost) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - } - - /* ProtocolProfile must be BrwsArt */ - if (login->protocolProfile != lassoLoginProtocolProfileBrwsArt) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE)); - return LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE; - } - - /* process federation and build assertion only if signature is OK */ - if (LASSO_PROFILE(login)->signature_status == 0 && authentication_result == TRUE) { - ret = lasso_login_process_federation(login, is_consent_obtained); - /* fill the response with the assertion */ - if (ret == 0) { - federation = lasso_identity_get_federation(LASSO_PROFILE(login)->identity, - LASSO_PROFILE(login)->remote_providerID); - lasso_login_build_assertion(login, - federation, - authenticationMethod, - reauthenticateOnOrAfter); - lasso_federation_destroy(federation); - } - else if (ret < 0) { - return ret; - } - } - - /* build artifact infos */ - remote_provider = lasso_server_get_provider_ref(LASSO_PROFILE(login)->server, - LASSO_PROFILE(login)->remote_providerID, - NULL); - /* liberty-idff-bindings-profiles-v1.2.pdf p.25 */ - url = lasso_provider_get_assertionConsumerServiceURL(remote_provider, lassoProviderTypeSp, NULL); - identityProviderSuccinctID = lasso_sha1(LASSO_PROFILE(login)->server->providerID); - assertionHandle = lasso_build_random_sequence(20); - - memcpy(samlArt, "\000\003", 2); /* byte code */ - memcpy(samlArt+2, identityProviderSuccinctID, 20); - memcpy(samlArt+22, assertionHandle, 20); - - xmlFree(assertionHandle); - xmlFree(identityProviderSuccinctID); - b64_samlArt = xmlSecBase64Encode(samlArt, 42, 0); - relayState = lasso_node_get_child_content(LASSO_PROFILE(login)->request, - "RelayState", NULL, NULL); - - switch (http_method) { - case lassoHttpMethodRedirect: - if (relayState == NULL) { - LASSO_PROFILE(login)->msg_url = g_strdup_printf("%s?SAMLart=%s", url, b64_samlArt); - } - else { - LASSO_PROFILE(login)->msg_url = g_strdup_printf("%s?SAMLart=%s&RelayState=%s", - url, b64_samlArt, relayState); - } - break; - case lassoHttpMethodPost: - LASSO_PROFILE(login)->msg_url = g_strdup(url); - LASSO_PROFILE(login)->msg_body = g_strdup(b64_samlArt); - if (relayState != NULL) { - LASSO_PROFILE(login)->msg_relayState = g_strdup(relayState); - } - break; - default: - break; - } - LASSO_PROFILE(login)->response_type = lassoMessageTypeArtifact; - login->assertionArtifact = g_strdup(b64_samlArt); - xmlFree(url); - xmlFree(b64_samlArt); - xmlFree(relayState); - - return ret; + /* XXX: function to check */ + LassoFederation *federation = NULL; + LassoProvider *remote_provider; + gchar *url; + xmlSecByte samlArt[42], *b64_samlArt, *relayState; + xmlChar *assertionHandle, *identityProviderSuccinctID; + gint ret = 0; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + if (http_method != LASSO_HTTP_METHOD_REDIRECT && http_method != LASSO_HTTP_METHOD_POST) { + message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); + return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; + } + + /* ProtocolProfile must be BrwsArt */ + if (login->protocolProfile != LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART) { + message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE)); + return LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE; + } + + /* process federation and build assertion only if signature is OK */ + if (LASSO_PROFILE(login)->signature_status == 0 && authentication_result == TRUE) { + ret = lasso_login_process_federation(login, is_consent_obtained); + if (ret < 0) + return ret; + + /* fill the response with the assertion */ + if (ret == 0) { + federation = g_hash_table_lookup(LASSO_PROFILE(login)->identity->federations, + LASSO_PROFILE(login)->remote_providerID); + lasso_login_build_assertion(login, + federation, + authenticationMethod, + authenticationInstant, + reauthenticateOnOrAfter, + notBefore, + notOnOrAfter); + } + } + + if (LASSO_PROFILE(login)->remote_providerID == NULL) + return -1; + + /* build artifact infos */ + remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, + LASSO_PROFILE(login)->remote_providerID); + /* liberty-idff-bindings-profiles-v1.2.pdf p.25 */ + url = lasso_provider_get_metadata_one(remote_provider, "AssertionConsumerServiceURL"); + identityProviderSuccinctID = lasso_sha1( + LASSO_PROVIDER(LASSO_PROFILE(login)->server)->ProviderID); + assertionHandle = lasso_build_random_sequence(20); + + memcpy(samlArt, "\000\003", 2); /* type code */ + memcpy(samlArt+2, identityProviderSuccinctID, 20); + memcpy(samlArt+22, assertionHandle, 20); + + xmlFree(assertionHandle); + xmlFree(identityProviderSuccinctID); + b64_samlArt = xmlSecBase64Encode(samlArt, 42, 0); + relayState = LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)->RelayState; + + switch (http_method) { + case LASSO_HTTP_METHOD_REDIRECT: + if (relayState == NULL) { + LASSO_PROFILE(login)->msg_url = g_strdup_printf("%s?SAMLart=%s", url, b64_samlArt); + } + else { + LASSO_PROFILE(login)->msg_url = g_strdup_printf("%s?SAMLart=%s&RelayState=%s", + url, b64_samlArt, relayState); + } + break; + case LASSO_HTTP_METHOD_POST: + LASSO_PROFILE(login)->msg_url = g_strdup(url); + LASSO_PROFILE(login)->msg_body = g_strdup(b64_samlArt); + if (relayState != NULL) { + LASSO_PROFILE(login)->msg_relayState = g_strdup(relayState); + } + break; + default: + break; + } + login->assertionArtifact = g_strdup(b64_samlArt); + xmlFree(url); + xmlFree(b64_samlArt); + + return ret; } /** @@ -652,207 +576,208 @@ lasso_login_build_artifact_msg(LassoLogin *login, * Return value: 0 on success and a negative value otherwise. **/ gint -lasso_login_build_authn_request_msg(LassoLogin *login, - const gchar *remote_providerID) +lasso_login_build_authn_request_msg(LassoLogin *login, const gchar *remote_providerID) { - LassoProvider *provider, *remote_provider; - xmlChar *md_authnRequestsSigned = NULL; - xmlChar *request_protocolProfile = NULL; - xmlChar *url = NULL; - gchar *query = NULL; - gchar *lareq = NULL; - gboolean must_sign; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - if (remote_providerID != NULL) { - LASSO_PROFILE(login)->remote_providerID = g_strdup(remote_providerID); - } - else { - LASSO_PROFILE(login)->remote_providerID = lasso_server_get_first_providerID(LASSO_PROFILE(login)->server); - } - - provider = LASSO_PROVIDER(LASSO_PROFILE(login)->server); - remote_provider = lasso_server_get_provider_ref(LASSO_PROFILE(login)->server, - LASSO_PROFILE(login)->remote_providerID, - &err); - if (remote_provider == NULL) { - ret = err->code; - g_error_free(err); - return ret; - } - - /* check if authnRequest must be signed */ - md_authnRequestsSigned = lasso_provider_get_authnRequestsSigned(provider, &err); - if (md_authnRequestsSigned != NULL) { - must_sign = xmlStrEqual(md_authnRequestsSigned, "true"); - xmlFree(md_authnRequestsSigned); - } - else { - /* AuthnRequestsSigned metadata is required in metadata */ - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - /* get SingleSignOnServiceURL metadata */ - url = lasso_provider_get_singleSignOnServiceURL(remote_provider, &err); - if (url == NULL) { - /* SingleSignOnServiceURL metadata is required */ - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - if (login->http_method == lassoHttpMethodRedirect) { - /* REDIRECT -> query */ - if (must_sign) { - query = lasso_node_export_to_query(LASSO_PROFILE(login)->request, - LASSO_PROFILE(login)->server->signature_method, - LASSO_PROFILE(login)->server->private_key); - if (query == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Failed to create AuthnRequest query (signed).\n"); - ret = -3; - goto done; - } - } - else { - query = lasso_node_export_to_query(LASSO_PROFILE(login)->request, 0, NULL); - if (query == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Failed to create AuthnRequest query.\n"); - ret = -4; - goto done; - } - } - /* alloc msg_url (+2 for the ? and \0) */ - LASSO_PROFILE(login)->msg_url = g_strdup_printf("%s?%s", url, query); - LASSO_PROFILE(login)->msg_body = NULL; - g_free(query); - } - else if (login->http_method == lassoHttpMethodPost) { - /* POST -> formular */ - if (must_sign) { - ret = lasso_samlp_request_abstract_sign_signature_tmpl(LASSO_SAMLP_REQUEST_ABSTRACT(LASSO_PROFILE(login)->request), - LASSO_PROFILE(login)->server->private_key, - LASSO_PROFILE(login)->server->certificate); - } - if (ret < 0) { - goto done; - } - lareq = lasso_node_export_to_base64(LASSO_PROFILE(login)->request); - if (lareq != NULL) { - LASSO_PROFILE(login)->msg_url = g_strdup(url); - LASSO_PROFILE(login)->msg_body = lareq; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Failed to export AuthnRequest (Base64 encoded).\n"); - ret = -5; - } - } - else { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE)); - ret = LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE; - } - - done: - xmlFree(url); - xmlFree(request_protocolProfile); - - return ret; + LassoProvider *provider, *remote_provider; + xmlChar *md_authnRequestsSigned = NULL; + xmlChar *request_protocolProfile = NULL; + xmlChar *url = NULL; + gchar *query = NULL; + gchar *lareq = NULL; + gboolean must_sign; + gint ret = 0; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + if (remote_providerID != NULL) { + LASSO_PROFILE(login)->remote_providerID = g_strdup(remote_providerID); + } else { + LASSO_PROFILE(login)->remote_providerID = lasso_server_get_first_providerID( + LASSO_PROFILE(login)->server); + } + + provider = LASSO_PROVIDER(LASSO_PROFILE(login)->server); + remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, + LASSO_PROFILE(login)->remote_providerID); + if (remote_provider == NULL) { + return -1; /* XXX */ + } + + /* check if authnRequest must be signed */ + md_authnRequestsSigned = lasso_provider_get_metadata_one(provider, "AuthnRequestsSigned"); + must_sign = (md_authnRequestsSigned && strcmp(md_authnRequestsSigned, "true") == 0); + + /* get SingleSignOnServiceURL metadata */ + url = lasso_provider_get_metadata_one(remote_provider, "SingleSignOnServiceURL"); + if (url == NULL) { + return -1; /* XXX */ + } + + if (login->http_method == LASSO_HTTP_METHOD_REDIRECT) { + /* REDIRECT -> query */ + if (must_sign) { + query = lasso_node_export_to_query(LASSO_PROFILE(login)->request, + LASSO_PROFILE(login)->server->signature_method, + LASSO_PROFILE(login)->server->private_key); + if (query == NULL) { + message(G_LOG_LEVEL_CRITICAL, + "Failed to create AuthnRequest query (signed)."); + ret = -3; + goto done; + } + } + else { + query = lasso_node_export_to_query(LASSO_PROFILE(login)->request, 0, NULL); + if (query == NULL) { + message(G_LOG_LEVEL_CRITICAL, + "Failed to create AuthnRequest query."); + ret = -4; + goto done; + } + } + /* alloc msg_url (+2 for the ? and \0) */ + LASSO_PROFILE(login)->msg_url = g_strdup_printf("%s?%s", url, query); + LASSO_PROFILE(login)->msg_body = NULL; + g_free(query); + } + if (login->http_method == LASSO_HTTP_METHOD_POST) { + /* POST -> formular */ + if (must_sign) { +#if 0 /* XXX: signatures are done differently */ + ret = lasso_samlp_request_abstract_sign_signature_tmpl(LASSO_SAMLP_REQUEST_ABSTRACT(LASSO_PROFILE(login)->request), + LASSO_PROFILE(login)->server->private_key, + LASSO_PROFILE(login)->server->certificate); +#endif + } + + if (ret < 0) { + goto done; + } + lareq = lasso_node_export_to_base64(LASSO_PROFILE(login)->request); + + if (lareq != NULL) { + LASSO_PROFILE(login)->msg_url = g_strdup(url); + LASSO_PROFILE(login)->msg_body = lareq; + } else { + message(G_LOG_LEVEL_CRITICAL, + "Failed to export AuthnRequest (Base64 encoded)."); + ret = -5; + } + } + +done: + xmlFree(url); + xmlFree(request_protocolProfile); + + return ret; } /** * lasso_login_build_authn_response_msg: * @login: a LassoLogin - * @authentication_result: the authentication result - * @authenticationMethod: the authentication method + * @authentication_result: whether the principal is authenticated + * @is_consent_obtained: whether the principal consents to be federated + * @authenticationMethod: the method used to authenticate the principal + * @authenticationInstant: the time at which the authentication took place * @reauthenticateOnOrAfter: the time at, or after which the service provider - * reauthenticates the Principal with the identity provider + * reauthenticates the Principal with the identity provider + * @notBefore: the earliest time instant at which the assertion is valid + * @notOnOrAfter: the time instant at which the assertion has expired * * Builds an authentication response. The data for the sending of the response * are stored in msg_url and msg_body. + * + * @authenticationMethod, @authenticationInstant, @reauthenticateOnOrAfter, + * @notBefore, @notOnOrAfter should be NULL if @authentication_result is FALSE. + * If @authenticationInstant is NULL, the current time will be set. + * + * Time values must be encoded in UTC. * * Return value: 0 on success and a negative value otherwise. **/ gint -lasso_login_build_authn_response_msg(LassoLogin *login, - gboolean authentication_result, - gboolean is_consent_obtained, - const gchar *authenticationMethod, - const gchar *reauthenticateOnOrAfter) +lasso_login_build_authn_response_msg(LassoLogin *login, + gboolean authentication_result, + gboolean is_consent_obtained, + const char *authenticationMethod, + const char *authenticationInstant, + const char *reauthenticateOnOrAfter, + const char *notBefore, + const char *notOnOrAfter) { - LassoProvider *remote_provider; - LassoFederation *federation; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - /* ProtocolProfile must be BrwsPost */ - if (login->protocolProfile != lassoLoginProtocolProfileBrwsPost) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE)); - return LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE; - } - - /* create LibAuthnResponse */ - LASSO_PROFILE(login)->response = lasso_authn_response_new(LASSO_PROFILE(login)->server->providerID, - LASSO_PROFILE(login)->request); - LASSO_PROFILE(login)->response_type = lassoMessageTypeAuthnResponse; - - /* if signature is not OK => modify AuthnResponse StatusCode */ - if (LASSO_PROFILE(login)->signature_status == LASSO_DS_ERROR_INVALID_SIGNATURE || - LASSO_PROFILE(login)->signature_status == LASSO_DS_ERROR_SIGNATURE_NOT_FOUND) { - switch (LASSO_PROFILE(login)->signature_status) { - case LASSO_DS_ERROR_INVALID_SIGNATURE: - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoLibStatusCodeInvalidSignature); - break; - case LASSO_DS_ERROR_SIGNATURE_NOT_FOUND: /* Unsigned AuthnRequest */ - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoLibStatusCodeUnsignedAuthnRequest); - break; - } - /* ret = LASSO_PROFILE(login)->signature_status; */ - } - else { - /* modify AuthnResponse StatusCode if user authentication is not OK */ - if (authentication_result == FALSE) { - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoSamlStatusCodeRequestDenied); - } - - if (LASSO_PROFILE(login)->signature_status == 0 && authentication_result == TRUE) { - /* process federation */ - ret = lasso_login_process_federation(login, is_consent_obtained); - /* fill the response with the assertion */ - if (ret == 0) { - federation = lasso_identity_get_federation(LASSO_PROFILE(login)->identity, - LASSO_PROFILE(login)->remote_providerID); - lasso_login_build_assertion(login, - federation, - authenticationMethod, - reauthenticateOnOrAfter); - lasso_federation_destroy(federation); - } - else if (ret < 0) { + LassoProvider *remote_provider; + LassoFederation *federation; + gint ret = 0; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + /* ProtocolProfile must be BrwsPost */ + if (login->protocolProfile != LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST) { + message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE)); + return LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE; + } + + /* create LibAuthnResponse */ + LASSO_PROFILE(login)->response = lasso_lib_authn_response_new( + LASSO_PROVIDER(LASSO_PROFILE(login)->server)->ProviderID, + LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)); + + /* if signature is not OK => modify AuthnResponse StatusCode */ + if (LASSO_PROFILE(login)->signature_status == LASSO_DS_ERROR_INVALID_SIGNATURE || + LASSO_PROFILE(login)->signature_status == LASSO_DS_ERROR_SIGNATURE_NOT_FOUND) { + switch (LASSO_PROFILE(login)->signature_status) { + case LASSO_DS_ERROR_INVALID_SIGNATURE: + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_LIB_STATUS_CODE_INVALID_SIGNATURE); + break; + case LASSO_DS_ERROR_SIGNATURE_NOT_FOUND: /* Unsigned AuthnRequest */ + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_LIB_STATUS_CODE_UNSIGNED_AUTHN_REQUEST); + break; + } + /* ret = LASSO_PROFILE(login)->signature_status; */ + } else { + /* modify AuthnResponse StatusCode if user authentication is not OK */ + if (authentication_result == FALSE) { + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_SAML_STATUS_CODE_REQUEST_DENIED); + } + + if (LASSO_PROFILE(login)->signature_status == 0 && authentication_result == TRUE) { + /* process federation */ + ret = lasso_login_process_federation(login, is_consent_obtained); + /* fill the response with the assertion */ + if (ret == 0) { + federation = g_hash_table_lookup( + LASSO_PROFILE(login)->identity->federations, + LASSO_PROFILE(login)->remote_providerID); + lasso_login_build_assertion(login, + federation, + authenticationMethod, + authenticationInstant, + reauthenticateOnOrAfter, + notBefore, + notOnOrAfter); + } + else if (ret < 0) { + return ret; + } + } + } + + if (LASSO_SAMLP_RESPONSE(LASSO_PROFILE(login)->response)->Status == NULL) { + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_SAML_STATUS_CODE_SUCCESS); + } + + remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, + LASSO_PROFILE(login)->remote_providerID); + /* build an lib:AuthnResponse base64 encoded */ + LASSO_PROFILE(login)->msg_body = lasso_node_export_to_base64(LASSO_PROFILE(login)->response); + LASSO_PROFILE(login)->msg_url = lasso_provider_get_metadata_one( + remote_provider, "AssertionConsumerServiceURL"); + return ret; - } - } - } - - remote_provider = lasso_server_get_provider_ref(LASSO_PROFILE(login)->server, - LASSO_PROFILE(login)->remote_providerID, - NULL); - /* build an lib:AuthnResponse base64 encoded */ - LASSO_PROFILE(login)->msg_body = lasso_node_export_to_base64(LASSO_PROFILE(login)->response); - LASSO_PROFILE(login)->msg_url = lasso_provider_get_assertionConsumerServiceURL(remote_provider, - lassoProviderTypeSp, - NULL); - - return ret; } /** @@ -867,37 +792,39 @@ lasso_login_build_authn_response_msg(LassoLogin *login, gint lasso_login_build_request_msg(LassoLogin *login) { - LassoProvider *remote_provider; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - /* sign request */ - ret= lasso_samlp_request_abstract_sign_signature_tmpl(LASSO_SAMLP_REQUEST_ABSTRACT(LASSO_PROFILE(login)->request), - LASSO_PROFILE(login)->server->private_key, - LASSO_PROFILE(login)->server->certificate); - LASSO_PROFILE(login)->msg_body = lasso_node_export_to_soap(LASSO_PROFILE(login)->request); - - /* get msg_url (SOAP Endpoint) */ - remote_provider = lasso_server_get_provider_ref(LASSO_PROFILE(login)->server, - LASSO_PROFILE(login)->remote_providerID, - &err); - if (err != NULL) { - goto done; - } - LASSO_PROFILE(login)->msg_url = lasso_provider_get_soapEndpoint(remote_provider, - lassoProviderTypeIdp, &err); - if (err != NULL) { - goto done; - } - return 0; - - done: - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - return ret; + LassoProvider *remote_provider; + gint ret = 0; + GError *err = NULL; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + /* sign request */ +#if 0 /* XXX: signatures are done differently */ + ret = lasso_samlp_request_abstract_sign_signature_tmpl( + LASSO_SAMLP_REQUEST_ABSTRACT(LASSO_PROFILE(login)->request), + LASSO_PROFILE(login)->server->private_key, + LASSO_PROFILE(login)->server->certificate); +#endif + LASSO_PROFILE(login)->msg_body = lasso_node_export_to_soap(LASSO_PROFILE(login)->request); + + /* get msg_url (SOAP Endpoint) */ + remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, + LASSO_PROFILE(login)->remote_providerID); + if (err != NULL) { + goto done; + } + LASSO_PROFILE(login)->msg_url = lasso_provider_get_metadata_one( + remote_provider, "SoapEndpoint"); + if (err != NULL) { + goto done; + } + return 0; + +done: + message(G_LOG_LEVEL_CRITICAL, err->message); + ret = err->code; + g_error_free(err); + return ret; } /** @@ -910,57 +837,50 @@ lasso_login_build_request_msg(LassoLogin *login) * Return value: 0 on success or a negative value if an **/ gint -lasso_login_build_response_msg(LassoLogin *login, - gchar *remote_providerID) +lasso_login_build_response_msg(LassoLogin *login, gchar *remote_providerID) { - LassoProvider *remote_provider; - LassoNode *assertion; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), -1); - - LASSO_PROFILE(login)->response = lasso_response_new(); - - if (remote_providerID != NULL) { - LASSO_PROFILE(login)->remote_providerID = g_strdup(remote_providerID); - remote_provider = lasso_server_get_provider_ref(LASSO_PROFILE(login)->server, - LASSO_PROFILE(login)->remote_providerID, - NULL); - /* FIXME verify the SOAP request signature */ - ret = lasso_node_verify_signature(LASSO_PROFILE(login)->request, - remote_provider->public_key, - remote_provider->ca_cert_chain); - /* changed status code into RequestDenied - if signature is invalid or not found - if an error occurs during verification */ - if (ret != 0) { - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoSamlStatusCodeRequestDenied); - } - - if (LASSO_PROFILE(login)->session) { - /* get assertion in session and add it in response */ - assertion = lasso_session_get_assertion(LASSO_PROFILE(login)->session, - LASSO_PROFILE(login)->remote_providerID); - if (assertion != NULL) { - lasso_samlp_response_add_assertion(LASSO_SAMLP_RESPONSE(LASSO_PROFILE(login)->response), - assertion); - lasso_node_destroy(assertion); - } - else { - /* FIXME should this message output by lasso_session_get_assertion () ? */ - message(G_LOG_LEVEL_CRITICAL, "Assertion not found in session\n"); - } - } - } - else { - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoSamlStatusCodeRequestDenied); - } - - LASSO_PROFILE(login)->msg_body = lasso_node_export_to_soap(LASSO_PROFILE(login)->response); - - return ret; + LassoProvider *remote_provider; + LassoSamlAssertion *assertion; + gint ret = 0; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), -1); + + LASSO_PROFILE(login)->response = lasso_samlp_response_new(); + + if (remote_providerID != NULL) { + LASSO_PROFILE(login)->remote_providerID = g_strdup(remote_providerID); + remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, + LASSO_PROFILE(login)->remote_providerID); + /* FIXME verify the SOAP request signature */ + ret = lasso_node_verify_signature(LASSO_PROFILE(login)->request, + remote_provider->public_key, + remote_provider->ca_cert_chain); + /* changed status code into RequestDenied + if signature is invalid or not found + if an error occurs during verification */ + if (ret != 0) { + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_SAML_STATUS_CODE_REQUEST_DENIED); + } + + if (LASSO_PROFILE(login)->session) { + /* get assertion in session and add it in response */ + assertion = lasso_session_get_assertion(LASSO_PROFILE(login)->session, + LASSO_PROFILE(login)->remote_providerID); + LASSO_SAMLP_RESPONSE(LASSO_PROFILE(login)->response)->Assertion = assertion; + if (assertion == NULL) { + /* FIXME should this message output by lasso_session_get_assertion () ? */ + message(G_LOG_LEVEL_CRITICAL, "Assertion not found in session\n"); + } + } + } else { + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_SAML_STATUS_CODE_REQUEST_DENIED); + } + + LASSO_PROFILE(login)->msg_body = lasso_node_export_to_soap(LASSO_PROFILE(login)->response); + + return ret; } /** @@ -972,136 +892,129 @@ lasso_login_build_response_msg(LassoLogin *login, void lasso_login_destroy(LassoLogin *login) { - g_object_unref(G_OBJECT(login)); + g_object_unref(G_OBJECT(login)); } -/** - * lasso_login_dump: - * @login: a login object - * - * Dumps the login object in an XML string. - * - * Return value: a newly allocated string orgative value if an error occurs. - **/ -gchar* -lasso_login_dump(LassoLogin *login) +gint +lasso_login_init_authn_request(LassoLogin *login, lassoHttpMethod http_method) { - LassoNode *node; - gchar *parent_dump, *dump; - gchar protocolProfile[6], http_method[6]; + LassoLibAuthnRequest *request; - g_return_val_if_fail(LASSO_IS_LOGIN(login), NULL); + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - parent_dump = lasso_profile_dump(LASSO_PROFILE(login), "Login"); - node = lasso_node_new_from_dump(parent_dump); - g_free(parent_dump); + if (http_method != LASSO_HTTP_METHOD_REDIRECT && http_method != LASSO_HTTP_METHOD_POST) { + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); + return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; + } - g_snprintf(protocolProfile, 6, "%d", login->protocolProfile); - LASSO_NODE_GET_CLASS(node)->new_child(node, "ProtocolProfile", protocolProfile, FALSE); + login->http_method = http_method; - if (login->assertionArtifact != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "AssertionArtifact", login->assertionArtifact, FALSE); - } - dump = lasso_node_export(node); - lasso_node_destroy(node); + /* XXX: should be moved somehow in samlp_request_abstract.c */ + request = lasso_lib_authn_request_new(); + LASSO_SAMLP_REQUEST_ABSTRACT(request)->RequestID = lasso_build_unique_id(32); + LASSO_SAMLP_REQUEST_ABSTRACT(request)->MajorVersion = LASSO_LIB_MAJOR_VERSION_N; + LASSO_SAMLP_REQUEST_ABSTRACT(request)->MinorVersion = LASSO_LIB_MINOR_VERSION_N; + LASSO_SAMLP_REQUEST_ABSTRACT(request)->IssueInstant = lasso_get_current_time(); + request->ProviderID = g_strdup(LASSO_PROVIDER(LASSO_PROFILE(login)->server)->ProviderID); - return dump; -} + if (http_method == LASSO_HTTP_METHOD_POST) { + /* XXX: if post sign_type/sign_method + LASSO_SIGNATURE_TYPE_WITHX509, + LASSO_SIGNATURE_METHOD_RSA_SHA1); + */ + } -gint -lasso_login_init_authn_request(LassoLogin *login, - lassoHttpMethod http_method) -{ - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - if (http_method != lassoHttpMethodRedirect && http_method != lassoHttpMethodPost) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - } - - login->http_method = http_method; - - if (http_method == lassoHttpMethodPost) { - LASSO_PROFILE(login)->request = lasso_authn_request_new(LASSO_PROFILE(login)->server->providerID, - lassoSignatureTypeWithX509, - lassoSignatureMethodRsaSha1); - } - else { - LASSO_PROFILE(login)->request = lasso_authn_request_new(LASSO_PROFILE(login)->server->providerID, - lassoSignatureTypeNone, - 0); - } - - if (LASSO_PROFILE(login)->request == NULL) { - return -2; - } - - LASSO_PROFILE(login)->request_type = lassoMessageTypeAuthnRequest; - - return 0; + LASSO_PROFILE(login)->request = LASSO_NODE(request); + + if (LASSO_PROFILE(login)->request == NULL) { + return -2; + } + + return 0; } gint -lasso_login_init_request(LassoLogin *login, - gchar *response_msg, - lassoHttpMethod response_http_method) +lasso_login_init_request(LassoLogin *login, gchar *response_msg, + lassoHttpMethod response_http_method) { - LassoNode *response = NULL; - xmlChar *artifact, *b64_identityProviderSuccinctID; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - - /* rebuild response (artifact) */ - switch (response_http_method) { - case lassoHttpMethodRedirect: - /* artifact by REDIRECT */ - response = lasso_artifact_new_from_query(response_msg); - break; - case lassoHttpMethodPost: - /* artifact by POST */ - response = lasso_artifact_new_from_lares(response_msg, NULL); - break; - default: - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - } - LASSO_PROFILE(login)->response = response; - LASSO_PROFILE(login)->response_type = lassoMessageTypeArtifact; - - /* get remote identityProviderSuccinctID */ - b64_identityProviderSuccinctID = lasso_artifact_get_b64IdentityProviderSuccinctID(LASSO_ARTIFACT(response), &err); - if (b64_identityProviderSuccinctID != NULL) { - LASSO_PROFILE(login)->remote_providerID = lasso_server_get_providerID_from_hash(LASSO_PROFILE(login)->server, - b64_identityProviderSuccinctID); - xmlFree(b64_identityProviderSuccinctID); - } - else { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_clear_error(&err); - } - - /* create SamlpRequest */ - artifact = lasso_artifact_get_samlArt(LASSO_ARTIFACT(LASSO_PROFILE(login)->response), &err); - if (artifact != NULL) { - LASSO_PROFILE(login)->request = lasso_request_new(artifact); - LASSO_PROFILE(login)->request_type = lassoMessageTypeRequest; - xmlFree(artifact); - } - else { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_clear_error(&err); - } - - return ret; + char **query_fields; + gint ret = 0; + int i; + char *artifact_b64, *provider_succint_id_b64; + char provider_succint_id[21], assertion_handle[21]; + char artifact[43]; + LassoSamlpRequestAbstract *request; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + + /* rebuild response (artifact) */ + switch (response_http_method) { + case LASSO_HTTP_METHOD_REDIRECT: /* artifact by REDIRECT */ + query_fields = urlencoded_to_strings(response_msg); + for (i=0; query_fields[i]; i++) { + if (strncmp(query_fields[i], "SAMLart=", 8) != 0) { + free(query_fields[i]); + continue; + } + artifact_b64 = strdup(query_fields[i]+8); + free(query_fields[i]); + } + free(query_fields); + break; + case LASSO_HTTP_METHOD_POST: + /* artifact by POST */ + g_assert_not_reached(); + /* XXX: artifact code should be moved in this file + response = lasso_artifact_new_from_lares(response_msg, NULL); + */ + break; + default: + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); + return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; + } + + i = xmlSecBase64Decode(artifact_b64, artifact, 43); + if (i < 0 || i > 42) { + free(artifact_b64); + return -1; + } + + if (artifact[0] != 0 || artifact[1] != 3) { /* wrong type code */ + free(artifact_b64); + return -1; + } + + memcpy(provider_succint_id, artifact+2, 20); + provider_succint_id[20] = 0; + memcpy(assertion_handle, artifact+22, 20); + assertion_handle[20] = 0; + + provider_succint_id_b64 = xmlSecBase64Encode(provider_succint_id, 20, 0); + + LASSO_PROFILE(login)->remote_providerID = lasso_server_get_providerID_from_hash( + LASSO_PROFILE(login)->server, provider_succint_id_b64); + xmlFree(provider_succint_id_b64); + + request = LASSO_SAMLP_REQUEST_ABSTRACT(g_object_new(LASSO_TYPE_SAMLP_REQUEST, NULL)); + request->RequestID = lasso_build_unique_id(32); + request->MajorVersion = LASSO_LIB_MAJOR_VERSION_N; + request->MinorVersion = LASSO_LIB_MINOR_VERSION_N; + request->IssueInstant = lasso_get_current_time(); + + LASSO_SAMLP_REQUEST(request)->AssertionArtifact = artifact_b64; + + LASSO_PROFILE(login)->request = LASSO_NODE(request); + + + return ret; } /** - * lasso_login_init_self_addressed_authn_request: + * lasso_login_init_idp_initiated_authn_request: * @login: a LassoLogin. * @remote_providerID: the providerID of the remote service provider (may be NULL). * @@ -1113,39 +1026,41 @@ lasso_login_init_request(LassoLogin *login, * Return value: 0 on success and a negative value if an error occurs. **/ gint -lasso_login_init_self_addressed_authn_request(LassoLogin *login, - const gchar *remote_providerID) +lasso_login_init_idp_initiated_authn_request(LassoLogin *login, + const gchar *remote_providerID) { - LassoNode *request; - gchar *first_providerID; - gint ret = 0; + LassoLibAuthnRequest *request; + gchar *first_providerID; + gint ret = 0; - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - /* if remote_providerID is NULL, get first providerID in server */ + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + /* if remote_providerID is NULL, get first providerID in server */ - /* store providerID of the service provider */ - if (remote_providerID == NULL) { - first_providerID = lasso_server_get_first_providerID(LASSO_PROFILE(login)->server); - LASSO_PROFILE(login)->remote_providerID = first_providerID; - } - else { - LASSO_PROFILE(login)->remote_providerID = g_strdup(remote_providerID); - } + /* store providerID of the service provider */ + if (remote_providerID == NULL) { + first_providerID = lasso_server_get_first_providerID(LASSO_PROFILE(login)->server); + LASSO_PROFILE(login)->remote_providerID = first_providerID; + } + else { + LASSO_PROFILE(login)->remote_providerID = g_strdup(remote_providerID); + } - /* build self-addressed lib:AuthnRequest */ - request = lasso_authn_request_new(LASSO_PROFILE(login)->remote_providerID, - lassoSignatureTypeNone, 0); + /* build self-addressed lib:AuthnRequest */ + request = lasso_lib_authn_request_new(); /* XXX */ + LASSO_SAMLP_REQUEST_ABSTRACT(request)->RequestID = lasso_build_unique_id(32); + LASSO_SAMLP_REQUEST_ABSTRACT(request)->MajorVersion = LASSO_LIB_MAJOR_VERSION_N; + LASSO_SAMLP_REQUEST_ABSTRACT(request)->MinorVersion = LASSO_LIB_MINOR_VERSION_N; + LASSO_SAMLP_REQUEST_ABSTRACT(request)->IssueInstant = lasso_get_current_time(); + request->ProviderID = g_strdup(LASSO_PROFILE(login)->remote_providerID); - lasso_lib_authn_request_set_nameIDPolicy(LASSO_LIB_AUTHN_REQUEST(request), - lassoLibNameIDPolicyTypeAny); + request->NameIDPolicy = LASSO_LIB_NAMEID_POLICY_TYPE_ANY; - /* remove RequestID attribute else it would be used in response assertion */ - xmlRemoveProp((xmlAttrPtr)lasso_node_get_attr(request, "RequestID", NULL)); + /* remove RequestID attribute else it would be used in response assertion */ + LASSO_SAMLP_REQUEST_ABSTRACT(LASSO_PROFILE(login)->request)->RequestID = NULL; - LASSO_PROFILE(login)->request = request; - LASSO_PROFILE(login)->request_type = lassoMessageTypeAuthnRequest; + LASSO_PROFILE(login)->request = LASSO_NODE(request); - return ret; + return ret; } /** @@ -1159,26 +1074,12 @@ lasso_login_init_self_addressed_authn_request(LassoLogin *login, gboolean lasso_login_must_ask_for_consent(LassoLogin *login) { - xmlChar *content; - gboolean isPassive = TRUE; /* default value */ - gboolean ret = lasso_login_must_ask_for_consent_private(login); - - /* if must_ask_for_consent = TRUE we must return FALSE if isPassive is TRUE */ - if (ret == TRUE) { - content = lasso_node_get_child_content(LASSO_PROFILE(login)->request, "IsPassive", - NULL, NULL); - if (content != NULL) { - if (xmlStrEqual(content, "false") || xmlStrEqual(content, "0")) { - isPassive = FALSE; - } - xmlFree(content); - } - if (isPassive == TRUE) { - ret = FALSE; - } - } - - return ret; + if (lasso_login_must_ask_for_consent_private(login)) { + if (LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)->IsPassive) + return FALSE; + return TRUE; + } + return FALSE; } /** @@ -1192,456 +1093,357 @@ lasso_login_must_ask_for_consent(LassoLogin *login) gboolean lasso_login_must_authenticate(LassoLogin *login) { - gboolean must_authenticate = FALSE; - gboolean isPassive = TRUE; - gboolean forceAuthn = FALSE; - gchar *str; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - /* verify if the user must be authenticated or not */ - - /* get IsPassive and ForceAuthn in AuthnRequest if exists */ - if (LASSO_PROFILE(login)->request != NULL) { - str = lasso_node_get_child_content(LASSO_PROFILE(login)->request, "IsPassive", - NULL, NULL); - if (str != NULL) { - if (xmlStrEqual(str, "false") || xmlStrEqual(str, "0")) { - isPassive = FALSE; - } - xmlFree(str); - } - - str = lasso_node_get_child_content(LASSO_PROFILE(login)->request, "ForceAuthn", - NULL, NULL); - if (str != NULL) { - if (xmlStrEqual(str, "true") || xmlStrEqual(str, "1")) { - forceAuthn = TRUE; - } - xmlFree(str); - } - } - - if ((forceAuthn == TRUE || LASSO_PROFILE(login)->session == NULL) && isPassive == FALSE) { - must_authenticate = TRUE; - } - else if (LASSO_PROFILE(login)->identity == NULL && \ - isPassive == TRUE && \ - login->protocolProfile == lassoLoginProtocolProfileBrwsPost) { - lasso_profile_set_response_status(LASSO_PROFILE(login), - lassoLibStatusCodeNoPassive); - } - - return must_authenticate; + gboolean must_authenticate = FALSE; + LassoLibAuthnRequest *request; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + request = LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request); + + /* verify if the user must be authenticated or not */ + + /* get IsPassive and ForceAuthn in AuthnRequest if exists */ + + if ((request->ForceAuthn || LASSO_PROFILE(login)->session == NULL) && \ + request->IsPassive == FALSE) { + must_authenticate = TRUE; + } + else if (LASSO_PROFILE(login)->identity == NULL && \ + request->IsPassive && \ + login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST) { + lasso_profile_set_response_status(LASSO_PROFILE(login), + LASSO_LIB_STATUS_CODE_NO_PASSIVE); + } + + return must_authenticate; } gint -lasso_login_process_authn_request_msg(LassoLogin *login, - gchar *authn_request_msg, - lassoHttpMethod authn_request_http_method) +lasso_login_process_authn_request_msg(LassoLogin *login, gchar *authn_request_msg) { - LassoProvider *remote_provider; - gchar *protocolProfile; - xmlChar *md_authnRequestsSigned; - gboolean must_verify_signature = FALSE; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail((authn_request_msg != NULL - || authn_request_http_method == lassoHttpMethodSelfAddressed) - && (authn_request_msg == NULL - || authn_request_http_method != lassoHttpMethodSelfAddressed), - LASSO_PARAM_ERROR_INVALID_VALUE); - - /* rebuild request */ - switch (authn_request_http_method) { - case lassoHttpMethodSelfAddressed: - /* LibAuthnRequest already set by lasso_login_build_self_addressed_authn_request. */ - if (LASSO_PROFILE(login)->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_MISSING_REQUEST)); - return LASSO_PROFILE_ERROR_MISSING_REQUEST; - } - break; - case lassoHttpMethodRedirect: - /* LibAuthnRequest sent by GET method */ - LASSO_PROFILE(login)->request = lasso_authn_request_new_from_export(authn_request_msg, - lassoNodeExportTypeQuery); - if (LASSO_PROFILE(login)->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_QUERY)); - return LASSO_PROFILE_ERROR_INVALID_QUERY; - } - break; - case lassoHttpMethodPost: - /* LibAuthnRequest sent by POST method */ - LASSO_PROFILE(login)->request = lasso_authn_request_new_from_export(authn_request_msg, - lassoNodeExportTypeBase64); - if (LASSO_PROFILE(login)->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_POST_MSG)); - return LASSO_PROFILE_ERROR_INVALID_POST_MSG; - } - break; - case lassoHttpMethodSoap: - /* LibAuthnRequest sent by SOAP method - useful only for LECP */ - LASSO_PROFILE(login)->request = lasso_authn_request_new_from_export(authn_request_msg, - lassoNodeExportTypeSoap); - if (LASSO_PROFILE(login)->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG)); - return LASSO_PROFILE_ERROR_INVALID_SOAP_MSG; - } - default: - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - } - - LASSO_PROFILE(login)->request_type = lassoMessageTypeAuthnRequest; - - /* get ProtocolProfile in lib:AuthnRequest */ - protocolProfile = lasso_node_get_child_content(LASSO_PROFILE(login)->request, - "ProtocolProfile", NULL, NULL); - if (protocolProfile == NULL || xmlStrEqual(protocolProfile, lassoLibProtocolProfileBrwsArt)) { - login->protocolProfile = lassoLoginProtocolProfileBrwsArt; - } - else if (xmlStrEqual(protocolProfile, lassoLibProtocolProfileBrwsPost)) { - login->protocolProfile = lassoLoginProtocolProfileBrwsPost; - } - else { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE)); - xmlFree(protocolProfile); - return LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE; - } - xmlFree(protocolProfile); - - /* get remote ProviderID */ - LASSO_PROFILE(login)->remote_providerID = lasso_node_get_child_content(LASSO_PROFILE(login)->request, - "ProviderID", NULL, NULL); - - /* Check authnRequest signature. */ - if (authn_request_http_method != lassoHttpMethodSelfAddressed) { - remote_provider = lasso_server_get_provider_ref(LASSO_PROFILE(login)->server, - LASSO_PROFILE(login)->remote_providerID, - &err); - if (remote_provider != NULL) { - /* Is authnRequest signed ? */ - md_authnRequestsSigned = lasso_provider_get_authnRequestsSigned(remote_provider, &err); - if (md_authnRequestsSigned != NULL) { - must_verify_signature = xmlStrEqual(md_authnRequestsSigned, "true"); - xmlFree(md_authnRequestsSigned); - } - else { - /* AuthnRequestsSigned element is required */ - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); + lassoHttpMethod authn_request_http_method; /* XXX update to current CVS code */ + LassoProvider *remote_provider; + gchar *protocolProfile; + xmlChar *md_authnRequestsSigned; + gboolean must_verify_signature = FALSE; + gint ret = 0; + LassoLibAuthnRequest *request; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + if (authn_request_msg == NULL) { + authn_request_http_method = LASSO_HTTP_METHOD_IDP_INITIATED; + if (LASSO_PROFILE(login)->request == NULL) { + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_PROFILE_ERROR_MISSING_REQUEST)); + return LASSO_PROFILE_ERROR_MISSING_REQUEST; + } + + /* LibAuthnRequest already set by lasso_login_init_idp_initiated_authn_request() */ + request = LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request); + + /* verify that NameIDPolicy is 'any' */ + if (request->NameIDPolicy == NULL) + return LASSO_LOGIN_ERROR_INVALID_NAMEIDPOLICY; + + if (strcmp(request->NameIDPolicy, LASSO_LIB_NAMEID_POLICY_TYPE_ANY) != 0) + return LASSO_LOGIN_ERROR_INVALID_NAMEIDPOLICY; + } else { + request = lasso_lib_authn_request_new(); + lasso_node_init_from_message(LASSO_NODE(request), authn_request_msg); + + LASSO_PROFILE(login)->request = LASSO_NODE(request); + } + + + /* get ProtocolProfile in lib:AuthnRequest */ + protocolProfile = LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)->ProtocolProfile; + if (protocolProfile == NULL || + xmlStrEqual(protocolProfile, LASSO_LIB_PROTOCOL_PROFILE_BRWS_ART)) { + login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART; + } + else if (xmlStrEqual(protocolProfile, LASSO_LIB_PROTOCOL_PROFILE_BRWS_POST)) { + login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST; + } + else { + message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE)); + return LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE; + } + + /* get remote ProviderID */ + LASSO_PROFILE(login)->remote_providerID = g_strdup( + LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)->ProviderID); + + /* Check authnRequest signature. */ + if (authn_request_http_method != LASSO_HTTP_METHOD_IDP_INITIATED) { + remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, + LASSO_PROFILE(login)->remote_providerID); + if (remote_provider != NULL) { + /* Is authnRequest signed ? */ + md_authnRequestsSigned = lasso_provider_get_metadata_one( + remote_provider, "AuthnRequestsSigned"); + if (md_authnRequestsSigned != NULL) { + must_verify_signature = xmlStrEqual(md_authnRequestsSigned, "true"); + g_free(md_authnRequestsSigned); + } else { + /* AuthnRequestsSigned element is required */ + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + } else { + message(G_LOG_LEVEL_CRITICAL, "Must sign without knowing provider"); + return -1; + } + + /* verify request signature */ + if (must_verify_signature) { + ret = lasso_provider_verify_signature(remote_provider, + authn_request_msg, "RequestID"); + LASSO_PROFILE(login)->signature_status = ret; + } + } + return ret; - } - } - else { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - return ret; - } - - /* verify request signature */ - if (must_verify_signature) { - switch (authn_request_http_method) { - case lassoHttpMethodRedirect: - ret = lasso_query_verify_signature(authn_request_msg, - remote_provider->public_key, - LASSO_PROFILE(login)->server->private_key); - break; - case lassoHttpMethodPost: - case lassoHttpMethodSoap: - /* FIXME detect X509Data ? */ - ret = lasso_node_verify_signature(LASSO_PROFILE(login)->request, - remote_provider->public_key, - remote_provider->ca_cert_chain); - break; - } - LASSO_PROFILE(login)->signature_status = ret; - } - } - - return ret; } gint -lasso_login_process_authn_response_msg(LassoLogin *login, - gchar *authn_response_msg) +lasso_login_process_authn_response_msg(LassoLogin *login, gchar *authn_response_msg) { - gint ret1 = 0, ret2 = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(authn_response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - - LASSO_PROFILE(login)->response = lasso_authn_response_new_from_export(authn_response_msg, - lassoNodeExportTypeBase64); - LASSO_PROFILE(login)->response_type = lassoMessageTypeAuthnResponse; - - LASSO_PROFILE(login)->remote_providerID = lasso_node_get_child_content(LASSO_PROFILE(login)->response, - "ProviderID", - lassoLibHRef, - &err); - if (LASSO_PROFILE(login)->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret1 = err->code; - g_error_free(err); - } - - LASSO_PROFILE(login)->msg_relayState = lasso_node_get_child_content(LASSO_PROFILE(login)->response, - "RelayState", - lassoLibHRef, - NULL); - - ret2 = lasso_login_process_response_status_and_assertion(login); - - return ret2 == 0 ? ret1 : ret2; + gint ret1 = 0, ret2 = 0; + + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(authn_response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + + LASSO_PROFILE(login)->response = lasso_lib_authn_response_new(NULL, NULL); + lasso_node_init_from_message(LASSO_PROFILE(login)->response, authn_response_msg); + + LASSO_PROFILE(login)->remote_providerID = g_strdup( + LASSO_LIB_AUTHN_RESPONSE(LASSO_PROFILE(login)->response)->ProviderID); + + if (LASSO_PROFILE(login)->remote_providerID == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + } + + LASSO_PROFILE(login)->msg_relayState = g_strdup(LASSO_LIB_AUTHN_RESPONSE( + LASSO_PROFILE(login)->response)->RelayState); + + ret2 = lasso_login_process_response_status_and_assertion(login); + + return ret2 == 0 ? ret1 : ret2; } gint -lasso_login_process_request_msg(LassoLogin *login, - gchar *request_msg) +lasso_login_process_request_msg(LassoLogin *login, gchar *request_msg) { - gint ret = 0; - GError *err = NULL; - - 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); - - /* rebuild samlp:Request with request_msg */ - LASSO_PROFILE(login)->request = lasso_request_new_from_export(request_msg, - lassoNodeExportTypeSoap); - if (LASSO_PROFILE(login)->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Failed to rebuild samlp:Request with request message.\n"); - return LASSO_ERROR_UNDEFINED; - } - LASSO_PROFILE(login)->request_type = lassoMessageTypeRequest; - - /* get AssertionArtifact */ - login->assertionArtifact = lasso_node_get_child_content(LASSO_PROFILE(login)->request, - "AssertionArtifact", - lassoSamlProtocolHRef, &err); - if (err != NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - } - - return ret; + gint ret = 0; + LassoProfile *profile = LASSO_PROFILE(login); + + 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); + + /* rebuild samlp:Request with request_msg */ + profile->request = lasso_node_new_from_soap(request_msg); + /* XXX was: lasso_request_new_from_export(request_msg, LASSO_NODE_EXPORT_TYPE_SOAP); */ + if (profile->request == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Failed to rebuild samlp:Request with request message.\n"); + return LASSO_ERROR_UNDEFINED; + } + /* get AssertionArtifact */ + login->assertionArtifact = LASSO_SAMLP_REQUEST(profile->request)->AssertionArtifact; + + return ret; } gint -lasso_login_process_response_msg(LassoLogin *login, - gchar *response_msg) +lasso_login_process_response_msg(LassoLogin *login, gchar *response_msg) { - g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - - /* rebuild samlp:Response with response_msg */ - LASSO_PROFILE(login)->response = lasso_response_new_from_export(response_msg, - lassoNodeExportTypeSoap); - if (LASSO_PROFILE(login)->response == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Failed to rebuild samlp:Response with response message.\n"); - return LASSO_ERROR_UNDEFINED; - } - LASSO_PROFILE(login)->response_type = lassoMessageTypeResponse; - - return lasso_login_process_response_status_and_assertion(login); + g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + + /* rebuild samlp:Response with response_msg */ + LASSO_PROFILE(login)->response = lasso_node_new_from_soap(response_msg); + if (! LASSO_IS_SAMLP_RESPONSE(LASSO_PROFILE(login)->response) ) { + LASSO_PROFILE(login)->response = NULL; + message(G_LOG_LEVEL_CRITICAL, "Failed to rebuild samlp:Response from message."); + return LASSO_ERROR_UNDEFINED; + } + + return lasso_login_process_response_status_and_assertion(login); } /*****************************************************************************/ -/* overrided parent class methods */ +/* private methods */ /*****************************************************************************/ -static void -lasso_login_dispose(LassoLogin *login) +static LassoNodeClass *parent_class = NULL; + +static xmlNode* +get_xmlNode(LassoNode *node) { - if (login->private->dispose_has_run == TRUE) { - return; - } - login->private->dispose_has_run = TRUE; + xmlNode *xmlnode; + LassoLogin *login = LASSO_LOGIN(node); + + xmlnode = parent_class->get_xmlNode(node); + xmlNodeSetName(xmlnode, "Login"); + xmlSetProp(xmlnode, "LoginDumpVersion", "2"); - debug("Login object 0x%x disposed ...\n", login); + if (login->assertionArtifact) + xmlNewTextChild(xmlnode, NULL, "AssertionArtifact", login->assertionArtifact); - /* unref reference counted objects */ + if (login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART) + xmlNewTextChild(xmlnode, NULL, "ProtocolProfile", "Artifact"); + if (login->protocolProfile == LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST) + xmlNewTextChild(xmlnode, NULL, "ProtocolProfile", "POST"); - parent_class->dispose(G_OBJECT(login)); + if (login->nameIDPolicy) + xmlNewTextChild(xmlnode, NULL, "NameIDPolicy", login->nameIDPolicy); + + return xmlnode; } static void -lasso_login_finalize(LassoLogin *login) -{ - debug("Login object 0x%x finalized ...\n", login); +init_from_xml(LassoNode *node, xmlNode *xmlnode) +{ + LassoLogin *login = LASSO_LOGIN(node); + xmlNode *t; + + parent_class->init_from_xml(node, xmlnode); + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + if (strcmp(t->name, "AssertionArtifact") == 0) + login->assertionArtifact = xmlNodeGetContent(t); + if (strcmp(t->name, "NameIDPolicy") == 0) + login->nameIDPolicy = xmlNodeGetContent(t); + if (strcmp(t->name, "ProtocolProfile") == 0) { + char *s; + s = xmlNodeGetContent(t); + if (strcmp(s, "Artifact") == 0) + login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART; + if (strcmp(s, "POST") == 0) + login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST; + xmlFree(s); + } + t = t->next; + } +} - g_free(login->assertionArtifact); +/*****************************************************************************/ +/* overrided parent class methods */ +/*****************************************************************************/ - g_free (login->private); +static void +dispose(GObject *object) +{ + LassoLogin *login = LASSO_LOGIN(object); + + if (login->private->dispose_has_run == TRUE) { + return; + } + login->private->dispose_has_run = TRUE; - parent_class->finalize(G_OBJECT(login)); + debug("Login object 0x%x disposed ...\n", login); + + /* unref reference counted objects */ + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + +static void +finalize(GObject *object) +{ + LassoLogin *login = LASSO_LOGIN(object); + + debug("Login object 0x%x finalized ...\n", login); + g_free(login->assertionArtifact); + g_free(login->private); + G_OBJECT_CLASS(parent_class)->finalize(object); } /*****************************************************************************/ -/* instance and class init functions */ +/* instance and class init functions */ /*****************************************************************************/ static void -lasso_login_instance_init(GTypeInstance *instance, - gpointer g_class) +instance_init(LassoLogin *login) { - LassoLogin *login = LASSO_LOGIN(instance); - - login->private = g_new (LassoLoginPrivate, 1); - login->private->dispose_has_run = FALSE; + login->private = g_new (LassoLoginPrivate, 1); + login->private->dispose_has_run = FALSE; - login->protocolProfile = 0; - login->assertionArtifact = NULL; + login->protocolProfile = 0; + login->assertionArtifact = NULL; } static void -lasso_login_class_init(LassoLoginClass *class) +class_init(LassoLoginClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - /* override parent class methods */ - gobject_class->dispose = (void *)lasso_login_dispose; - gobject_class->finalize = (void *)lasso_login_finalize; + parent_class = g_type_class_peek_parent(klass); + + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; } -GType lasso_login_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoLoginClass), - NULL, - NULL, - (GClassInitFunc) lasso_login_class_init, - NULL, - NULL, - sizeof(LassoLogin), - 0, - (GInstanceInitFunc) lasso_login_instance_init, - }; - - this_type = g_type_register_static(LASSO_TYPE_PROFILE, - "LassoLogin", - &this_info, 0); - } - return this_type; +GType +lasso_login_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof(LassoLoginClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoLogin), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_PROFILE, + "LassoLogin", &this_info, 0); + } + return this_type; } LassoLogin* lasso_login_new(LassoServer *server) { - LassoLogin *login; + LassoLogin *login = NULL; - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); + g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - login = LASSO_LOGIN(g_object_new(LASSO_TYPE_LOGIN, - "server", lasso_server_copy(server), - NULL)); - - return login; + login = g_object_new(LASSO_TYPE_LOGIN, NULL); + LASSO_PROFILE(login)->server = server; + + return login; } LassoLogin* -lasso_login_new_from_dump(LassoServer *server, - gchar *dump) +lasso_login_new_from_dump(LassoServer *server, const gchar *dump) { - LassoLogin *login; - LassoNode *node_dump, *request_node = NULL, *response_node = NULL; - gchar *protocolProfile, *export, *type; - - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - g_return_val_if_fail(dump != NULL, NULL); - - login = LASSO_LOGIN(g_object_new(LASSO_TYPE_LOGIN, - "server", lasso_server_copy(server), - NULL)); - - node_dump = lasso_node_new_from_dump(dump); - - /* profile attributes */ - LASSO_PROFILE(login)->nameIdentifier = lasso_node_get_child_content(node_dump, "NameIdentifier", - lassoLassoHRef, NULL); - LASSO_PROFILE(login)->remote_providerID = lasso_node_get_child_content(node_dump, "RemoteProviderID", - lassoLassoHRef, NULL); - LASSO_PROFILE(login)->msg_url = lasso_node_get_child_content(node_dump, "MsgUrl", - lassoLassoHRef, NULL); - LASSO_PROFILE(login)->msg_body = lasso_node_get_child_content(node_dump, "MsgBody", - lassoLassoHRef, NULL); - LASSO_PROFILE(login)->msg_relayState = lasso_node_get_child_content(node_dump, "MsgRelayState", - lassoLassoHRef, NULL); - - type = lasso_node_get_child_content(node_dump, "RequestType", lassoLassoHRef, NULL); - LASSO_PROFILE(login)->request_type = atoi(type); - xmlFree(type); - - /* rebuild request */ - if (LASSO_PROFILE(login)->request_type == lassoMessageTypeAuthnRequest) { - request_node = lasso_node_get_child(node_dump, "AuthnRequest", lassoLibHRef, NULL); - } - else if (LASSO_PROFILE(login)->request_type == lassoMessageTypeRequest) { - request_node = lasso_node_get_child(node_dump, "Request", lassoSamlProtocolHRef, NULL); - } - if (request_node != NULL) { - export = lasso_node_export(request_node); - if (LASSO_PROFILE(login)->request_type == lassoMessageTypeAuthnRequest) { - LASSO_PROFILE(login)->request = lasso_authn_request_new_from_export(export, - lassoNodeExportTypeXml); - } - else if (LASSO_PROFILE(login)->request_type == lassoMessageTypeRequest) { - LASSO_PROFILE(login)->request = lasso_request_new_from_export(export, - lassoNodeExportTypeXml); - } - g_free(export); - lasso_node_destroy(request_node); - } - - type = lasso_node_get_child_content(node_dump, "ResponseType", lassoLassoHRef, NULL); - LASSO_PROFILE(login)->response_type = atoi(type); - xmlFree(type); - - /* rebuild response */ - if (LASSO_PROFILE(login)->response_type == lassoMessageTypeAuthnResponse) { - response_node = lasso_node_get_child(node_dump, "AuthnResponse", lassoLibHRef, NULL); - } - else if (LASSO_PROFILE(login)->response_type == lassoMessageTypeResponse) { - response_node = lasso_node_get_child(node_dump, "Response", lassoSamlProtocolHRef, NULL); - } - if (response_node != NULL) { - export = lasso_node_export(response_node); - if (LASSO_PROFILE(login)->response_type == lassoMessageTypeAuthnResponse) { - LASSO_PROFILE(login)->response = lasso_authn_response_new_from_export(export, - lassoNodeExportTypeXml); - } - else if (LASSO_PROFILE(login)->response_type == lassoMessageTypeResponse) { - LASSO_PROFILE(login)->response = lasso_response_new_from_export(export, - lassoNodeExportTypeXml); - } - g_free(export); - lasso_node_destroy(response_node); - } - - type = lasso_node_get_child_content(node_dump, "ProviderType", lassoLassoHRef, NULL); - LASSO_PROFILE(login)->provider_type = atoi(type); - xmlFree(type); - - /* login attributes */ - protocolProfile = lasso_node_get_child_content(node_dump, "ProtocolProfile", - lassoLassoHRef, NULL); - if (protocolProfile != NULL) { - login->protocolProfile = atoi(protocolProfile); - xmlFree(protocolProfile); - } - - login->assertionArtifact = lasso_node_get_child_content(node_dump, "AssertionArtifact", - lassoLassoHRef, NULL); - - lasso_node_destroy(node_dump); - - return login; + LassoLogin *login; + xmlDoc *doc; + + login = g_object_new(LASSO_TYPE_LOGIN, NULL); + doc = xmlParseMemory(dump, strlen(dump)); + init_from_xml(LASSO_NODE(login), xmlDocGetRootElement(doc)); + LASSO_PROFILE(login)->server = server; + + return login; } + +gchar* +lasso_login_dump(LassoLogin *login) +{ + return lasso_node_dump(LASSO_NODE(login), NULL, 1); +} + diff --git a/lasso/id-ff/login.h b/lasso/id-ff/login.h index beaae867..764f78e6 100644 --- a/lasso/id-ff/login.h +++ b/lasso/id-ff/login.h @@ -33,10 +33,10 @@ extern "C" { #include <lasso/environs/profile.h> -#include <lasso/protocols/authn_request.h> -#include <lasso/protocols/authn_response.h> -#include <lasso/protocols/request.h> -#include <lasso/protocols/response.h> +#include <lasso/xml/lib_authn_request.h> +#include <lasso/xml/lib_authn_response.h> +#include <lasso/xml/samlp_request.h> +#include <lasso/xml/samlp_response.h> #define LASSO_TYPE_LOGIN (lasso_login_get_type()) #define LASSO_LOGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_LOGIN, LassoLogin)) @@ -50,24 +50,25 @@ typedef struct _LassoLoginClass LassoLoginClass; typedef struct _LassoLoginPrivate LassoLoginPrivate; typedef enum { - lassoLoginProtocolProfileBrwsArt = 1, - lassoLoginProtocolProfileBrwsPost, + LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART = 1, + LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST, } lassoLoginProtocolProfile; struct _LassoLogin { - LassoProfile parent; - /*< public >*/ - lassoLoginProtocolProfile protocolProfile; - gchar *assertionArtifact; - - /*< private >*/ - gchar *nameIDPolicy; - lassoHttpMethod http_method; - LassoLoginPrivate *private; + LassoProfile parent; + + /*< public >*/ + lassoLoginProtocolProfile protocolProfile; + gchar *assertionArtifact; + + /*< private >*/ + gchar *nameIDPolicy; + lassoHttpMethod http_method; + LassoLoginPrivate *private; }; struct _LassoLoginClass { - LassoProfileClass parent; + LassoProfileClass parent; }; LASSO_EXPORT GType lasso_login_get_type (void); @@ -75,25 +76,31 @@ LASSO_EXPORT GType lasso_login_get_type (void); LASSO_EXPORT LassoLogin* lasso_login_new (LassoServer *server); LASSO_EXPORT LassoLogin* lasso_login_new_from_dump (LassoServer *server, - gchar *dump); + const gchar *dump); LASSO_EXPORT gint lasso_login_accept_sso (LassoLogin *login); LASSO_EXPORT gint lasso_login_build_artifact_msg (LassoLogin *login, - gboolean authentication_result, - gboolean is_consent_obtained, - const gchar *authenticationMethod, - const gchar *reauthenticateOnOrAfter, - lassoHttpMethod http_method); + gboolean authentication_result, + gboolean is_consent_obtained, + const char *authenticationMethod, + const char *authenticationInstant, + const char *reauthenticateOnOrAfter, + const char *notBefore, + const char *notOnOrAfter, + lassoHttpMethod http_method); LASSO_EXPORT gint lasso_login_build_authn_request_msg (LassoLogin *login, const gchar *remote_providerID); LASSO_EXPORT gint lasso_login_build_authn_response_msg (LassoLogin *login, - gboolean authentication_result, - gboolean is_consent_obtained, - const gchar *authenticationMethod, - const gchar *reauthenticateOnOrAfter); + gboolean authentication_result, + gboolean is_consent_obtained, + const char *authenticationMethod, + const char *authenticationInstant, + const char *reauthenticateOnOrAfter, + const char *notBefore, + const char *notOnOrAfter); LASSO_EXPORT gint lasso_login_build_request_msg (LassoLogin *login); @@ -110,7 +117,7 @@ LASSO_EXPORT gint lasso_login_init_authn_request (LassoLogin LASSO_EXPORT gint lasso_login_init_request (LassoLogin *login, gchar *response_msg, lassoHttpMethod response_http_method); -LASSO_EXPORT gint lasso_login_init_self_addressed_authn_request (LassoLogin *login, +LASSO_EXPORT gint lasso_login_init_idp_initiated_authn_request (LassoLogin *login, const gchar *remote_providerID); LASSO_EXPORT gboolean lasso_login_must_ask_for_consent (LassoLogin *login); @@ -118,8 +125,7 @@ LASSO_EXPORT gboolean lasso_login_must_ask_for_consent (LassoLogin *log LASSO_EXPORT gboolean lasso_login_must_authenticate (LassoLogin *login); LASSO_EXPORT gint lasso_login_process_authn_request_msg (LassoLogin *login, - gchar *authn_request_msg, - lassoHttpMethod authn_request_http_method); + gchar *authn_request_msg); LASSO_EXPORT gint lasso_login_process_authn_response_msg (LassoLogin *login, gchar *authn_response_msg); diff --git a/lasso/id-ff/logout.c b/lasso/id-ff/logout.c index 3ef23636..c2d2c0dd 100644 --- a/lasso/id-ff/logout.c +++ b/lasso/id-ff/logout.c @@ -30,16 +30,14 @@ #include <lasso/environs/logout.h> #include <lasso/xml/errors.h> -#define LASSO_LOGOUT_NODE "LassoLogout" -#define LASSO_REMOTE_PROVIDERID_NODE "RemoteProviderID" - -static GObjectClass *parent_class = NULL; - struct _LassoLogoutPrivate { - gboolean dispose_has_run; + gboolean dispose_has_run; + gboolean all_soap; }; +static void check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile); + /*****************************************************************************/ /* public methods */ /*****************************************************************************/ @@ -50,117 +48,87 @@ struct _LassoLogoutPrivate * * This method builds the logout request message. * - * It gets the single logout protocol profile of the remote provider and : - * if it is a SOAP method, then it builds the logout request SOAP message, - * sets the msg_body attribute, gets the single logout service url - * and sets the msg_url attribute of the logout object. + * It gets the http method retrieved to send the request and : * - * if it is a HTTP-Redirect method, then it builds the logout request QUERY message, - * builds the logout request url, sets the msg_url to the logout request url, - * sets the msg_body to NULL + * - if it is a SOAP method, then it builds the logout request SOAP message, + * sets the msg_body attribute, gets the single logout service url and sets + * the msg_url attribute of the logout object. * - * Optionaly ( if private key and certificates paths are set in server object ) - * it signs the message (with X509 if a SOAP message, - * else with simple signature if a QUERY message ) + * - if it is a HTTP-Redirect method, then it builds the logout request QUERY + * message, builds the logout request url, sets the msg_url to the logout + * request url, sets the msg_body to NULL + * + * Optionaly (if private key and certificates paths are set in server object) + * it signs the message (with X509 if a SOAP message, else with simple + * signature if a QUERY message) * - * Return value: 0 if ok, else < 0 + * Return value: 0 if ok, else return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD + * if the http method is invalid, else returns -1 **/ gint lasso_logout_build_request_msg(LassoLogout *logout) { - LassoProfile *profile; - LassoProvider *provider; - xmlChar *protocolProfile = NULL; - GError *err = NULL; - gchar *url = NULL, *query = NULL; - lassoProviderType remote_provider_type; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); - - profile = LASSO_PROFILE(logout); - - /* get the remote provider type and get the remote provider object */ - if (profile->provider_type == lassoProviderTypeSp) { - remote_provider_type = lassoProviderTypeIdp; - } - else if (profile->provider_type == lassoProviderTypeIdp) { - remote_provider_type = lassoProviderTypeSp; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, &err); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - /* get the prototocol profile of the logout request */ - protocolProfile = lasso_provider_get_singleLogoutProtocolProfile(provider, - remote_provider_type, - NULL); - if (protocolProfile == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Single logout protocol profile not found\n"); - ret = -1; - goto done; - } - - /* build the logout request message */ - if (xmlStrEqual(protocolProfile, lassoLibProtocolProfileSloSpSoap) || \ - xmlStrEqual(protocolProfile, lassoLibProtocolProfileSloIdpSoap)) { - /* sign the request message */ - lasso_samlp_request_abstract_sign_signature_tmpl(LASSO_SAMLP_REQUEST_ABSTRACT(profile->request), - profile->server->private_key, - profile->server->certificate); - - /* build the logout request message */ - profile->msg_url = lasso_provider_get_soapEndpoint(provider, - remote_provider_type, - NULL); - profile->msg_body = lasso_node_export_to_soap(profile->request); - } - else if (xmlStrEqual(protocolProfile,lassoLibProtocolProfileSloSpHttp) || \ - xmlStrEqual(protocolProfile,lassoLibProtocolProfileSloIdpHttp)) { - /* build and optionaly sign the logout request QUERY message */ - url = lasso_provider_get_singleLogoutServiceURL(provider, remote_provider_type, NULL); - query = lasso_node_export_to_query(profile->request, - profile->server->signature_method, - profile->server->private_key); - if ( (url == NULL) || (query == NULL) ) { - message(G_LOG_LEVEL_CRITICAL, "Error while building request QUERY url\n"); - ret = -1; - goto done; - } - - /* build the msg_url */ - profile->msg_url = g_strdup_printf("%s?%s", url, query); - profile->msg_body = NULL; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid logout protocol profile\n"); - ret = -1; - goto done; - } - - done: - if (protocolProfile != NULL) { - xmlFree(protocolProfile); - } - if (url != NULL) { - xmlFree(url); - } - if (query != NULL) { - xmlFree(query); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + char *url, *query; + + g_return_val_if_fail(LASSO_IS_LOGOUT(logout), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(logout); + + /* get remote provider */ + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + + /* build the logout request message */ + if (logout->initial_http_request_method == LASSO_HTTP_METHOD_SOAP) { +#if 0 /* XXX: signatures are done differently */ + /* sign the request message */ + lasso_samlp_request_abstract_sign_signature_tmpl( + LASSO_SAMLP_REQUEST_ABSTRACT(profile->request), + profile->server->private_key, + profile->server->certificate); +#endif + /* build the logout request message */ + profile->msg_url = lasso_provider_get_metadata_one(remote_provider, "SoapEndpoint"); + profile->msg_body = lasso_node_export_to_soap(profile->request); + } + if (logout->initial_http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + /* build and optionaly sign the logout request QUERY message */ + url = lasso_provider_get_metadata_one(remote_provider, + "SingleLogoutServiceURL"); + if (url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Unknown profile service URL"); + return -1; + } + query = lasso_node_export_to_query(profile->request, + profile->server->signature_method, + profile->server->private_key); + if (query == NULL) { + g_free(url); + message(G_LOG_LEVEL_CRITICAL, "Error while building request QUERY url"); + return -1; + } + /* build the msg_url */ + profile->msg_url = g_strdup_printf("%s?%s", url, query); + g_free(url); + g_free(query); + profile->msg_body = NULL; + } + + if (profile->msg_url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Invalid http method\n"); + return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; + } + + return 0; } + /** * lasso_logout_build_response_msg: * @logout: the logout object @@ -185,19 +153,19 @@ lasso_logout_build_request_msg(LassoLogout *logout) gint lasso_logout_build_response_msg(LassoLogout *logout) { + /* XXX function to update (working but ugly) */ LassoProfile *profile; LassoProvider *provider; gchar *url = NULL, *query = NULL; GError *err = NULL; gint ret = 0; - gint remote_provider_type; g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); profile = LASSO_PROFILE(logout); /* get the provider */ - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, &err); + provider = g_hash_table_lookup(profile->server->providers, profile->remote_providerID); if (provider == NULL) { message(G_LOG_LEVEL_CRITICAL, err->message); ret = err->code; @@ -205,35 +173,24 @@ lasso_logout_build_response_msg(LassoLogout *logout) goto done; } - /* get the remote provider type */ - if (profile->provider_type == lassoProviderTypeSp) { - remote_provider_type = lassoProviderTypeIdp; - } - else if (profile->provider_type == lassoProviderTypeIdp) { - remote_provider_type = lassoProviderTypeSp; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - /* build logout response message */ switch (profile->http_request_method) { - case lassoHttpMethodSoap: + case LASSO_HTTP_METHOD_SOAP: /* optionaly sign the response message */ if (profile->server->private_key) { +#if 0 /* XXX: signature different now */ lasso_samlp_response_abstract_set_signature(LASSO_SAMLP_RESPONSE_ABSTRACT(profile->response), profile->server->signature_method, profile->server->private_key, profile->server->certificate); +#endif } profile->msg_url = NULL; profile->msg_body = lasso_node_export_to_soap(profile->response); break; - case lassoHttpMethodRedirect: - url = lasso_provider_get_singleLogoutServiceReturnURL(provider, remote_provider_type, NULL); + case LASSO_HTTP_METHOD_REDIRECT: + url = lasso_provider_get_metadata_one(provider, "SingleLogoutServiceReturnURL"); query = lasso_node_export_to_query(profile->response, profile->server->signature_method, profile->server->private_key); @@ -272,68 +229,7 @@ lasso_logout_build_response_msg(LassoLogout *logout) void lasso_logout_destroy(LassoLogout *logout) { - g_object_unref(G_OBJECT(logout)); -} - -/** - * lasso_logout_dump: - * @logout: the logout object - * - * This method dumps the logout object in string a xml message. - * it first adds profile informations. - * Next, it adds his logout informations (initial_request, initial_response, - * initial_remote_providerID and providerID_index). - * - * Return value: a newly allocated string or NULL - **/ -gchar * -lasso_logout_dump(LassoLogout *logout) -{ - LassoNode *initial_node = NULL, *child_node = NULL; - gchar *dump = NULL, *parent_dump = NULL, *providerID_index_str; - LassoNode *node = NULL; - - g_return_val_if_fail(LASSO_IS_LOGOUT(logout), NULL); - - parent_dump = lasso_profile_dump(LASSO_PROFILE(logout), "Logout"); - node = lasso_node_new_from_dump(parent_dump); - g_free(parent_dump); - - if (logout->initial_request != NULL) { - initial_node = lasso_node_new(); - LASSO_NODE_GET_CLASS(initial_node)->set_name(initial_node, "InitialLogoutResquest"); - child_node = lasso_node_copy(logout->initial_request); - LASSO_NODE_GET_CLASS(initial_node)->add_child(initial_node, child_node, FALSE); - lasso_node_destroy(child_node); - - LASSO_NODE_GET_CLASS(node)->add_child(node, initial_node, FALSE); - } - - if (logout->initial_response != NULL) { - initial_node = lasso_node_new(); - LASSO_NODE_GET_CLASS(initial_node)->set_name(initial_node, "InitialLogoutResponse"); - child_node = lasso_node_copy(logout->initial_response); - LASSO_NODE_GET_CLASS(initial_node)->add_child(initial_node, child_node, FALSE); - lasso_node_destroy(child_node); - - LASSO_NODE_GET_CLASS(node)->add_child(node, initial_node, FALSE); - } - - if (logout->initial_remote_providerID != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "InitialRemoteProviderID", - logout->initial_remote_providerID, FALSE); - } - - /* add providerID_index */ - providerID_index_str = g_strdup_printf("%d", logout->providerID_index); - LASSO_NODE_GET_CLASS(node)->new_child(node, "ProviderIDIndex", - providerID_index_str, FALSE); - - dump = lasso_node_export(node); - - lasso_node_destroy(node); - - return dump; + g_object_unref(G_OBJECT(logout)); } /** @@ -386,194 +282,139 @@ lasso_logout_get_next_providerID(LassoLogout *logout) * Return value: 0 if ok, else < 0 **/ gint -lasso_logout_init_request(LassoLogout *logout, - gchar *remote_providerID, - lassoHttpMethod request_method) /* FIXME : support this param to allow the user to choose the request method */ +lasso_logout_init_request(LassoLogout *logout, char *remote_providerID, lassoHttpMethod http_method) { - LassoProfile *profile = NULL; - LassoProvider *provider = NULL; - LassoNode *nameIdentifier = NULL; - LassoFederation *federation = NULL; - xmlChar *content = NULL, *nameQualifier = NULL, *format = NULL; - xmlChar *singleLogoutProtocolProfile = NULL; - GError *err = NULL; - gboolean is_http_redirect_get_method = FALSE; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); - - profile = LASSO_PROFILE(logout); - - /* verify if the identity and session exist */ - if (profile->identity == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Identity not found\n"); - ret = -1; - goto done; - } - if (profile->session == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Session not found\n"); - ret = -1; - goto done; - } - - /* get the remote provider id */ - /* If remote_providerID is NULL, then get the first remote provider id in session */ - if (remote_providerID == NULL) { - profile->remote_providerID = lasso_session_get_first_providerID(profile->session); - } - else { - profile->remote_providerID = g_strdup(remote_providerID); - } - if (profile->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "No remote provider id to send the logout request\n"); - ret = -1; - goto done; - } - - /* get federation */ - federation = lasso_identity_get_federation(profile->identity, profile->remote_providerID); - if (federation == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Federation not found\n"); - ret = -1; - goto done; - } - - /* get the name identifier */ - switch (profile->provider_type) { - case lassoProviderTypeSp: - /* SP : get the local name identifier, if it is NULL, then get the remote name identifier */ - nameIdentifier = lasso_federation_get_local_nameIdentifier(federation); - if (nameIdentifier == NULL) { - nameIdentifier = lasso_federation_get_remote_nameIdentifier(federation); - } - break; - case lassoProviderTypeIdp: - /* IDP : get the remote name identifier, if it is NULL, then get the local name identifier */ - nameIdentifier = lasso_federation_get_remote_nameIdentifier(federation); - if (nameIdentifier == NULL) { - nameIdentifier = lasso_federation_get_local_nameIdentifier(federation); - } - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - - if (nameIdentifier == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier not found for %s\n", - profile->remote_providerID); - ret = -1; - goto done; - } - - /* Get name identifier attributes */ - /* WARNING : Don't free content, it will be backed up in nameIdentifier attribute of LassoDefederation object */ - content = lasso_node_get_content(nameIdentifier, NULL); - nameQualifier = lasso_node_get_attr_value(nameIdentifier, "NameQualifier", NULL); - format = lasso_node_get_attr_value(nameIdentifier, "Format", NULL); - - /* get the provider */ - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, &err); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - /* Get the single logout protocol profile */ - if (profile->provider_type == lassoProviderTypeIdp) { - singleLogoutProtocolProfile = lasso_provider_get_singleLogoutProtocolProfile(provider, lassoProviderTypeSp, NULL); - } - else if (profile->provider_type == lassoProviderTypeSp) { - singleLogoutProtocolProfile = lasso_provider_get_singleLogoutProtocolProfile(provider, lassoProviderTypeIdp, NULL); - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - if (singleLogoutProtocolProfile == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Single logout protocol profile not found\n"); - ret = -1; - goto done; - } - - /* before setting profile->request, verify if it is already set */ - if (LASSO_IS_LOGOUT_REQUEST(profile->request) == TRUE) { - lasso_node_destroy(profile->request); - profile->request = NULL; - } - - /* build a new request object from single logout protocol profile */ - if (xmlStrEqual(singleLogoutProtocolProfile, lassoLibProtocolProfileSloSpSoap) || \ - xmlStrEqual(singleLogoutProtocolProfile, lassoLibProtocolProfileSloIdpSoap)) { - profile->request = lasso_logout_request_new(profile->server->providerID, - content, - nameQualifier, - format, - lassoSignatureTypeWithX509, - lassoSignatureMethodRsaSha1); - } - else if (xmlStrEqual(singleLogoutProtocolProfile, lassoLibProtocolProfileSloSpHttp) || \ - xmlStrEqual(singleLogoutProtocolProfile, lassoLibProtocolProfileSloIdpHttp)) { - is_http_redirect_get_method = TRUE; - profile->request = lasso_logout_request_new(profile->server->providerID, - content, - nameQualifier, - format, - lassoSignatureTypeNone, - 0); - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid single logout protocol profile : %s\n", singleLogoutProtocolProfile); - ret = -1; - goto done; - } - if (LASSO_IS_LOGOUT_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Error while building the request\n"); - ret = -1; - goto done; - } - - /* Set the name identifier attribute with content local variable */ - profile->nameIdentifier = content; - content = NULL; - - /* if logout request from a SP and if an HTTP Redirect / GET method, then remove assertion */ - if (profile->provider_type == lassoProviderTypeSp && is_http_redirect_get_method == TRUE) { - lasso_session_remove_assertion(profile->session, profile->remote_providerID); - } - - done: - if (federation != NULL) { - lasso_federation_destroy(federation); - } - if (nameIdentifier != NULL ) { - lasso_node_destroy(nameIdentifier); - } - if (content != NULL) { - xmlFree(content); - } - if (nameQualifier != NULL) { - xmlFree(nameQualifier); - } - if (format != NULL) { - xmlFree(format); - } - if (singleLogoutProtocolProfile != NULL) { - xmlFree(singleLogoutProtocolProfile); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoSamlNameIdentifier *nameIdentifier; + LassoSamlAssertion *assertion; + LassoFederation *federation = NULL; + gboolean is_http_redirect_get_method = FALSE; + + g_return_val_if_fail(LASSO_IS_LOGOUT(logout), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(logout); + + /* verify if session exists */ + if (profile->session == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Session not found"); + return -1; + } + + /* get the remote provider id + If remote_providerID is NULL, then get the first remote provider id in session */ + if (remote_providerID == NULL) { + profile->remote_providerID = lasso_session_get_first_providerID(profile->session); + } else { + profile->remote_providerID = g_strdup(remote_providerID); + } + if (profile->remote_providerID == NULL) { + message(G_LOG_LEVEL_CRITICAL, "No remote provider id to build the logout request"); + return -1; + } + + /* get assertion */ + assertion = lasso_session_get_assertion(profile->session, profile->remote_providerID); + if (LASSO_IS_SAML_ASSERTION(assertion) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Assertion not found"); + return -1; + } + + /* if format is one time, then get name identifier from assertion, + else get name identifier from federation */ + nameIdentifier = LASSO_SAML_SUBJECT_STATEMENT_ABSTRACT( + assertion->AuthenticationStatement)->Subject->NameIdentifier; + if (strcmp(nameIdentifier->Format, LASSO_LIB_NAME_IDENTIFIER_FORMAT_ONE_TIME) != 0) { + if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + return -1; + } + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (federation == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + return -1; + } + + nameIdentifier = lasso_profile_get_nameIdentifier(profile); + if (nameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Name identifier not found for %s", + profile->remote_providerID); + return -1; + } + } + + /* get the provider */ + remote_provider = g_hash_table_lookup( + profile->server->providers, profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Remote provider not found"); + return -1; + } + + /* before setting profile->request, verify if it is already set */ + if (LASSO_IS_LIB_LOGOUT_REQUEST(profile->request) == TRUE) { + lasso_node_destroy(profile->request); + profile->request = NULL; + } + + /* build a new request object from single logout protocol profile */ + + /* get / verify http method */ + 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) { + return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } + } + + /* build a new request object from http method */ + if (http_method == LASSO_HTTP_METHOD_SOAP) { + profile->request = lasso_lib_logout_request_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + nameIdentifier, + LASSO_SIGNATURE_TYPE_WITHX509, + LASSO_SIGNATURE_METHOD_RSA_SHA1); + } + if (http_method == LASSO_HTTP_METHOD_REDIRECT) { + is_http_redirect_get_method = TRUE; + profile->request = lasso_lib_logout_request_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + nameIdentifier, + LASSO_SIGNATURE_TYPE_NONE, + 0); + } + if (LASSO_IS_LIB_LOGOUT_REQUEST(profile->request) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Error while building the request"); + return -1; + } + + /* Set the name identifier attribute with content local variable */ + profile->nameIdentifier = g_strdup(nameIdentifier->content); + + /* 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); + } + + /* Save the http method */ + logout->initial_http_request_method = http_method; + + return 0; } /** * lasso_logout_process_request_msg: * @logout: the logout object * @request_msg: the logout request message - * @request_method: the logout request method * * Processes a logout request. * if it is a SOAP request method then it builds the logout request object @@ -587,253 +428,191 @@ lasso_logout_init_request(LassoLogout *logout, * * Return value: 0 on success or a negative value otherwise. **/ -gint lasso_logout_process_request_msg(LassoLogout *logout, - gchar *request_msg, - lassoHttpMethod request_method) +gint lasso_logout_process_request_msg(LassoLogout *logout, char *request_msg) { - LassoProfile *profile; - LassoProvider *provider; - gchar *remote_providerID = NULL; - gint ret = 0; - GError *err = NULL; - - g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); - g_return_val_if_fail(request_msg != NULL, -1); - - profile = LASSO_PROFILE(logout); - - /* rebuild the request message and optionaly verify the signature */ - switch (request_method) { - case lassoHttpMethodSoap: - profile->request = lasso_logout_request_new_from_export(request_msg, - lassoNodeExportTypeSoap); - - /* verify requets is a LogoutRequest */ - if (LASSO_IS_LOGOUT_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG)); - ret = LASSO_PROFILE_ERROR_INVALID_SOAP_MSG; - goto done; - } - - /* verify signature */ - remote_providerID = lasso_node_get_child_content(profile->request, "ProviderID", NULL, NULL); - if (remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "ProviderID not found\n"); - ret = -1; - goto done; - } - provider = lasso_server_get_provider_ref(profile->server, remote_providerID, &err); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - if (provider->ca_cert_chain != NULL) { - ret = lasso_node_verify_signature(profile->request, provider->public_key, - provider->ca_cert_chain); - } - break; - case lassoHttpMethodRedirect: - profile->request = lasso_logout_request_new_from_export(request_msg, - lassoNodeExportTypeQuery); - /* if problem while rebuilding the response, then return invalid query code error */ - if (LASSO_IS_LOGOUT_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_QUERY)); - ret = LASSO_PROFILE_ERROR_INVALID_QUERY; - goto done; - } - - break; - default: - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - ret = LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - goto done; - } - - /* set the http request method */ - profile->http_request_method = request_method; - - /* Set the NameIdentifier */ - profile->nameIdentifier = lasso_node_get_child_content(profile->request, - "NameIdentifier", - NULL, NULL); - - done: - if (remote_providerID != NULL ) { - xmlFree(remote_providerID); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoMessageFormat format; + + g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); + g_return_val_if_fail(request_msg != NULL, -1); + + profile = LASSO_PROFILE(logout); + + profile->request = lasso_lib_logout_request_new(); + format = lasso_node_init_from_message(profile->request, request_msg); + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_INVALID_MSG; + } + + remote_provider = g_hash_table_lookup(profile->server->providers, + LASSO_LIB_LOGOUT_REQUEST(profile->request)->ProviderID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Unknown provider"); + return -1; + } + + /* verify signatures */ + profile->signature_status = lasso_provider_verify_signature( + remote_provider, request_msg, "RequestID"); + + 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_strdup( + LASSO_LIB_LOGOUT_REQUEST(profile->request)->NameIdentifier->content); + + return profile->signature_status; } + /** * lasso_logout_process_response_msg: * @logout: the logout object * @response_msg: the response message - * @response_method: the response method * * Parses the response message and builds the response object. * Get the status code value : - * if it is not success, then if the local provider is a Service Provider and response method is SOAP, - * then builds a new logout request message for HTTP Redirect / GET method and returns the code error - * LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE and exits. + * if it is not success, then if the local provider is a Service Provider and response method + * is SOAP, then builds a new logout request message for HTTP Redirect / GET method and returns + * the code error LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE and exits. * * Sets the remote provider id. * Sets the relay state. * - * if it is a SOAP method or, IDP provider type and http method is Redirect / GET, then removes assertion. + * if it is a SOAP method or, IDP provider type and http method is Redirect / GET, + * then removes assertion. * - * If local server is an Identity Provider and if there is no more assertion (Identity Provider has logged out every Service Providers), + * If local server is an Identity Provider and if there is no more assertion + * (Identity Provider has logged out every Service Providers), * then restores the initial response. * Return value: 0 if OK else LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE or < 0 **/ gint -lasso_logout_process_response_msg(LassoLogout *logout, - gchar *response_msg, - lassoHttpMethod response_method) +lasso_logout_process_response_msg(LassoLogout *logout, gchar *response_msg) { - gchar *last_providerID = NULL; - xmlChar *statusCodeValue = NULL; - LassoNode *statusCode = NULL; - LassoProfile *profile = NULL; - GError *err = NULL; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); - g_return_val_if_fail(response_msg != NULL, -1); - - profile = LASSO_PROFILE(logout); - - /* before verify if profile->response is set */ - if (LASSO_IS_LOGOUT_RESPONSE(profile->response) == TRUE) { - lasso_node_destroy(profile->response); - profile->response = NULL; - } - - /* build logout response object */ - switch (response_method) { - case lassoHttpMethodSoap: - profile->response = lasso_logout_response_new_from_export(response_msg, lassoNodeExportTypeSoap); - break; - case lassoHttpMethodRedirect: - profile->response = lasso_logout_response_new_from_export(response_msg, lassoNodeExportTypeQuery); - /* if problem while rebuilding the response, then return invalid query code error */ - if (LASSO_IS_LOGOUT_RESPONSE(profile->response) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_QUERY)); - ret = LASSO_PROFILE_ERROR_INVALID_QUERY; - goto done; - } - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid response method\n"); - ret = -1; - goto done; - } - if (LASSO_IS_LOGOUT_RESPONSE(profile->response) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Message is not a LogoutResponse\n"); - ret = -1; - goto done; - } - - /* get the status code */ - statusCode = lasso_node_get_child(profile->response, "StatusCode", NULL, NULL); - if (statusCode == NULL) { - message(G_LOG_LEVEL_CRITICAL, "StatusCode node not found\n"); - ret = -1; - goto done; - } - statusCodeValue = lasso_node_get_attr_value(statusCode, "Value", NULL); - - if (!xmlStrEqual(statusCodeValue, lassoSamlStatusCodeSuccess)) { - - /* At SP, if the request method was a SOAP type, then rebuild the request message with HTTP method */ - if (xmlStrEqual(statusCodeValue, lassoLibStatusCodeUnsupportedProfile) && \ - profile->provider_type == lassoProviderTypeSp && \ - profile->http_request_method == lassoHttpMethodSoap) { - /* temporary vars */ - LassoProvider *provider; - gchar *url, *query; - - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, &err); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - /* FIXME : verify the IDP support a HTTP method */ - - /* Build and optionaly sign the logout request QUERY message */ - url = lasso_provider_get_singleLogoutServiceURL(provider, lassoProviderTypeIdp, NULL); - query = lasso_node_export_to_query(profile->request, - profile->server->signature_method, - profile->server->private_key); - profile->msg_url = g_strdup_printf("%s?%s", url, query); - profile->msg_body = NULL; - - /* send a HTTP Redirect / GET method, so first remove session */ - lasso_session_remove_assertion(profile->session, profile->remote_providerID); - - ret = LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Status code is not success : %s\n", statusCodeValue); - ret = -1; - } - - goto done; - } - - /* LogoutResponse status code value is ok */ - - /* set the remote provider id */ - profile->remote_providerID = lasso_node_get_child_content(profile->response, - "ProviderID", - lassoLibHRef, - NULL); - - /* set the msg_relayState */ - profile->msg_relayState = lasso_node_get_child_content(profile->response, "RelayState", lassoLibHRef, NULL); - - /* if SOAP method or, if IDP provider type and HTTP Redirect, then remove assertion */ - if ( (response_method == lassoHttpMethodSoap) || (profile->provider_type == lassoProviderTypeIdp && response_method == lassoHttpMethodRedirect) ) { - ret = lasso_session_remove_assertion(profile->session, profile->remote_providerID); - if (profile->provider_type == lassoProviderTypeIdp && logout->providerID_index >= 0) { - logout->providerID_index--; - } - } - - /* If at IDP and if there is no more assertion, IDP a logged out every SPs, return the initial response to initial SP */ - if (profile->provider_type == lassoProviderTypeIdp && logout->initial_remote_providerID && profile->session->providerIDs->len == 0) { - if (profile->remote_providerID != NULL) { - g_free(profile->remote_providerID); - } - if (profile->request != NULL) { - lasso_node_destroy(profile->request); - } - if (profile->response != NULL) { - lasso_node_destroy(profile->response); - } - - profile->remote_providerID = logout->initial_remote_providerID; - profile->request = logout->initial_request; - profile->response = logout->initial_response; - - logout->initial_remote_providerID = NULL; - logout->initial_request = NULL; - logout->initial_response = NULL; - } - - done: - if (last_providerID != NULL) { - g_free(last_providerID); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + char *statusCodeValue; + lassoHttpMethod response_method; + LassoMessageFormat format; + int rc; + + g_return_val_if_fail(LASSO_IS_LOGOUT(logout), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(logout); + + /* before verify if profile->response is set */ + if (LASSO_IS_LIB_LOGOUT_RESPONSE(profile->response) == TRUE) { + lasso_node_destroy(profile->response); + profile->response = NULL; + } + + profile->response = lasso_lib_logout_response_new(); + format = lasso_node_init_from_message(profile->response, response_msg); + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_INVALID_MSG; + } + if (format == LASSO_MESSAGE_FORMAT_SOAP) + response_method = LASSO_HTTP_METHOD_SOAP; + if (format == LASSO_MESSAGE_FORMAT_QUERY) + response_method = LASSO_HTTP_METHOD_REDIRECT; + + /* get provider */ + profile->remote_providerID = LASSO_LIB_STATUS_RESPONSE(profile->response)->ProviderID; + if (profile->remote_providerID == NULL) { + message(G_LOG_LEVEL_CRITICAL, "ProviderID not found"); + return LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID; + } + + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Invalid provider"); + return -1; + } + + /* verify signature */ + rc = lasso_provider_verify_signature(remote_provider, response_msg, "ResponseID"); + + statusCodeValue = LASSO_LIB_STATUS_RESPONSE(profile->response)->Status->StatusCode->Value; + + if (strcmp(statusCodeValue, LASSO_SAML_STATUS_CODE_SUCCESS) != 0) { + /* At SP, if the request method was a SOAP type, then rebuild the request + * message with HTTP method */ + if (strcmp(statusCodeValue, LASSO_LIB_STATUS_CODE_UNSUPPORTED_PROFILE) == 0 && + remote_provider->role == LASSO_PROVIDER_ROLE_IDP && + logout->initial_http_request_method == LASSO_HTTP_METHOD_SOAP) { + gchar *url, *query; + + /* Build and optionaly sign the logout request QUERY message */ + url = lasso_provider_get_metadata_one(remote_provider, + "SingleLogoutServiceURL"); + query = lasso_node_export_to_query(profile->request, + profile->server->signature_method, + profile->server->private_key); + profile->msg_url = g_strdup_printf("%s?%s", url, query); + g_free(query); + profile->msg_body = NULL; + + /* send a HTTP Redirect / GET method, so first remove session */ + lasso_session_remove_assertion(profile->session, profile->remote_providerID); + + return LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE; + } + message(G_LOG_LEVEL_CRITICAL, "Status code is not success : %s", statusCodeValue); + return -1; + } + + /* LogoutResponse status code value is ok */ + + /* set the msg_relayState */ + profile->msg_relayState = g_strdup( + LASSO_LIB_STATUS_RESPONSE(profile->response)->RelayState); + + /* if SOAP method or, if IDP provider type and HTTP Redirect, then remove assertion */ + if ( response_method == LASSO_HTTP_METHOD_SOAP || + (remote_provider->role == LASSO_PROVIDER_ROLE_SP && + response_method == LASSO_HTTP_METHOD_REDIRECT) ) { + lasso_session_remove_assertion(profile->session, profile->remote_providerID); +#if 0 /* ? */ + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP && + logout->providerID_index >= 0) { + logout->providerID_index--; + } +#endif + } + + /* If at IDP and if there is no more assertion, IDP a logged out every SPs, + return the initial response to initial SP */ + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP && + logout->initial_remote_providerID && + g_hash_table_size(profile->session->assertions) == 0) { + if (profile->remote_providerID != NULL) + g_free(profile->remote_providerID); + if (profile->request != NULL) + lasso_node_destroy(profile->request); + if (profile->response != NULL) + lasso_node_destroy(profile->response); + + profile->remote_providerID = logout->initial_remote_providerID; + profile->request = logout->initial_request; + profile->response = logout->initial_response; + + logout->initial_remote_providerID = NULL; + logout->initial_request = NULL; + logout->initial_response = NULL; + } + + return rc; } + /** * lasso_logout_reset_providerID_index: * @logout: the logout object @@ -855,196 +634,249 @@ gint lasso_logout_reset_providerID_index(LassoLogout *logout) * lasso_logout_validate_request: * @logout: the logout object * - * Sets the remote provider id - * Sets a logout response with status code value to success. - * Verifies federation and authentication. - * If the request http method is a SOAP method, then verifies every other - * Service Providers supports SOAP method : if not, then sets status code value to - * UnsupportedProfile and returns a code error with LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE. - * - * Every tests are ok, then removes assertion. - * (profile->provider_type == lassoProviderTypeIdp && profile->session->providerIDs->len >= 1) - * If local server is an Identity Provider and if there is more than one Service Provider - * (except the initial Service Provider), - * then saves the initial request, response and remote provider id. + * - Sets the remote provider id + * - Sets a logout response with status code value to success. + * - Verifies federation and authentication. + * - If the request http method is a SOAP method, then verifies every other + * Service Providers supports SOAP method : if not, then sets status code + * value to UnsupportedProfile and returns a code error with + * LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE. + * - Every tests are ok, then removes assertion. + * - If local server is an Identity Provider and if there is more than one + * Service Provider (except the initial Service Provider), then saves the + * initial request, response and remote provider id. * * Return value: O if OK else < 0 **/ gint lasso_logout_validate_request(LassoLogout *logout) { - LassoProfile *profile; - LassoFederation *federation = NULL; - LassoNode *nameIdentifier, *assertion; - LassoNode *statusCode; - LassoNodeClass *statusCode_class; - xmlChar *remote_providerID; - gint ret = 0; + LassoProfile *profile; + LassoFederation *federation = NULL; + LassoProvider *remote_provider; + LassoSamlNameIdentifier *nameIdentifier; + LassoSamlAssertion *assertion; + + g_return_val_if_fail(LASSO_IS_LOGOUT(logout), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(logout); + + /* verify logout request */ + if (LASSO_IS_LIB_LOGOUT_REQUEST(profile->request) == FALSE) + return LASSO_PROFILE_ERROR_MISSING_REQUEST; + + profile->remote_providerID = g_strdup( + LASSO_LIB_LOGOUT_REQUEST(profile->request)->ProviderID); + + /* get the provider */ + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) + return -1; + + /* Set LogoutResponse */ + profile->response = NULL; + if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { + profile->response = lasso_lib_logout_response_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + LASSO_SAML_STATUS_CODE_SUCCESS, + LASSO_LIB_LOGOUT_REQUEST(profile->request), + LASSO_SIGNATURE_TYPE_WITHX509, + LASSO_SIGNATURE_METHOD_RSA_SHA1); + } + if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + profile->response = lasso_lib_logout_response_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + LASSO_SAML_STATUS_CODE_SUCCESS, + LASSO_LIB_LOGOUT_REQUEST(profile->request), + LASSO_SIGNATURE_TYPE_NONE, + 0); + } + if (LASSO_IS_LIB_LOGOUT_RESPONSE(profile->response) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Error while building response\n"); + return -1; + } + + /* verify signature status */ + if (profile->signature_status != 0) { + lasso_profile_set_response_status(profile, LASSO_LIB_STATUS_CODE_INVALID_SIGNATURE); + } + + /* Get the name identifier */ + nameIdentifier = LASSO_LIB_LOGOUT_REQUEST(profile->request)->NameIdentifier; + if (nameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Name identifier not found in logout request"); + lasso_profile_set_response_status( + profile, LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return LASSO_XML_ERROR_NODE_NOT_FOUND; + } + + /* verify authentication */ + assertion = lasso_session_get_assertion(profile->session, profile->remote_providerID); + if (assertion == NULL) { + message(G_LOG_LEVEL_WARNING, "%s has no assertion", profile->remote_providerID); + lasso_profile_set_response_status(profile, LASSO_SAML_STATUS_CODE_REQUEST_DENIED); + return -1; + } + + /* If name identifier is federated, then verify federation */ + if (strcmp(nameIdentifier->Format, LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED) == 0) { + if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return -1; + } + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (LASSO_IS_FEDERATION(federation) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return -1; + } + + if (lasso_federation_verify_nameIdentifier(federation, nameIdentifier) == 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 -1; + } + } + + /* 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->all_soap = TRUE; + g_hash_table_foreach(profile->server->providers, + (GHFunc)check_soap_support, profile); + + if (logout->private->all_soap == FALSE) { + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_UNSUPPORTED_PROFILE); + return LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE; + } + } + + /* FIXME : set the status code in response */ + + /* authentication is ok, federation is ok, propagation support is ok, remove federation */ + 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 = profile->request; + logout->initial_response = profile->response; + + profile->remote_providerID = NULL; + profile->request = NULL; + profile->response = NULL; + } + + return 0; +} - g_return_val_if_fail(LASSO_IS_LOGOUT(logout), -1); - profile = LASSO_PROFILE(logout); - /* verify logout request */ - if (profile->request == NULL) { - ret = LASSO_PROFILE_ERROR_MISSING_REQUEST; - goto done; - } +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ - /* Set the remote provider id from the request */ - remote_providerID = lasso_node_get_child_content(profile->request, "ProviderID", - NULL, NULL); - if (remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "ProviderID in LogoutRequest not found\n"); - ret = -1; - goto done; - } - profile->remote_providerID = remote_providerID; +static LassoNodeClass *parent_class = NULL; - /* Set LogoutResponse */ - switch (profile->http_request_method) { - case lassoHttpMethodSoap: - profile->response = lasso_logout_response_new(profile->server->providerID, - lassoSamlStatusCodeSuccess, - profile->request, - lassoSignatureTypeWithX509, - lassoSignatureMethodRsaSha1); - break; - case lassoHttpMethodRedirect: - profile->response = lasso_logout_response_new(profile->server->providerID, - lassoSamlStatusCodeSuccess, - profile->request, - lassoSignatureTypeNone, - 0); - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid HTTP request method\n"); - ret = -1; - goto done; - } - if (LASSO_IS_LOGOUT_RESPONSE(profile->response) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Error while building response\n"); - ret = -1; - goto done; - } +static void check_soap_support(gchar *key, LassoProvider *provider, LassoProfile *profile) +{ + GList *supported_profiles; + LassoSamlAssertion *assertion; - /* Get the name identifier */ - nameIdentifier = lasso_node_get_child(profile->request, "NameIdentifier", - NULL, NULL); - if (nameIdentifier == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier not found in logout request\n"); - lasso_profile_set_response_status(profile, lassoLibStatusCodeFederationDoesNotExist); - ret = -1; - goto done; - } + if (strcmp(provider->ProviderID, profile->remote_providerID) == 0) + return; /* original service provider (initiated logout) */ - /* verify authentication */ - if (profile->identity == NULL) { - message(G_LOG_LEVEL_WARNING, "Identity not found\n"); - /* FIXME : use RequestDenied if no identity found ? */ - lasso_profile_set_response_status(profile, lassoSamlStatusCodeRequestDenied); - ret = -1; - goto done; - } - assertion = lasso_session_get_assertion(profile->session, remote_providerID); - if (assertion == NULL) { - message(G_LOG_LEVEL_WARNING, "%s has no assertion\n", remote_providerID); - lasso_profile_set_response_status(profile, lassoSamlStatusCodeRequestDenied); - ret = -1; - goto done; - } - lasso_node_destroy(assertion); - - /* Verify federation */ - federation = lasso_identity_get_federation(profile->identity, remote_providerID); - if (federation == NULL) { - message(G_LOG_LEVEL_WARNING, "No federation for %s\n", remote_providerID); - lasso_profile_set_response_status(profile, lassoLibStatusCodeFederationDoesNotExist); - ret = -1; - goto done; - } + assertion = lasso_session_get_assertion(profile->session, provider->ProviderID); + if (assertion == NULL) + return; /* not authenticated with this provider */ - if (lasso_federation_verify_nameIdentifier(federation, nameIdentifier) == FALSE) { - message(G_LOG_LEVEL_WARNING, "No name identifier for %s\n", remote_providerID); - lasso_profile_set_response_status(profile, lassoLibStatusCodeFederationDoesNotExist); - ret = -1; - goto done; - } + supported_profiles = lasso_provider_get_metadata_list(provider, + "SingleLogoutProtocolProfile"); + while (supported_profiles && strcmp(supported_profiles->data, + LASSO_LIB_PROTOCOL_PROFILE_SLO_SP_SOAP) != 0) + supported_profiles = g_list_next(supported_profiles); - /* 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 (profile->provider_type == lassoProviderTypeIdp && profile->http_request_method == lassoHttpMethodSoap) { - gboolean all_http_soap; - LassoProvider *provider; - gchar *providerID, *protocolProfile; - int i; - - all_http_soap = TRUE; - - for (i = 0; i<profile->server->providers->len; i++) { - provider = g_ptr_array_index(profile->server->providers, i); - providerID = lasso_provider_get_providerID(provider); - - /* if the original service provider then continue */ - if (xmlStrEqual(remote_providerID, providerID)) { - continue; - } - - /* if principal is not authenticated with this remote service provider, continue */ - assertion = lasso_session_get_assertion(profile->session, providerID); - if (assertion == NULL) { - continue; - } - - /* if protocolProfile is SOAP continue else break */ - protocolProfile = lasso_provider_get_singleLogoutProtocolProfile(provider, lassoProviderTypeSp, NULL); - if (protocolProfile == NULL || !xmlStrEqual(protocolProfile, lassoLibProtocolProfileSloSpSoap)) { - all_http_soap = FALSE; - break; - } - if (protocolProfile != NULL) { - xmlFree(protocolProfile); - } - if (providerID != NULL) { - xmlFree(providerID); - } - } + if (supported_profiles) + return; /* provider support profile */ - if (all_http_soap==FALSE) { - lasso_profile_set_response_status(profile, lassoLibStatusCodeUnsupportedProfile); - ret = LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE; - goto done; - } - } + + LASSO_LOGOUT(profile)->private->all_soap = FALSE; +} - /* FIXME : set the status code in response */ - - /* authentication is ok, federation is ok, propagation support is ok, remove federation */ - 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 - * REMARK : if only initial service provider was logged, - * then profile->session->providerIDs->len == 0, - * else profile->session->providerIDs->len >= 1 - */ - if (profile->provider_type == lassoProviderTypeIdp && profile->session->providerIDs->len >= 1) { - logout->initial_remote_providerID = profile->remote_providerID; - logout->initial_request = profile->request; - logout->initial_response = profile->response; - - profile->remote_providerID = NULL; - profile->request = NULL; - profile->response = NULL; - } - done: - if (federation != NULL) { - lasso_federation_destroy(federation); - } +static xmlNode* +get_xmlNode(LassoNode *node) +{ + xmlNode *xmlnode, *t; + LassoLogout *logout = LASSO_LOGOUT(node); - return ret; + xmlnode = parent_class->get_xmlNode(node); + xmlNodeSetName(xmlnode, "Logout"); + xmlSetProp(xmlnode, "LogoutDumpVersion", "2"); + + if (logout->initial_request) { + t = xmlNewTextChild(xmlnode, NULL, "InitialRequest", NULL); + xmlAddChild(t, lasso_node_get_xmlNode(logout->initial_request)); + } + + if (logout->initial_response) { + t = xmlNewTextChild(xmlnode, NULL, "InitialResponse", NULL); + xmlAddChild(t, lasso_node_get_xmlNode(logout->initial_response)); + } + + if (logout->initial_remote_providerID) + xmlNewTextChild(xmlnode, NULL, "InitialRemoteProviderID", + logout->initial_remote_providerID); + + if (logout->providerID_index) { + /* XXX: I don't think is is still necessary */ + } + + return xmlnode; +} + +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) +{ + LassoLogout *logout = LASSO_LOGOUT(node); + xmlNode *t; + + parent_class->init_from_xml(node, xmlnode); + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + if (strcmp(t->name, "InitialRemoteProviderID") == 0) + logout->initial_remote_providerID = xmlNodeGetContent(t); + + /* XXX: restore initial_request and initial_response */ + if (strcmp(t->name, "InitialRequest") == 0) { + /* XXX */ + } + if (strcmp(t->name, "InitialResponse") == 0) { + /* XXX */ + } + + t = t->next; + } } /*****************************************************************************/ @@ -1052,32 +884,33 @@ lasso_logout_validate_request(LassoLogout *logout) /*****************************************************************************/ static void -lasso_logout_dispose(LassoLogout *logout) +dispose(GObject *object) { - if (logout->private->dispose_has_run) { - return; - } - logout->private->dispose_has_run = TRUE; + LassoLogout *logout = LASSO_LOGOUT(object); + if (logout->private->dispose_has_run) { + return; + } + logout->private->dispose_has_run = TRUE; - debug("Logout object 0x%x disposed ...\n", logout); + debug("Logout object 0x%x disposed ...\n", logout); - /* unref reference counted objects */ - lasso_node_destroy(logout->initial_request); - lasso_node_destroy(logout->initial_response); + /* unref reference counted objects */ + /* XXX + lasso_node_destroy(logout->initial_request); + lasso_node_destroy(logout->initial_response); + */ - parent_class->dispose(G_OBJECT(logout)); + G_OBJECT_CLASS(parent_class)->dispose(object); } static void -lasso_logout_finalize(LassoLogout *logout) +finalize(GObject *object) { - debug("Logout object 0x%x finalized ...\n", logout); - - g_free(logout->initial_remote_providerID); - - g_free(logout->private); - - parent_class->finalize(G_OBJECT(logout)); + LassoLogout *logout = LASSO_LOGOUT(object); + debug("Logout object 0x%x finalized ...\n", logout); + g_free(logout->initial_remote_providerID); + g_free(logout->private); + G_OBJECT_CLASS(parent_class)->finalize(object); } /*****************************************************************************/ @@ -1085,53 +918,52 @@ lasso_logout_finalize(LassoLogout *logout) /*****************************************************************************/ static void -lasso_logout_instance_init(GTypeInstance *instance, - gpointer g_class) +instance_init(LassoLogout *logout) { - LassoLogout *logout = LASSO_LOGOUT(instance); + logout->private = g_new(LassoLogoutPrivate, 1); + logout->private->dispose_has_run = FALSE; - logout->private = g_new (LassoLogoutPrivate, 1); - logout->private->dispose_has_run = FALSE; + logout->initial_request = NULL; + logout->initial_response = NULL; + logout->initial_remote_providerID = NULL; - logout->initial_request = NULL; - logout->initial_response = NULL; - logout->initial_remote_providerID = NULL; - - logout->providerID_index = 0; + logout->providerID_index = 0; } static void -lasso_logout_class_init(LassoLogoutClass *class) +class_init(LassoLogoutClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - /* override parent class methods */ - gobject_class->dispose = (void *)lasso_logout_dispose; - gobject_class->finalize = (void *)lasso_logout_finalize; + parent_class = g_type_class_peek_parent(klass); + + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; } -GType lasso_logout_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoLogoutClass), - NULL, - NULL, - (GClassInitFunc) lasso_logout_class_init, - NULL, - NULL, - sizeof(LassoLogout), - 0, - (GInstanceInitFunc) lasso_logout_instance_init, - }; - - this_type = g_type_register_static(LASSO_TYPE_PROFILE, - "LassoLogout", - &this_info, 0); - } - return this_type; +GType +lasso_logout_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoLogoutClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoLogout), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_PROFILE, + "LassoLogout", &this_info, 0); + } + return this_type; } /** @@ -1144,118 +976,45 @@ GType lasso_logout_get_type() { * Return value: a new instance of logout object or NULL **/ LassoLogout* -lasso_logout_new(LassoServer *server, - lassoProviderType provider_type) +lasso_logout_new(LassoServer *server) { - LassoLogout *logout; + LassoLogout *logout; - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); + g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - /* set the logout object */ - logout = g_object_new(LASSO_TYPE_LOGOUT, - "server", lasso_server_copy(server), - "provider_type", provider_type, - NULL); + logout = g_object_new(LASSO_TYPE_LOGOUT, NULL); + LASSO_PROFILE(logout)->server = server; - return logout; + return logout; } LassoLogout* -lasso_logout_new_from_dump(LassoServer *server, - gchar *dump) +lasso_logout_new_from_dump(LassoServer *server, const char *dump) { - LassoLogout *logout; - LassoProfile *profile; - LassoNode *node_dump, *request_node, *response_node; - LassoNode *initial_request_node, *initial_response_node; - gchar *type, *export, *providerID_index_str; - - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - g_return_val_if_fail(dump != NULL, NULL); - - logout = LASSO_LOGOUT(g_object_new(LASSO_TYPE_LOGOUT, - "server", lasso_server_copy(server), - NULL)); - - profile = LASSO_PROFILE(logout); - - node_dump = lasso_node_new_from_dump(dump); - - /* profile attributes */ - profile->nameIdentifier = lasso_node_get_child_content(node_dump, "NameIdentifier", - lassoLassoHRef, NULL); - profile->remote_providerID = lasso_node_get_child_content(node_dump, "RemoteProviderID", - lassoLassoHRef, NULL); - profile->msg_url = lasso_node_get_child_content(node_dump, "MsgUrl", - lassoLassoHRef, NULL); - profile->msg_body = lasso_node_get_child_content(node_dump, "MsgBody", - lassoLassoHRef, NULL); - profile->msg_relayState = lasso_node_get_child_content(node_dump, "MsgRelayState", - lassoLassoHRef, NULL); - - /* rebuild request */ - request_node = lasso_node_get_child(node_dump, "LogoutRequest", lassoLibHRef, NULL); - - if (LASSO_IS_NODE(request_node) == TRUE) { - export = lasso_node_export(request_node); - profile->request = lasso_logout_request_new_from_export(export, - lassoNodeExportTypeXml); - g_free(export); - lasso_node_destroy(request_node); - } - - - /* rebuild response */ - response_node = lasso_node_get_child(node_dump, "LogoutResponse", lassoLibHRef, NULL); - if (response_node != NULL) { - export = lasso_node_export(response_node); - profile->response = lasso_logout_response_new_from_export(export, - lassoNodeExportTypeXml); - g_free(export); - lasso_node_destroy(response_node); - } - - /* provider type */ - type = lasso_node_get_child_content(node_dump, "ProviderType", lassoLassoHRef, NULL); - profile->provider_type = atoi(type); - xmlFree(type); - - /* logout attributes */ - /* Initial logout request */ - initial_request_node = lasso_node_get_child(node_dump, "InitialRequest", lassoLassoHRef, NULL); - if (initial_request_node != NULL) { - request_node = lasso_node_get_child(node_dump, "LogoutRequest", lassoLibHRef, NULL); - export = lasso_node_export(request_node); - profile->request = lasso_logout_request_new_from_export(export, - lassoNodeExportTypeXml); - g_free(export); - lasso_node_destroy(request_node); - } - - /* Initial logout response */ - initial_response_node = lasso_node_get_child(node_dump, "InitialResponse", lassoLassoHRef, NULL); - if (initial_response_node != NULL) { - response_node = lasso_node_get_child(node_dump, "LogoutResponse", lassoLibHRef, NULL); - export = lasso_node_export(response_node); - profile->response = lasso_logout_response_new_from_export(export, - lassoNodeExportTypeXml); - g_free(export); - lasso_node_destroy(response_node); - } + LassoLogout *logout; + xmlDoc *doc; - /* Initial logout remote provider id */ - logout->initial_remote_providerID = lasso_node_get_child_content(node_dump, "InitialRemoteProviderID", lassoLassoHRef, NULL); + logout = lasso_logout_new(server); + doc = xmlParseMemory(dump, strlen(dump)); + init_from_xml(LASSO_NODE(logout), xmlDocGetRootElement(doc)); - /* index provider id */ - - providerID_index_str = lasso_node_get_child_content(node_dump, "ProviderIDIndex", NULL, NULL); - - if (providerID_index_str == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Index ProviderID not found\n"); - } - else { - logout->providerID_index = atoi(providerID_index_str); - } + return logout; +} - return logout; +/** + * lasso_logout_dump: + * @logout: the logout object + * + * This method dumps the logout object in string a xml message. + * it first adds profile informations. + * Next, it adds his logout informations (initial_request, initial_response, + * initial_remote_providerID and providerID_index). + * + * Return value: a newly allocated string or NULL + **/ +gchar * +lasso_logout_dump(LassoLogout *logout) +{ + return lasso_node_dump(LASSO_NODE(logout), NULL, 1); } + diff --git a/lasso/id-ff/logout.h b/lasso/id-ff/logout.h index 7c157d41..8f369a3d 100644 --- a/lasso/id-ff/logout.h +++ b/lasso/id-ff/logout.h @@ -31,8 +31,8 @@ extern "C" { #endif /* __cplusplus */ #include <lasso/environs/profile.h> -#include <lasso/protocols/logout_request.h> -#include <lasso/protocols/logout_response.h> +#include <lasso/xml/lib_logout_request.h> +#include <lasso/xml/lib_logout_response.h> #define LASSO_TYPE_LOGOUT (lasso_logout_get_type()) #define LASSO_LOGOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_LOGOUT, LassoLogout)) @@ -46,31 +46,28 @@ typedef struct _LassoLogoutClass LassoLogoutClass; typedef struct _LassoLogoutPrivate LassoLogoutPrivate; struct _LassoLogout { - LassoProfile parent; + LassoProfile parent; - /*< public >*/ - - /*< private >*/ - LassoNode *initial_request; - LassoNode *initial_response; - gchar *initial_remote_providerID; - - gint providerID_index; - - LassoLogoutPrivate *private; + /*< private >*/ + LassoNode *initial_request; + LassoNode *initial_response; + gchar *initial_remote_providerID; + gint providerID_index; + lassoHttpMethod initial_http_request_method; + + LassoLogoutPrivate *private; }; struct _LassoLogoutClass { - LassoProfileClass parent; + LassoProfileClass parent; }; LASSO_EXPORT GType lasso_logout_get_type (void); -LASSO_EXPORT LassoLogout* lasso_logout_new (LassoServer *server, - lassoProviderType provider_type); +LASSO_EXPORT LassoLogout* lasso_logout_new (LassoServer *server); -LASSO_EXPORT LassoLogout* lasso_logout_new_from_dump (LassoServer *server, gchar *dump); +LASSO_EXPORT LassoLogout* lasso_logout_new_from_dump(LassoServer *server, const gchar *dump); LASSO_EXPORT gint lasso_logout_build_request_msg (LassoLogout *logout); @@ -87,12 +84,10 @@ LASSO_EXPORT gint lasso_logout_init_request (LassoLogout *l lassoHttpMethod request_method); LASSO_EXPORT gint lasso_logout_process_request_msg (LassoLogout *logout, - gchar *request_msg, - lassoHttpMethod request_method); + gchar *request_msg); LASSO_EXPORT gint lasso_logout_process_response_msg (LassoLogout *logout, - gchar *response_msg, - lassoHttpMethod response_method); + gchar *response_msg); LASSO_EXPORT gint lasso_logout_reset_providerID_index (LassoLogout *logout); diff --git a/lasso/id-ff/name_identifier_mapping.c b/lasso/id-ff/name_identifier_mapping.c index 48baafc9..6c9dc751 100644 --- a/lasso/id-ff/name_identifier_mapping.c +++ b/lasso/id-ff/name_identifier_mapping.c @@ -31,555 +31,442 @@ /* public methods */ /*****************************************************************************/ -gchar * -lasso_name_identifier_mapping_dump(LassoNameIdentifierMapping *mapping) -{ - gchar *dump = NULL; - - g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), NULL); - - return dump; -} - gint lasso_name_identifier_mapping_build_request_msg(LassoNameIdentifierMapping *mapping) { - LassoProfile *profile; - LassoProvider *provider; - xmlChar *protocolProfile; - GError *err = NULL; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), -1); - - profile = LASSO_PROFILE(mapping); - - /* verify the provider type is a service provider type */ - if (profile->provider_type != lassoProviderTypeSp) { - message(G_LOG_LEVEL_CRITICAL, "Build request msg method is forbidden for an IDP\n"); - ret = -1; - goto done; - } - - /* get provider object */ - provider = lasso_server_get_provider_ref(profile->server, - profile->remote_providerID, - NULL); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Provider %s not found\n", profile->remote_providerID); - ret = -1; - goto done; - } - - /* get the prototocol profile of the name identifier mapping request */ - protocolProfile = lasso_provider_get_nameIdentifierMappingProtocolProfile(provider, - lassoProviderTypeIdp, - NULL); - if (protocolProfile == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier mapping protocol profile not found\n"); - ret = -1; - goto done; - } - - /* Build the name identifier mapping request message (SOAP or QUERY type) */ - if(xmlStrEqual(protocolProfile, lassoLibProtocolProfileNimSpHttp)) { - profile->msg_url = lasso_provider_get_soapEndpoint(provider, - lassoProviderTypeIdp, - NULL); - if (profile->msg_url == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier mapping url not found\n"); - ret = -1; - goto done; - } - - profile->msg_body = lasso_node_export_to_soap(profile->request); - if (profile->msg_body == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Error while building name identifier mapping request SOAP message\n"); - ret = -1; - goto done; - } - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid protocol profile\n"); - ret = -1; - goto done; - } - - done: - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + + g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), -1); + + profile = LASSO_PROFILE(mapping); + + /* get provider object */ + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Provider %s not found", profile->remote_providerID); + return -1; + } + + if (remote_provider->role != LASSO_PROVIDER_ROLE_IDP) { + message(G_LOG_LEVEL_CRITICAL, "Build request msg method is forbidden at IDP"); + return -1; + } + + profile->msg_url = lasso_provider_get_metadata_one(remote_provider, "SoapEndpoint"); + if (profile->msg_url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Name identifier mapping url not found"); + return -1; + } + + profile->msg_body = lasso_node_export_to_soap(profile->request); + if (profile->msg_body == NULL) { + message(G_LOG_LEVEL_CRITICAL, + "Error building name identifier mapping request SOAP message"); + return -1; + } + + return 0; } gint lasso_name_identifier_mapping_build_response_msg(LassoNameIdentifierMapping *mapping) { - LassoProfile *profile; - LassoProvider *provider; - xmlChar *protocolProfile; - GError *err = NULL; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), -1); - - profile = LASSO_PROFILE(mapping); - - /* verify the provider type is a service provider type */ - if (profile->provider_type != lassoProviderTypeIdp) { - message(G_LOG_LEVEL_CRITICAL, "Build request msg method is forbidden for an SP\n"); - ret = -1; - goto done; - } - - /* build name identifier mapping response msg */ - switch (profile->http_request_method) { - case lassoHttpMethodSoap: - profile->msg_url = NULL; - profile->msg_body = lasso_node_export_to_soap(profile->response); - break; - case lassoHttpMethodRedirect: - profile->msg_url = lasso_node_export_to_query(profile->response, - profile->server->signature_method, - profile->server->private_key); - profile->msg_body = NULL; - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid http request method\n"); - ret = -1; - goto done; - } - - done: - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + + g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), -1); + + profile = LASSO_PROFILE(mapping); + + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Provider %s not found", profile->remote_providerID); + return -1; + } + + if (remote_provider->role != LASSO_PROVIDER_ROLE_SP) { + message(G_LOG_LEVEL_CRITICAL, "Build response msg method is forbidden at SP"); + return -1; + } + + /* verify the provider type is a service provider type */ + /* build name identifier mapping response msg */ + if (profile->http_request_method != LASSO_HTTP_METHOD_SOAP) { + message(G_LOG_LEVEL_CRITICAL, "Invalid http request method"); + return -1; + } + + profile->msg_url = NULL; + profile->msg_body = lasso_node_export_to_soap(profile->response); + + return 0; } void lasso_name_identifier_mapping_destroy(LassoNameIdentifierMapping *mapping) { - g_object_unref(G_OBJECT(mapping)); + g_object_unref(G_OBJECT(mapping)); } gint lasso_name_identifier_mapping_init_request(LassoNameIdentifierMapping *mapping, - gchar *targetNameSpace, - gchar *remote_providerID) + char *targetNamespace, char *remote_providerID) { - LassoProfile *profile; - LassoNode *nameIdentifier; - LassoProvider *provider; - LassoFederation *federation; - xmlChar *content, *nameQualifier, *format, *nameIdentifierMappingProtocolProfile; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), -1); - g_return_val_if_fail(targetNameSpace != NULL, -1); - - profile = LASSO_PROFILE(mapping); - - /* verify the provider type is a service provider type */ - if (profile->provider_type != lassoProviderTypeSp) { - message(G_LOG_LEVEL_CRITICAL, "Init request method is forbidden for an IDP\n"); - ret = -1; - goto done; - } - - /* verify if the identity exists */ - if (profile->identity == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Identity not found\n"); - ret = -1; - goto done; - } - - /* set the remote provider id */ - if (remote_providerID == NULL) { - profile->remote_providerID = lasso_identity_get_first_providerID(profile->identity); - } - else { - profile->remote_providerID = g_strdup(remote_providerID); - } - if (profile->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Remote provider id not found\n"); - ret = -1; - goto done; - } - - /* get federation */ - federation = lasso_identity_get_federation(profile->identity, profile->remote_providerID); - if(federation == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Federation not found\n"); - ret = -1; - goto done; - } - /* get the name identifier */ - nameIdentifier = LASSO_NODE(lasso_federation_get_local_nameIdentifier(federation)); - if(nameIdentifier == NULL) { - nameIdentifier = LASSO_NODE(lasso_federation_get_remote_nameIdentifier(federation)); - } - if (nameIdentifier == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier not found\n"); - ret = -1; - goto done; - } - lasso_federation_destroy(federation); - - /* get content and attributes of name identifier */ - content = lasso_node_get_content(nameIdentifier, NULL); - nameQualifier = lasso_node_get_attr_value(nameIdentifier, "NameQualifier", NULL); - format = lasso_node_get_attr_value(nameIdentifier, "Format", NULL); - if (content == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Content of name identifier not found\n"); - ret = -1; - goto done; - } - - /* get protocol profile */ - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, NULL); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Provider %s not found\n", profile->remote_providerID); - ret = -1; - goto done; - } - - nameIdentifierMappingProtocolProfile = lasso_provider_get_nameIdentifierMappingProtocolProfile(provider, - lassoProviderTypeIdp, - NULL); - if (nameIdentifierMappingProtocolProfile == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier mapping protocol profile not found\n"); - ret = -1; - goto done; - } - - /* build the request */ - if (xmlStrEqual(nameIdentifierMappingProtocolProfile, lassoLibProtocolProfileNimSpHttp)) { - profile->request = lasso_name_identifier_mapping_request_new(profile->server->providerID, - content, - nameQualifier, - format, - targetNameSpace, - lassoSignatureTypeWithX509, - lassoSignatureMethodRsaSha1); - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid name identifier mapping protocol profile\n"); - ret = -1; - goto done; - } - - done: - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoFederation *federation; + LassoSamlNameIdentifier *nameIdentifier; + + g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(targetNamespace != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(mapping); + + /* verify if the identity exists */ + if (profile->identity == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + return -1; + } + + /* set the remote provider id */ + if (remote_providerID == NULL) + g_assert_not_reached(); /* was default; didn't make sense */ + profile->remote_providerID = g_strdup(remote_providerID); + + /* verify the provider type is a service provider type */ + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + if (remote_provider->role != LASSO_PROVIDER_ROLE_IDP) { + message(G_LOG_LEVEL_CRITICAL, "Init request method is forbidden for an IDP"); + return -1; + } + + /* get federation */ + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if(federation == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + return -1; + } + + /* name identifier */ + nameIdentifier = federation->local_nameIdentifier; + if (nameIdentifier == NULL) + nameIdentifier = federation->remote_nameIdentifier; + if (nameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Name identifier not found"); + return -1; + } + + /* get / verify http method */ + profile->http_request_method = LASSO_HTTP_METHOD_NONE; + if (lasso_provider_accept_http_method(LASSO_PROVIDER(profile->server), + remote_provider, + LASSO_MD_PROTOCOL_TYPE_NAME_IDENTIFIER_MAPPING, + LASSO_HTTP_METHOD_REDIRECT, TRUE) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "unsupported profile!"); + return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } + + profile->request = lasso_lib_name_identifier_mapping_request_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + nameIdentifier, + targetNamespace, + LASSO_SIGNATURE_TYPE_WITHX509, + LASSO_SIGNATURE_METHOD_RSA_SHA1); + if (LASSO_IS_LIB_NAME_IDENTIFIER_MAPPING_REQUEST(profile->request) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Invalid request"); + return -1; + } + + profile->http_request_method = LASSO_HTTP_METHOD_SOAP; + + return 0; } gint lasso_name_identifier_mapping_process_request_msg(LassoNameIdentifierMapping *mapping, - gchar *request_msg, - lassoHttpMethod request_method) + char *request_msg) { - LassoProfile *profile; - LassoFederation *federation; - LassoNode *nameIdentifier; - LassoNode *statusCode; - LassoNodeClass *statusCode_class; - xmlChar *remote_providerID; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), -1); - g_return_val_if_fail(request_msg != NULL, -1); - - profile = LASSO_PROFILE(mapping); - - switch(request_method){ - case lassoHttpMethodRedirect: - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_QUERY)); - ret = LASSO_PROFILE_ERROR_INVALID_QUERY; - goto done; - break; - case lassoHttpMethodSoap: - profile->request = lasso_name_identifier_mapping_request_new_from_export(request_msg, lassoNodeExportTypeSoap); - if (LASSO_IS_NAME_IDENTIFIER_MAPPING_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG)); - ret = LASSO_PROFILE_ERROR_INVALID_SOAP_MSG; - goto done; - } - break; - default: - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - ret = LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - goto done; - } - - /* set the http request method */ - profile->http_request_method = request_method; - - /* NameIdentifier */ - profile->nameIdentifier = lasso_node_get_child_content(profile->request, - "NameIdentifier", NULL, NULL); - - done: - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoMessageFormat format; + + g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(request_msg != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(mapping); + + /* build name identifier mapping from message */ + profile->request = lasso_lib_name_identifier_mapping_request_new(); + format = lasso_node_init_from_message(profile->request, request_msg); + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_INVALID_MSG; + } + + remote_provider = g_hash_table_lookup(profile->server->providers, + LASSO_LIB_NAME_IDENTIFIER_MAPPING_REQUEST(profile->request)->ProviderID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Unknown provider"); + return -1; + } + profile->remote_providerID = g_strdup(remote_provider->ProviderID); + + /* verify http method is supported */ + if (lasso_provider_accept_http_method(LASSO_PROVIDER(profile->server), + remote_provider, + LASSO_MD_PROTOCOL_TYPE_NAME_IDENTIFIER_MAPPING, + LASSO_HTTP_METHOD_REDIRECT, FALSE) == FALSE ) { + message(G_LOG_LEVEL_CRITICAL, "unsupported profile!"); + return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } + + /* verify signature */ + profile->signature_status = lasso_provider_verify_signature( + remote_provider, request_msg, "RequestID"); + + profile->http_request_method = LASSO_HTTP_METHOD_SOAP; + + profile->nameIdentifier = g_strdup(LASSO_LIB_NAME_IDENTIFIER_MAPPING_REQUEST( + profile->request)->NameIdentifier->content); + + return profile->signature_status; } gint lasso_name_identifier_mapping_process_response_msg(LassoNameIdentifierMapping *mapping, - gchar *response_msg, - lassoHttpMethod response_method) + char *response_msg) { - LassoProfile *profile; - xmlChar *statusCodeValue; - LassoNode *statusCode; - GError *err = NULL; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), -1); - g_return_val_if_fail(response_msg != NULL, -1); - - profile = LASSO_PROFILE(mapping); - - switch(response_method){ - case lassoHttpMethodSoap: - profile->response = lasso_name_identifier_mapping_response_new_from_export(response_msg, lassoNodeExportTypeSoap); - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid response method\n"); - ret = -1; - goto done; - } - if (LASSO_IS_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Error while building NameIdentifierMappingResponse message\n"); - ret = -1; - goto done; - } - - /* Verify the status code value */ - statusCode = lasso_node_get_child(profile->response, "StatusCode", NULL, NULL); - if (statusCode == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Status code not found\n"); - ret = -1; - goto done; - } - statusCodeValue = lasso_node_get_attr_value(statusCode, "Value", NULL); - if (statusCodeValue == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Status code value not found\n"); - ret = -1; - goto done; - } - if (xmlStrEqual(statusCodeValue, lassoLibStatusCodeFederationDoesNotExist)) { - message(G_LOG_LEVEL_CRITICAL, "Status code : Federation does not exists\n"); - ret = -1; - goto done; - } - else if (xmlStrEqual(statusCodeValue, lassoLibStatusCodeUnknownPrincipal)) { - message(G_LOG_LEVEL_CRITICAL, "Status code : Unknown Principal\n"); - ret = -1; - goto done; - } - - /* Set the target name identifier */ - mapping->targetNameIdentifier = lasso_node_get_child_content(profile->response, "NameIdentifier", NULL, NULL); - - done: - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoMessageFormat format; + int rc; + char *statusCodeValue; + + g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(mapping); + + profile->response = lasso_lib_name_identifier_mapping_response_new(); + format = lasso_node_init_from_message(profile->response, response_msg); + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_INVALID_MSG; + } + + remote_provider = g_hash_table_lookup(profile->server->providers, + LASSO_LIB_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response)->ProviderID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + + /* verify signature */ + rc = lasso_provider_verify_signature(remote_provider, response_msg, "ResponseID"); + + statusCodeValue = LASSO_LIB_NAME_IDENTIFIER_MAPPING_RESPONSE( + profile->response)->Status->StatusCode->Value; + if (strcmp(statusCodeValue, LASSO_SAML_STATUS_CODE_SUCCESS) != 0) { + message(G_LOG_LEVEL_CRITICAL, "%s", statusCodeValue); + return -1; + } + + /* Set the target name identifier */ + mapping->targetNameIdentifier = g_strdup(LASSO_LIB_NAME_IDENTIFIER_MAPPING_REQUEST( + profile->request)->NameIdentifier->content); + + return 0; } gint lasso_name_identifier_mapping_validate_request(LassoNameIdentifierMapping *mapping) { - LassoProfile *profile = NULL; - LassoFederation *federation = NULL; - LassoNode *nameIdentifier = NULL, *targetNameIdentifier = NULL; - gchar *remote_providerID = NULL, *targetNameSpace = NULL; - gint ret = 0; - gint remote_provider_type; - - g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping) == TRUE, -1); - - profile = LASSO_PROFILE(mapping); - - /* verify the provider type is a service provider type */ - if (profile->provider_type != lassoProviderTypeIdp) { - message(G_LOG_LEVEL_CRITICAL, "Build request msg method is forbidden for an SP\n"); - ret = -1; - goto done; - } - - /* verify request attribute of mapping is a name identifier mapping request */ - if (LASSO_IS_NAME_IDENTIFIER_MAPPING_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Invalid NameIdentifierMappingRequest\n"); - ret = -1; - goto done; - } - - /* set the name identifier mapping response object */ - switch (profile->http_request_method) { - case lassoHttpMethodSoap: - profile->response = lasso_name_identifier_mapping_response_new(profile->server->providerID, - (gchar *)lassoSamlStatusCodeSuccess, - profile->request, - lassoSignatureTypeWithX509, - lassoSignatureMethodRsaSha1); - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid HTTP request method\n"); - ret = -1; - goto done; - } - if (LASSO_IS_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Error while building NameIdentifierMappingResponse\n"); - ret = -1; - goto done; - } - - /* set the remote provider id from the request */ - profile->remote_providerID = lasso_node_get_child_content(profile->request, - "ProviderID", - NULL, - NULL); - if (profile->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Remote provider id not found\n"); - ret = -1; - goto done; - } - - /* Verify identity attribute of mapping object */ - if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Identity not found\n"); - ret = -1; - goto done; - } - - /* verify federation of the SP request */ - federation = lasso_identity_get_federation_ref(profile->identity, profile->remote_providerID); - if (LASSO_IS_FEDERATION(federation) == FALSE) { - lasso_name_identifier_mapping_response_set_status_code_value(LASSO_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response), - lassoLibStatusCodeUnknownPrincipal); - message(G_LOG_LEVEL_CRITICAL, "Federation not found\n"); - ret = -1; - goto done; - } - nameIdentifier = lasso_federation_get_remote_nameIdentifier(federation); - if (nameIdentifier == NULL) { - nameIdentifier = lasso_federation_get_local_nameIdentifier(federation); - } - if (nameIdentifier == NULL) { - lasso_name_identifier_mapping_response_set_status_code_value(LASSO_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response), - lassoLibStatusCodeUnknownPrincipal); - message(G_LOG_LEVEL_CRITICAL, "Name identifier of federation not found\n"); - ret = -1; - goto done; - } - lasso_node_destroy(nameIdentifier); - - /* get the federation of the target name space and his name identifier */ - targetNameSpace = lasso_node_get_child_content(profile->request, "TargetNameSpace", NULL, NULL); - if (targetNameSpace == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Target name space not found\n"); - ret = -1; - goto done; - } - federation = lasso_identity_get_federation_ref(profile->identity, targetNameSpace); - if (LASSO_IS_FEDERATION(federation) == FALSE) { - lasso_name_identifier_mapping_response_set_status_code_value(LASSO_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response), - lassoLibStatusCodeFederationDoesNotExist); - message(G_LOG_LEVEL_CRITICAL, "Target name space federation not found\n"); - ret = -1; - goto done; - } - targetNameIdentifier = lasso_federation_get_remote_nameIdentifier(federation); - if (targetNameIdentifier == NULL) { - targetNameIdentifier = lasso_federation_get_local_nameIdentifier(federation); - } - if (targetNameIdentifier == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name identifier for target name space federation not found\n"); - lasso_name_identifier_mapping_response_set_status_code_value(LASSO_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response), - lassoLibStatusCodeFederationDoesNotExist); - ret = -1; - goto done; - } - lasso_lib_name_identifier_mapping_response_set_nameIdentifier(LASSO_LIB_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response), - LASSO_SAML_NAME_IDENTIFIER(targetNameIdentifier)); - - done: - if (nameIdentifier != NULL) { - lasso_node_destroy(nameIdentifier); - } - if (targetNameIdentifier != NULL) { - lasso_node_destroy(targetNameIdentifier); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoFederation *federation; + LassoLibNameIdentifierMappingRequest *request; + LassoSamlNameIdentifier *nameIdentifier, *targetNameIdentifier; + + g_return_val_if_fail(LASSO_IS_NAME_IDENTIFIER_MAPPING(mapping) == TRUE, + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_PROFILE(mapping); + + /* verify the provider type is a service provider type */ + if (profile->remote_providerID == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Remote provider id not found"); + return -1; + } + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider->role != LASSO_PROVIDER_ROLE_SP) { + message(G_LOG_LEVEL_CRITICAL, "Build request msg method is forbidden at SP"); + return -1; + } + + /* verify request attribute of mapping is a name identifier mapping request */ + if (LASSO_IS_LIB_NAME_IDENTIFIER_MAPPING_REQUEST(profile->request) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Invalid NameIdentifierMappingRequest"); + return -1; + } + + if (profile->http_request_method != LASSO_HTTP_METHOD_SOAP) { + message(G_LOG_LEVEL_CRITICAL, "Invalid HTTP request method"); + return -1; + } + + request = LASSO_LIB_NAME_IDENTIFIER_MAPPING_REQUEST(profile->request); + + profile->response = lasso_lib_name_identifier_mapping_response_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + LASSO_SAML_STATUS_CODE_SUCCESS, + request, + LASSO_SIGNATURE_TYPE_WITHX509, + LASSO_SIGNATURE_METHOD_RSA_SHA1); + + if (LASSO_IS_LIB_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Error building NameIdentifierMappingResponse"); + return -1; + } + + /* verify signature status */ + if (profile->signature_status != 0) { + lasso_profile_set_response_status(profile, LASSO_LIB_STATUS_CODE_INVALID_SIGNATURE); + } + + /* Verify identity attribute of mapping object */ + if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + return -1; + } + + /* verify federation of the SP request */ + federation = g_hash_table_lookup(profile->identity->federations, profile->remote_providerID); + if (LASSO_IS_FEDERATION(federation) == FALSE) { + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_UNKNOWN_PRINCIPAL); + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + return -1; + } + nameIdentifier = federation->remote_nameIdentifier; + if (nameIdentifier == NULL) + nameIdentifier = federation->local_nameIdentifier; + + if (nameIdentifier == NULL) { + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_UNKNOWN_PRINCIPAL); + message(G_LOG_LEVEL_CRITICAL, "Name identifier of federation not found"); + return -1; + } + + /* get the federation of the target name space and his name identifier */ + if (request->TargetNamespace == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Target name space not found"); + return -1; + } + federation = g_hash_table_lookup(profile->identity->federations, request->TargetNamespace); + if (LASSO_IS_FEDERATION(federation) == FALSE) { + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + message(G_LOG_LEVEL_CRITICAL, "Target name space federation not found"); + return -1; + } + + targetNameIdentifier = federation->remote_nameIdentifier; + if (targetNameIdentifier == NULL) { + targetNameIdentifier = federation->local_nameIdentifier; + } + + if (targetNameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, + "Name identifier for target name space federation not found"); + lasso_profile_set_response_status(profile, + LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST); + return -1; + } + + LASSO_LIB_NAME_IDENTIFIER_MAPPING_RESPONSE(profile->response)->NameIdentifier = + g_object_ref(targetNameIdentifier); + + return 0; } + + /*****************************************************************************/ /* instance and class init functions */ /*****************************************************************************/ static void -lasso_name_identifier_mapping_instance_init(LassoNameIdentifierMapping *name_identifier_mapping) +instance_init(LassoNameIdentifierMapping *name_identifier_mapping) { } static void -lasso_name_identifier_mapping_class_init(LassoNameIdentifierMappingClass *klass) +class_init(LassoNameIdentifierMappingClass *klass) { } -GType lasso_name_identifier_mapping_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoNameIdentifierMappingClass), - NULL, - NULL, - (GClassInitFunc) lasso_name_identifier_mapping_class_init, - NULL, - NULL, - sizeof(LassoNameIdentifierMapping), - 0, - (GInstanceInitFunc) lasso_name_identifier_mapping_instance_init, - }; - - this_type = g_type_register_static(LASSO_TYPE_PROFILE, - "LassoNameIdentifierMapping", - &this_info, 0); - } - return this_type; +GType +lasso_name_identifier_mapping_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoNameIdentifierMappingClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoNameIdentifierMapping), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_PROFILE, + "LassoNameIdentifierMapping", &this_info, 0); + } + return this_type; } LassoNameIdentifierMapping * -lasso_name_identifier_mapping_new(LassoServer *server, - lassoProviderType provider_type) +lasso_name_identifier_mapping_new(LassoServer *server) { - LassoNameIdentifierMapping *mapping; + LassoNameIdentifierMapping *mapping = NULL; + + g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - g_return_val_if_fail((provider_type == lassoProviderTypeSp) || (provider_type == lassoProviderTypeIdp), NULL); + mapping = g_object_new(LASSO_TYPE_NAME_IDENTIFIER_MAPPING, NULL); + LASSO_PROFILE(mapping)->server = server; - /* set the name_identifier_mapping object */ - mapping = g_object_new(LASSO_TYPE_NAME_IDENTIFIER_MAPPING, - "server", lasso_server_copy(server), - "provider_type", provider_type, - NULL); - return mapping; + return mapping; } -LassoNameIdentifierMapping * -lasso_name_identifier_mapping_new_from_dump(LassoServer *server, - gchar *dump) +LassoNameIdentifierMapping* +lasso_name_identifier_mapping_new_from_dump(LassoServer *server, gchar *dump) { - LassoNameIdentifierMapping *mapping; - LassoNode *node_dump; - - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - g_return_val_if_fail(dump != NULL, NULL); - - mapping = g_object_new(LASSO_TYPE_NAME_IDENTIFIER_MAPPING, - "server", lasso_server_copy(server), - NULL); - - node_dump = lasso_node_new_from_dump(dump); + g_assert_not_reached(); + return NULL; +} - return mapping; +char* +lasso_name_identifier_mapping_dump(LassoNameIdentifierMapping *mapping) +{ + g_assert_not_reached(); + return lasso_node_dump(LASSO_NODE(mapping), NULL, 1); } + diff --git a/lasso/id-ff/name_identifier_mapping.h b/lasso/id-ff/name_identifier_mapping.h index 9320d006..7f4f9de4 100644 --- a/lasso/id-ff/name_identifier_mapping.h +++ b/lasso/id-ff/name_identifier_mapping.h @@ -32,8 +32,8 @@ extern "C" { #include <lasso/environs/profile.h> -#include <lasso/protocols/name_identifier_mapping_request.h> -#include <lasso/protocols/name_identifier_mapping_response.h> +#include <lasso/xml/lib_name_identifier_mapping_request.h> +#include <lasso/xml/lib_name_identifier_mapping_response.h> #define LASSO_TYPE_NAME_IDENTIFIER_MAPPING (lasso_name_identifier_mapping_get_type()) #define LASSO_NAME_IDENTIFIER_MAPPING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_NAME_IDENTIFIER_MAPPING, LassoNameIdentifierMapping)) @@ -46,22 +46,18 @@ typedef struct _LassoNameIdentifierMapping LassoNameIdentifierMapping; typedef struct _LassoNameIdentifierMappingClass LassoNameIdentifierMappingClass; struct _LassoNameIdentifierMapping { - LassoProfile parent; - - gchar *targetNameIdentifier; - - /*< private >*/ + LassoProfile parent; + gchar *targetNameIdentifier; }; struct _LassoNameIdentifierMappingClass { - LassoProfileClass parent; - + LassoProfileClass parent; }; LASSO_EXPORT GType lasso_name_identifier_mapping_get_type (void); -LASSO_EXPORT LassoNameIdentifierMapping* lasso_name_identifier_mapping_new (LassoServer *server, - lassoProviderType provider_type); +LASSO_EXPORT LassoNameIdentifierMapping* lasso_name_identifier_mapping_new(LassoServer *server); +LASSO_EXPORT gchar * lasso_name_identifier_mapping_dump(LassoNameIdentifierMapping*); LASSO_EXPORT gint lasso_name_identifier_mapping_build_request_msg (LassoNameIdentifierMapping *mapping); @@ -74,12 +70,10 @@ LASSO_EXPORT gint lasso_name_identifier_mapping_init_requ gchar *remote_providerID); LASSO_EXPORT gint lasso_name_identifier_mapping_process_request_msg (LassoNameIdentifierMapping *mapping, - gchar *request_msg, - lassoHttpMethod request_method); + gchar *request_msg); LASSO_EXPORT gint lasso_name_identifier_mapping_process_response_msg (LassoNameIdentifierMapping *mapping, - gchar *response_msg, - lassoHttpMethod response_method); + gchar *response_msg); LASSO_EXPORT gint lasso_name_identifier_mapping_validate_request (LassoNameIdentifierMapping *mapping); diff --git a/lasso/id-ff/name_registration.c b/lasso/id-ff/name_registration.c index ebaa3877..bdccff8a 100644 --- a/lasso/id-ff/name_registration.c +++ b/lasso/id-ff/name_registration.c @@ -30,729 +30,549 @@ #include <lasso/xml/errors.h> -static GObjectClass *parent_class = NULL; - /*****************************************************************************/ /* public methods */ /*****************************************************************************/ /** - * lasso_name_registration_dump: - * @name_registration: the register name identifier object - * - * This method builds a dump of the register name identifier object - * - * Return value: a newly allocated string or NULL - **/ -gchar * -lasso_name_registration_dump(LassoNameRegistration *name_registration) -{ - gchar *dump = NULL, *parent_dump = NULL; - LassoNode *node = NULL; - - g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), NULL); - - parent_dump = lasso_profile_dump(LASSO_PROFILE(name_registration), "NameRegistration"); - node = lasso_node_new_from_dump(parent_dump); - g_free(parent_dump); - - if (name_registration->oldNameIdentifier != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "OldNameIdentifier", - name_registration->oldNameIdentifier, FALSE); - } - - dump = lasso_node_export(node); - - lasso_node_destroy(node); - - return dump; -} - -/** * lasso_name_registration_build_request_msg: * @name_registration: the register name identifier object * * This method build a register name identifier request message. * - * It gets the register name identifier protocol profile and : - * if it is a SOAP method, then it builds the register name identifier request SOAP message, - * optionaly signs his node, set the msg_body attribute, gets the SoapEndpoint - * url and set the msg_url attribute. + * It gets the register name identifier protocol profile and: + * + * - if it is a SOAP method, then it builds the register name identifier + * request SOAP message, optionaly signs his node, set the msg_body + * attribute, gets the SoapEndpoint url and set the msg_url attribute. * - * if it is a HTTP-Redirect method, then it builds the register name identifier request QUERY message - * ( optionaly signs the request message ), builds the request url with register name identifier url - * with register name identifier service url, set the msg_url attribute of the register name identifier - * object, set the msg_body to NULL. + * - if it is a HTTP-Redirect method, then it builds the register name + * identifier request QUERY message (optionaly signs the request message), + * builds the request url with register name identifier url with register + * name identifier service url, set the msg_url attribute of the register + * name identifier object, set the msg_body to NULL. * * Return value: 0 if OK else < 0 **/ gint lasso_name_registration_build_request_msg(LassoNameRegistration *name_registration) { - LassoProfile *profile; - LassoProvider *provider; - xmlChar *protocolProfile = NULL; - GError *err = NULL; - gchar *url = NULL, *query = NULL; - lassoProviderType remote_provider_type; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); + LassoProfile *profile; + LassoProvider *remote_provider; + char *url, *query; + + g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); - profile = LASSO_PROFILE(name_registration); - - /* get the remote provider type and get the remote provider object */ - if (profile->provider_type == lassoProviderTypeSp) { - remote_provider_type = lassoProviderTypeIdp; - } - else if (profile->provider_type == lassoProviderTypeIdp) { - remote_provider_type = lassoProviderTypeSp; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, &err); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - goto done; - } - - /* get the prototocol profile of the name_registration */ - protocolProfile = lasso_provider_get_registerNameIdentifierProtocolProfile(provider, - remote_provider_type, - NULL); - if (protocolProfile == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Name_Registration Protocol profile not found\n"); - ret = -1; - goto done; - } - - /* build the register name identifier request message */ - if (xmlStrEqual(protocolProfile, lassoLibProtocolProfileRniIdpSoap) || \ - xmlStrEqual(protocolProfile, lassoLibProtocolProfileRniSpSoap)) { - profile->request_type = lassoHttpMethodSoap; - /* sign the request message */ - lasso_samlp_request_abstract_set_signature(LASSO_SAMLP_REQUEST_ABSTRACT(profile->request), - profile->server->signature_method, - profile->server->private_key, - profile->server->certificate); - - /* build the registration request message */ - profile->msg_url = lasso_provider_get_soapEndpoint(provider, - remote_provider_type, - NULL); - profile->msg_body = lasso_node_export_to_soap(profile->request); - } - else if (xmlStrEqual(protocolProfile,lassoLibProtocolProfileRniIdpHttp) || \ - xmlStrEqual(protocolProfile,lassoLibProtocolProfileRniSpHttp)) { - /* build and optionaly sign the query message and build the register name identifier request url */ - url = lasso_provider_get_registerNameIdentifierServiceURL(provider, remote_provider_type, NULL); - if (url == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Register name identifier service url not found\n"); - ret = -1; - goto done; - } - - /* Before building the query, rename names of elements and attributes of SPProvidedNameIdentifier, */ - /* IDPProvidedNameIdentifier, OldProvidedNameIdentifier */ - lasso_register_name_identifier_request_rename_attributes_for_query(LASSO_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request)); - query = lasso_node_export_to_query(profile->request, - profile->server->signature_method, - profile->server->private_key); - if (query == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Error wile building register name identifier request query message\n"); - ret = -1; - goto done; - } - - /* build the msg_url */ - profile->msg_url = g_strdup_printf("%s?%s", url, query); - profile->msg_body = NULL; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid register name identifier protocol Profile \n"); - ret = -1; - goto done; - } - - done: - if (protocolProfile != NULL) { - xmlFree(protocolProfile); - } - if (url != NULL) { - xmlFree(url); - } - if (query != NULL) { - xmlFree(query); - } - - return ret; + profile = LASSO_PROFILE(name_registration); + + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + + if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { + /* XXX had call to lasso_samlp_request_abstract_sign_signature_tmpl */ + profile->msg_url = lasso_provider_get_metadata_one(remote_provider, "SoapEndpoint"); + profile->msg_body = lasso_node_export_to_soap(profile->request); + } + if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + /* build and optionaly sign the query message and build the + * register name identifier request url */ + url = lasso_provider_get_metadata_one(remote_provider, + "RegisterNameIdentifierServiceURL"); + if (url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Unknown profile service URL"); + return -1; + } + query = lasso_node_export_to_query(profile->request, + profile->server->signature_method, + profile->server->private_key); + if (query == NULL) { + g_free(url); + message(G_LOG_LEVEL_CRITICAL, "Error building request QUERY url"); + return -1; + } + /* build the msg_url */ + profile->msg_url = g_strdup_printf("%s?%s", url, query); + g_free(url); + g_free(query); + profile->msg_body = NULL; + } + + if (profile->msg_url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Invalid http method\n"); + return LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; + } + + return 0; } gint lasso_name_registration_build_response_msg(LassoNameRegistration *name_registration) { - LassoProfile *profile; - LassoProvider *provider; - xmlChar *protocolProfile; - gchar *url = NULL, *query = NULL; - GError *err = NULL; - lassoProviderType remote_provider_type; - gint ret = 0; + LassoProfile *profile; + LassoProvider *remote_provider; + char *url, *query; - g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); - - profile = LASSO_PROFILE(name_registration); - - /* get the provider */ - provider = lasso_server_get_provider_ref(profile->server, profile->remote_providerID, &err); - if (provider == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - ret = err->code; - g_error_free(err); - return ret; - } - - /* get the remote provider type */ - if (profile->provider_type == lassoProviderTypeSp) { - remote_provider_type = lassoProviderTypeIdp; - } - else if (profile->provider_type == lassoProviderTypeIdp) { - remote_provider_type = lassoProviderTypeSp; - } - else { - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - return -1; - } - - /* build register name identifier message */ - switch (profile->http_request_method) { - case lassoHttpMethodSoap: - profile->msg_url = NULL; - profile->msg_body = lasso_node_export_to_soap(profile->response); - break; - case lassoHttpMethodRedirect: - url = lasso_provider_get_registerNameIdentifierServiceReturnURL(provider, remote_provider_type, NULL); - if (url == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Register name identifier service return url not found\n"); - ret = -1; - goto done; - } - - query = lasso_node_export_to_query(profile->response, - profile->server->signature_method, - profile->server->private_key); - if (query == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Error while building register name identifier response query message\n"); - ret = -1; - goto done; - } - - profile->msg_url = g_strdup_printf("%s?%s", url, query); - profile->msg_body = NULL; - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid HTTP request method\n"); - ret = -1; - goto done; - } - - done: - if (url != NULL) { - g_free(url); - } - if (query != NULL) { - g_free(query); - } - - return 0; + g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); + + profile = LASSO_PROFILE(name_registration); + + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + + if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) { + profile->msg_url = NULL; /* XXX ??? */ + profile->msg_body = lasso_node_export_to_soap(profile->response); + return 0; + } + if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) { + url = lasso_provider_get_metadata_one(remote_provider, + "RegisterNameIdentifierServiceReturnURL"); + if (url == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Unknown profile service URL"); + return -1; + } + query = lasso_node_export_to_query(profile->response, + profile->server->signature_method, + profile->server->private_key); + if (query == NULL) { + g_free(url); + message(G_LOG_LEVEL_CRITICAL, "Error building request QUERY url"); + return -1; + } + /* build the msg_url */ + profile->msg_url = g_strdup_printf("%s?%s", url, query); + g_free(url); + g_free(query); + profile->msg_body = NULL; + + return 0; + } + + message(G_LOG_LEVEL_CRITICAL, "Invalid HTTP request method"); + return -1; } void lasso_name_registration_destroy(LassoNameRegistration *name_registration) { - g_object_unref(G_OBJECT(name_registration)); + g_object_unref(G_OBJECT(name_registration)); } gint lasso_name_registration_init_request(LassoNameRegistration *name_registration, - gchar *remote_providerID) + char *remote_providerID, lassoHttpMethod http_method) { - LassoProfile *profile; - LassoFederation *federation; - LassoNode *remote_nameIdentifier_node = NULL, *local_nameIdentifier_node = NULL; - GError *err = NULL; - LassoProvider *provider = NULL; - - xmlChar *spNameIdentifier = NULL, *spNameQualifier = NULL, *spFormat = NULL; - xmlChar *idpNameIdentifier = NULL, *idpNameQualifier = NULL, *idpFormat = NULL; - xmlChar *oldNameIdentifier = NULL, *oldNameQualifier = NULL, *oldFormat = NULL; - - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); - - profile = LASSO_PROFILE(name_registration); - - /* verify if the identity and session exist */ - if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Identity not found\n"); - ret = -1; - goto done; - } - - /* get the remote provider id */ - /* If remote_providerID is NULL, then get the first remote provider id in identity */ - if (remote_providerID == NULL) { - profile->remote_providerID = lasso_identity_get_first_providerID(profile->identity); - } - else { - profile->remote_providerID = g_strdup(remote_providerID); - } - if (profile->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "No provider id for init request\n"); - ret = -1; - goto done; - } - - /* Get federation */ - federation = lasso_identity_get_federation_ref(profile->identity, profile->remote_providerID); - if (LASSO_IS_FEDERATION(federation) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Federation not found\n"); - ret = -1; - goto done; - } - - /* FIXME : depending on the requester provider type, verify the format of the old name identifier is only federated type */ - - switch (profile->provider_type) { - case lassoProviderTypeSp: - /* set the new name identifier */ - spNameIdentifier = lasso_build_unique_id(32); - spNameQualifier = g_strdup(profile->remote_providerID); - spFormat = g_strdup(lassoLibNameIdentifierFormatFederated); - - /* save the new name identifier in profile->nameIdentifier */ - profile->nameIdentifier = g_strdup(spNameIdentifier); - - /* idp name identifier */ - remote_nameIdentifier_node = lasso_federation_get_remote_nameIdentifier(federation); - if (remote_nameIdentifier_node == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Remote NameIdentifier not found\n"); - ret = -1; - goto done; - } - idpNameIdentifier = lasso_node_get_content(remote_nameIdentifier_node, NULL); - idpNameQualifier = lasso_node_get_attr_value(remote_nameIdentifier_node, "NameQualifier", NULL); - idpFormat = lasso_node_get_attr_value(remote_nameIdentifier_node, "Format", NULL); - lasso_node_destroy(remote_nameIdentifier_node); - - /* set the old name identifier */ - local_nameIdentifier_node = lasso_federation_get_local_nameIdentifier(federation); - if (local_nameIdentifier_node != NULL) { - oldNameIdentifier = lasso_node_get_content(local_nameIdentifier_node, NULL); - oldNameQualifier = lasso_node_get_attr_value(local_nameIdentifier_node, "NameQualifier", NULL); - oldFormat = lasso_node_get_attr_value(local_nameIdentifier_node, "Format", NULL); - - /* old name identifier is from SP, name_registration->oldNameIdentifier must be from SP */ - name_registration->oldNameIdentifier = g_strdup(oldNameIdentifier); - } - lasso_node_destroy(local_nameIdentifier_node); - - /* oldNameIdentifier is none, no local name identifier at SP, old is IDP */ - if (oldNameIdentifier == NULL) { - oldNameIdentifier = g_strdup(idpNameIdentifier); - oldNameQualifier = g_strdup(idpNameQualifier); - oldFormat = g_strdup(idpFormat); - - /* old name identifier is from IDP, name_registration->oldNameQualifier must be from IDP */ - name_registration->oldNameIdentifier = g_strdup(idpNameIdentifier); - } - - /* save federation */ - lasso_federation_build_local_nameIdentifier(federation, - spNameQualifier, - lassoLibNameIdentifierFormatFederated, - spNameIdentifier); - profile->identity->is_dirty = TRUE; - break; - - case lassoProviderTypeIdp: - idpNameIdentifier = lasso_build_unique_id(32); - idpNameQualifier = g_strdup(profile->remote_providerID); - idpFormat = g_strdup(lassoLibNameIdentifierFormatFederated); - - /* save the new name identifier in profile->nameIdentifier */ - profile->nameIdentifier = g_strdup(idpNameIdentifier); - - /* set old provided name identifier */ - local_nameIdentifier_node = lasso_federation_get_local_nameIdentifier(federation); - if (local_nameIdentifier_node == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Local name identifier not found\n"); - ret = -1; - goto done; - } - oldNameIdentifier = lasso_node_get_content(local_nameIdentifier_node, NULL); - oldNameQualifier = lasso_node_get_attr_value(local_nameIdentifier_node, "NameQualifier", NULL); - oldFormat = lasso_node_get_attr_value(local_nameIdentifier_node, "Format", NULL); - lasso_node_destroy(local_nameIdentifier_node); - - /* set sp provided name identifier */ - spNameIdentifier = NULL; - spNameQualifier = NULL; - spFormat = NULL; - remote_nameIdentifier_node = lasso_federation_get_remote_nameIdentifier(federation); - if (remote_nameIdentifier_node != NULL) { - spNameIdentifier = lasso_node_get_content(remote_nameIdentifier_node, NULL); - spNameQualifier = lasso_node_get_attr_value(remote_nameIdentifier_node, "NameQualifier", NULL); - spFormat = lasso_node_get_attr_value(remote_nameIdentifier_node, "Format", NULL); - lasso_node_destroy(remote_nameIdentifier_node); - - /* name identifier from SP exists, oldNameIdentifier must be from SP */ - name_registration->oldNameIdentifier = NULL; - xmlFree(profile->nameIdentifier); - profile->nameIdentifier = NULL; - } - else { - /* name identifier from SP exists, oldNameIdentifier must be from SP */ - name_registration->oldNameIdentifier = g_strdup(oldNameIdentifier); - } - - /* save federation */ - lasso_federation_build_local_nameIdentifier(federation, - idpNameQualifier, - lassoLibNameIdentifierFormatFederated, - idpNameIdentifier); - profile->identity->is_dirty = TRUE; - break; - - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - - /* build a new request object from single logout protocol profile */ - profile->request = lasso_register_name_identifier_request_new(profile->server->providerID, - idpNameIdentifier, - idpNameQualifier, - idpFormat, - spNameIdentifier, - spNameQualifier, - spFormat, - oldNameIdentifier, - oldNameQualifier, - oldFormat); - if (profile->request == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Error while creating the request\n"); - ret = -1; - goto done; - } - - done: - if (idpNameIdentifier != NULL) { - xmlFree(idpNameIdentifier); - } - if (idpNameQualifier != NULL) { - xmlFree(idpNameQualifier); - } - if (idpFormat != NULL) { - xmlFree(idpFormat); - } - - if (spNameIdentifier != NULL) { - xmlFree(spNameIdentifier); - } - if (spNameQualifier != NULL) { - xmlFree(spNameQualifier); - } - if (spFormat != NULL) { - xmlFree(spFormat); - } - - if (oldNameIdentifier != NULL) { - xmlFree(oldNameIdentifier); - } - if (oldNameQualifier != NULL) { - xmlFree(oldNameQualifier); - } - if (oldFormat != NULL) { - xmlFree(oldFormat); - } - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoFederation *federation; + LassoSamlNameIdentifier *spNameIdentifier, *idpNameIdentifier, *oldNameIdentifier = NULL; + + g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); + + profile = LASSO_PROFILE(name_registration); + + /* verify if the identity and session exist */ + if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + return -1; + } + + /* set the remote provider id */ + if (remote_providerID == NULL) + g_assert_not_reached(); /* was default; didn't make sense */ + + profile->remote_providerID = g_strdup(remote_providerID); + + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + + /* Get federation */ + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (LASSO_IS_FEDERATION(federation) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + return -1; + } + + /* FIXME : depending on the requester provider type, verify the format + * of the old name identifier is only federated type */ + + if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) { + spNameIdentifier = lasso_saml_name_identifier_new(); + spNameIdentifier->content = lasso_build_unique_id(32); + spNameIdentifier->NameQualifier = g_strdup(profile->remote_providerID); + spNameIdentifier->Format = g_strdup(LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED); + + idpNameIdentifier = g_object_ref(federation->remote_nameIdentifier); + + if (federation->local_nameIdentifier) { + /* old name identifier is from SP, + * name_registration->oldNameIdentifier must be from SP */ + oldNameIdentifier = g_object_ref(federation->local_nameIdentifier); + } else { + /* oldNameIdentifier is none, no local name identifier at SP, old is IDP */ + oldNameIdentifier = g_object_ref(idpNameIdentifier); + } + + profile->nameIdentifier = g_strdup(spNameIdentifier->content); + name_registration->oldNameIdentifier = g_strdup(oldNameIdentifier->content); + } + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { + if (federation->local_nameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Local name identifier not found"); + return -1; + } + + oldNameIdentifier = g_object_ref(federation->local_nameIdentifier); + + spNameIdentifier = NULL; + if (federation->remote_nameIdentifier) { + spNameIdentifier = g_object_ref(federation->remote_nameIdentifier); + } + + idpNameIdentifier = lasso_saml_name_identifier_new(); + idpNameIdentifier->content = lasso_build_unique_id(32); + idpNameIdentifier->NameQualifier = g_strdup(profile->remote_providerID); + idpNameIdentifier->Format = g_strdup(LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED); + + if (spNameIdentifier) { + profile->nameIdentifier = g_strdup(spNameIdentifier->content); + name_registration->oldNameIdentifier = g_strdup(profile->nameIdentifier); + } else { + profile->nameIdentifier = g_strdup(idpNameIdentifier->content); + name_registration->oldNameIdentifier = g_strdup(oldNameIdentifier->content); + } + } + + if (oldNameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Invalid provider type"); + return -1; + } + + 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_REGISTER_NAME_IDENTIFIER); + } else { + if (lasso_provider_accept_http_method(LASSO_PROVIDER(profile->server), + remote_provider, + LASSO_MD_PROTOCOL_TYPE_REGISTER_NAME_IDENTIFIER, + http_method, + TRUE) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "unsupported profile!"); + return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } + } + + profile->request = lasso_lib_register_name_identifier_request_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + idpNameIdentifier, spNameIdentifier, oldNameIdentifier); + if (profile->request == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Error creating the request"); + return -1; + } + + profile->http_request_method = http_method; + + return 0; } gint lasso_name_registration_process_request_msg(LassoNameRegistration *name_registration, - gchar *request_msg, - lassoHttpMethod request_method) + char *request_msg) { - LassoProfile *profile; - gchar *spNameIdentifier; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); - g_return_val_if_fail(request_msg != NULL, -1); - - profile = LASSO_PROFILE(name_registration); - - /* rebuild the request message and optionaly verify the signature */ - switch (request_method) { - case lassoHttpMethodSoap: - profile->request = lasso_register_name_identifier_request_new_from_export(request_msg, lassoNodeExportTypeSoap); - if (LASSO_IS_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG)); - ret = LASSO_PROFILE_ERROR_INVALID_SOAP_MSG; - goto done; - } - break; - case lassoHttpMethodRedirect: - profile->request = lasso_register_name_identifier_request_new_from_export(request_msg, lassoNodeExportTypeQuery); - if (LASSO_IS_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_QUERY)); - ret = LASSO_PROFILE_ERROR_INVALID_QUERY; - goto done; - } - break; - default: - message(G_LOG_LEVEL_CRITICAL, lasso_strerror(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD)); - ret = LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD; - goto done; - } - - /* set the http request method */ - profile->http_request_method = request_method; - - /* set old name identifier */ - switch (profile->provider_type) { - case lassoProviderTypeSp: - /*default, SP provided name identifier for federation and is the only link to session and identity for SP application */ - name_registration->oldNameIdentifier = NULL; - profile->nameIdentifier = NULL; - - /* no sp provided name identifier, only IDP provide name identifier, set nameIdentifier and oldNameIdentifier attributes */ - spNameIdentifier = lasso_node_get_child_content(profile->request, "SPProvidedNameIdentifier", NULL, NULL); - if (spNameIdentifier == NULL) { - profile->nameIdentifier = lasso_node_get_child_content(profile->request, "IDPProvidedNameIdentifier", NULL, NULL); - name_registration->oldNameIdentifier = lasso_node_get_child_content(profile->request, "OldProvidedNameIdentifier", NULL, NULL); - } - else { - name_registration->oldNameIdentifier = spNameIdentifier; - } - break; - - case lassoProviderTypeIdp: - /* default, SP modified provided name identifier, set nameIdentifier, oldNameIdentifier */ - profile->nameIdentifier = lasso_node_get_child_content(profile->request, "SPProvidedNameIdentifier", NULL, NULL); - name_registration->oldNameIdentifier = lasso_node_get_child_content(profile->request, "OldProvidedNameIdentifier", NULL, NULL); - break; - - default: - ret = -1; - goto done; - } - - done : - - return ret; + LassoProfile *profile; + LassoProvider *remote_provider; + LassoMessageFormat format; + LassoSamlNameIdentifier *nameIdentifier; + + g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); + g_return_val_if_fail(request_msg != NULL, -1); + + profile = LASSO_PROFILE(name_registration); + + profile->request = lasso_lib_register_name_identifier_request_new(); + format = lasso_node_init_from_message(profile->request, request_msg); + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_INVALID_MSG; + } + + remote_provider = g_hash_table_lookup(profile->server->providers, + LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request)->ProviderID); + if (LASSO_IS_PROVIDER(remote_provider) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Unknown provider"); + return -1; + } + + 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; + + if (lasso_provider_accept_http_method(LASSO_PROVIDER(profile->server), + remote_provider, + LASSO_MD_PROTOCOL_TYPE_REGISTER_NAME_IDENTIFIER, + profile->http_request_method, FALSE) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE; + } + + nameIdentifier = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST( + profile->request)->SPProvidedNameIdentifier; + if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) { + if (nameIdentifier) { + profile->nameIdentifier = g_strdup(nameIdentifier->content); + name_registration->oldNameIdentifier = g_strdup(profile->nameIdentifier); + } else { + profile->nameIdentifier = g_strdup( + LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST( + profile->request)->IDPProvidedNameIdentifier->content); + name_registration->oldNameIdentifier = g_strdup( + LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST( + profile->request)->OldProvidedNameIdentifier->content); + } + } + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { + profile->nameIdentifier = g_strdup(nameIdentifier->content); + name_registration->oldNameIdentifier = g_strdup( + LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST( + profile->request)->OldProvidedNameIdentifier->content); + } + + + return 0; } gint lasso_name_registration_process_response_msg(LassoNameRegistration *name_registration, - gchar *response_msg, - lassoHttpMethod response_method) + char *response_msg) { - LassoProfile *profile; - LassoFederation *federation; - xmlChar *statusCodeValue; - LassoNode *statusCode; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); - g_return_val_if_fail(response_msg != NULL, -1); - - profile = LASSO_PROFILE(name_registration); - - /* parse NameRegistrationResponse */ - switch (response_method) { - case lassoHttpMethodSoap: - profile->response = lasso_register_name_identifier_response_new_from_export(response_msg, lassoNodeExportTypeSoap); - break; - case lassoHttpMethodRedirect: - profile->response = lasso_register_name_identifier_response_new_from_export(response_msg, lassoNodeExportTypeQuery); - break; - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid response method\n"); - ret = -1; - goto done; - } + LassoProfile *profile; + LassoProvider *remote_provider; + LassoFederation *federation; + LassoSamlNameIdentifier *nameIdentifier = NULL; + lassoHttpMethod response_method; + LassoMessageFormat format; + int rc; + char *statusCodeValue; + + g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); + g_return_val_if_fail(response_msg != NULL, -1); + + profile = LASSO_PROFILE(name_registration); + + /* build register name identifier response from message */ + profile->response = lasso_lib_register_name_identifier_response_new(); + format = lasso_node_init_from_message(profile->response, response_msg); + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return LASSO_PROFILE_ERROR_INVALID_MSG; + } + if (format == LASSO_MESSAGE_FORMAT_SOAP) + response_method = LASSO_HTTP_METHOD_SOAP; + if (format == LASSO_MESSAGE_FORMAT_QUERY) + response_method = LASSO_HTTP_METHOD_REDIRECT; - statusCode = lasso_node_get_child(profile->response, "StatusCode", NULL, NULL); - if (statusCode == NULL) { - message(G_LOG_LEVEL_CRITICAL, "StatusCode not found\n"); - ret = -1; - goto done; - } - statusCodeValue = lasso_node_get_attr_value(statusCode, "Value", NULL); - if (statusCodeValue == NULL) { - message(G_LOG_LEVEL_CRITICAL, "StatusCodeValue not found\n"); - ret = -1; - goto done; - } - - if(!xmlStrEqual(statusCodeValue, lassoSamlStatusCodeSuccess)) { - ret = -1; - goto done; - } - - /* Update federation with the nameIdentifier attribute. NameQualifier is local ProviderID and format is Federated type */ - if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Identity not found\n"); - ret = -1; - goto done; - } - federation = lasso_identity_get_federation_ref(profile->identity, profile->remote_providerID); - if (LASSO_IS_FEDERATION(federation) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Federation not found\n"); - ret = -1; - goto done; - } + remote_provider = g_hash_table_lookup(profile->server->providers, + LASSO_LIB_STATUS_RESPONSE(profile->response)->ProviderID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + + /* verify signature */ + rc = lasso_provider_verify_signature(remote_provider, response_msg, "ResponseID"); + + statusCodeValue = LASSO_LIB_STATUS_RESPONSE(profile->response)->Status->StatusCode->Value; + if (strcmp(statusCodeValue, LASSO_SAML_STATUS_CODE_SUCCESS) != 0) { + message(G_LOG_LEVEL_CRITICAL, "%s", statusCodeValue); + return -1; + } + + /* Update federation with the nameIdentifier attribute. NameQualifier + * is local ProviderID and format is Federated type */ + if (LASSO_IS_IDENTITY(profile->identity) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Identity not found"); + return -1; + } + + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (LASSO_IS_FEDERATION(federation) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + return -1; + } - /* Save new name identifier in federation */ - /* FIXME : use a proper way to set the identity dirty */ -/* if (profile->nameIdentifier == NULL) { */ -/* message(G_LOG_LEVEL_CRITICAL, "NameIdentifier in NameRegistration object not found\n"); */ -/* ret = -1; */ -/* goto done; */ -/* } */ + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Remote provider not found"); + return -1; + } + + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { + nameIdentifier = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST( + profile->request)->IDPProvidedNameIdentifier; + } + if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) { + nameIdentifier = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST( + profile->request)->SPProvidedNameIdentifier; + } + if (nameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Invalid provider role"); + return -1; + } + + lasso_federation_set_local_name_identifier(federation, nameIdentifier); + profile->identity->is_dirty = TRUE; + + /* set the relay state */ + profile->msg_relayState = g_strdup( + LASSO_LIB_STATUS_RESPONSE(profile->response)->RelayState); + + return 0; +} + +gint +lasso_name_registration_validate_request(LassoNameRegistration *name_registration) +{ + LassoProfile *profile; + LassoProvider *remote_provider; + LassoFederation *federation; + LassoLibRegisterNameIdentifierRequest *request; + LassoSamlNameIdentifier *providedNameIdentifier = NULL; + + g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); + + profile = LASSO_PROFILE(name_registration); + + /* verify the register name identifier request */ + if (LASSO_IS_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Register Name Identifier request not found"); + return -1; + } + + request = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request); + + /* set the remote provider id from the request */ + profile->remote_providerID = g_strdup(request->ProviderID); + if (profile->remote_providerID == NULL) { + message(G_LOG_LEVEL_CRITICAL, "No provider id found in name registration request"); + return -1; + } + + /* set register name identifier response */ + profile->response = lasso_lib_register_name_identifier_response_new_full( + LASSO_PROVIDER(profile->server)->ProviderID, + LASSO_SAML_STATUS_CODE_SUCCESS, + LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request)); + if (LASSO_IS_LIB_REGISTER_NAME_IDENTIFIER_RESPONSE(profile->response) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Error building response"); + return -1; + } + + /* verify federation */ + federation = g_hash_table_lookup(profile->identity->federations, + profile->remote_providerID); + if (LASSO_IS_FEDERATION(federation) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "Federation not found"); + return -1; + } + + if (request->OldProvidedNameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Old provided name identifier not found"); + return -1; + } + + if (lasso_federation_verify_nameIdentifier(federation, + request->OldProvidedNameIdentifier) == FALSE) { + message(G_LOG_LEVEL_CRITICAL, "No name identifier"); + return -1; + } + + remote_provider = g_hash_table_lookup(profile->server->providers, + profile->remote_providerID); + if (remote_provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "XXX"); + return -1; + } + + /* update name identifier in federation */ + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { + providedNameIdentifier = request->SPProvidedNameIdentifier; + } + if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) { + providedNameIdentifier = request->IDPProvidedNameIdentifier; + } + if (providedNameIdentifier == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Sp provided name identifier not found"); + return -1; + } + + lasso_federation_set_remote_name_identifier(federation, providedNameIdentifier); + profile->identity->is_dirty = TRUE; + + return 0; +} + + + +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ - /* set the relay state */ - profile->msg_relayState = lasso_node_get_child_content(profile->response, "RelayState", NULL, NULL); +static LassoNodeClass *parent_class = NULL; + +static xmlNode* +get_xmlNode(LassoNode *node) +{ + xmlNode *xmlnode; + LassoNameRegistration *name_registration = LASSO_NAME_REGISTRATION(node); - done: + xmlnode = parent_class->get_xmlNode(node); + xmlNodeSetName(xmlnode, "NameRegistration"); + xmlSetProp(xmlnode, "NameRegistrationDumpVersion", "2"); - return ret; + if (name_registration->oldNameIdentifier) { + xmlNewTextChild(xmlnode, NULL, "OldNameIdentifier", + name_registration->oldNameIdentifier); + } + + return xmlnode; } -gint -lasso_name_registration_validate_request(LassoNameRegistration *name_registration) +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) { - LassoProfile *profile; - LassoFederation *federation = NULL; - LassoNode *oldProvidedNameIdentifier_node, *providedNameIdentifier_node; - gchar *content, *format, *qualifier; - gint remote_provider_type; - gint ret = 0; - - g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration), -1); - - profile = LASSO_PROFILE(name_registration); - - /* verify the register name identifier request */ - if (LASSO_IS_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Register Name Identifier request not found\n"); - ret = -1; - goto done; - } - - /* set the remote provider id from the request */ - profile->remote_providerID = lasso_node_get_child_content(profile->request, "ProviderID", NULL, NULL); - if (profile->remote_providerID == NULL) { - message(G_LOG_LEVEL_CRITICAL, "No provider id found in name registration request\n"); - ret = -1; - goto done; - } - - /* set register name identifier response */ - profile->response = lasso_register_name_identifier_response_new(profile->server->providerID, - (gchar *)lassoSamlStatusCodeSuccess, - profile->request); - if (LASSO_IS_REGISTER_NAME_IDENTIFIER_RESPONSE(profile->response) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Error while building response\n"); - ret = -1; - goto done; - } - - /* get the remote provider type */ - if (profile->provider_type == lassoProviderTypeSp) { - remote_provider_type = lassoProviderTypeIdp; - } - else if (profile->provider_type == lassoProviderTypeIdp) { - remote_provider_type = lassoProviderTypeSp; - } - else { - message(G_LOG_LEVEL_CRITICAL, "invalid provider type\n"); - ret = -1; - goto done; - } - - /* verify federation */ - federation = lasso_identity_get_federation_ref(profile->identity, profile->remote_providerID); - if (LASSO_IS_FEDERATION(federation) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "Federation not found\n"); - ret = -1; - goto done; - } - - oldProvidedNameIdentifier_node = lasso_node_get_child(profile->request, "OldProvidedNameIdentifier", NULL, NULL); - if (oldProvidedNameIdentifier_node == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Old provided name identifier not found\n"); - ret = -1; - goto done; - } - - if (lasso_federation_verify_nameIdentifier(federation, oldProvidedNameIdentifier_node) == FALSE) { - message(G_LOG_LEVEL_CRITICAL, "No name identifier\n"); - ret = -1; - goto done; - } - - /* update name identifier in federation */ - switch (remote_provider_type) { - case lassoProviderTypeSp: - providedNameIdentifier_node = lasso_node_get_child(profile->request, "SPProvidedNameIdentifier", NULL, NULL); - if (providedNameIdentifier_node == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Sp provided name identifier not found\n"); - ret = -1; - goto done; - } - break; - - case lassoProviderTypeIdp: - providedNameIdentifier_node = lasso_node_get_child(profile->request, "IDPProvidedNameIdentifier", NULL, NULL); - if (providedNameIdentifier_node == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Idp provided name identifier not found\n"); - ret = -1; - goto done; - } - break; - - default: - message(G_LOG_LEVEL_CRITICAL, "Invalid provider type\n"); - ret = -1; - goto done; - } - content = lasso_node_get_content(providedNameIdentifier_node, NULL); - qualifier = lasso_node_get_attr_value(providedNameIdentifier_node, "NameQualifier", NULL); - format = lasso_node_get_attr_value(providedNameIdentifier_node, "Format", NULL); - if (content == NULL || qualifier == NULL || format == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Missing value in name identifier\n"); - ret = -1; - goto done; - } - lasso_federation_build_remote_nameIdentifier(federation, qualifier, format, content); - profile->identity->is_dirty = TRUE; - - /* Set the relay state */ - profile->msg_relayState = lasso_node_get_child_content(profile->request, "RelayState", NULL, NULL); - - done: - - return ret; + LassoNameRegistration *name_registration = LASSO_NAME_REGISTRATION(node); + xmlNode *t; + + parent_class->init_from_xml(node, xmlnode); + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + if (strcmp(t->name, "OldNameIdentifier") == 0) + name_registration->oldNameIdentifier = xmlNodeGetContent(t); + + t = t->next; + } } /*****************************************************************************/ @@ -760,11 +580,10 @@ lasso_name_registration_validate_request(LassoNameRegistration *name_registratio /*****************************************************************************/ static void -lasso_name_registration_finalize(LassoNameRegistration *name_registration) +finalize(GObject *object) { - debug("Register Name Identifier object 0x%x finalized ...\n"); - - parent_class->finalize(G_OBJECT(name_registration)); + debug("Register Name Identifier object 0x%x finalized ...\n"); + G_OBJECT_CLASS(parent_class)->finalize(object); } /*****************************************************************************/ @@ -772,121 +591,83 @@ lasso_name_registration_finalize(LassoNameRegistration *name_registration) /*****************************************************************************/ static void -lasso_name_registration_instance_init(LassoNameRegistration *name_registration) +instance_init(LassoNameRegistration *name_registration) { + name_registration->oldNameIdentifier = NULL; } static void -lasso_name_registration_class_init(LassoNameRegistrationClass *class) +class_init(LassoNameRegistrationClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); + parent_class = g_type_class_peek_parent(klass); - parent_class = g_type_class_peek_parent(class); - /* override parent class methods */ - gobject_class->finalize = (void *)lasso_name_registration_finalize; + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->finalize = finalize; } -GType lasso_name_registration_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoNameRegistrationClass), - NULL, - NULL, - (GClassInitFunc) lasso_name_registration_class_init, - NULL, - NULL, - sizeof(LassoNameRegistration), - 0, - (GInstanceInitFunc) lasso_name_registration_instance_init, - }; - - this_type = g_type_register_static(LASSO_TYPE_PROFILE, - "LassoNameRegistration", - &this_info, 0); - } - return this_type; +GType +lasso_name_registration_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoNameRegistrationClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoNameRegistration), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_PROFILE, + "LassoNameRegistration", &this_info, 0); + } + return this_type; } LassoNameRegistration * -lasso_name_registration_new(LassoServer *server, - lassoProviderType provider_type) +lasso_name_registration_new(LassoServer *server) { - LassoNameRegistration *name_registration; + LassoNameRegistration *name_registration; - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); + g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - /* set the name_registration object */ - name_registration = g_object_new(LASSO_TYPE_NAME_REGISTRATION, - "server", lasso_server_copy(server), - "provider_type", provider_type, - NULL); + name_registration = g_object_new(LASSO_TYPE_NAME_REGISTRATION, NULL); + LASSO_PROFILE(name_registration)->server = server; - return name_registration; + return name_registration; } LassoNameRegistration* -lasso_name_registration_new_from_dump(LassoServer *server, - gchar *dump) +lasso_name_registration_new_from_dump(LassoServer *server, const char *dump) { - LassoNameRegistration *name_registration; - LassoProfile *profile; - LassoNode *node_dump, *request_node, *response_node; - LassoNode *initial_request_node, *initial_response_node; - gchar *type, *export, *providerID_index_str; - - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - g_return_val_if_fail(dump != NULL, NULL); - - name_registration = LASSO_NAME_REGISTRATION(g_object_new(LASSO_TYPE_NAME_REGISTRATION, - "server", lasso_server_copy(server), - NULL)); - - profile = LASSO_PROFILE(name_registration); - - node_dump = lasso_node_new_from_dump(dump); - - /* profile attributes */ - profile->nameIdentifier = lasso_node_get_child_content(node_dump, "NameIdentifier", - lassoLassoHRef, NULL); - profile->remote_providerID = lasso_node_get_child_content(node_dump, "RemoteProviderID", - lassoLassoHRef, NULL); - profile->msg_url = lasso_node_get_child_content(node_dump, "MsgUrl", - lassoLassoHRef, NULL); - profile->msg_body = lasso_node_get_child_content(node_dump, "MsgBody", - lassoLassoHRef, NULL); - profile->msg_relayState = lasso_node_get_child_content(node_dump, "MsgRelayState", - lassoLassoHRef, NULL); - - /* rebuild request */ - request_node = lasso_node_get_child(node_dump, "RegisterNameIdentifierRequest", lassoLibHRef, NULL); - if (LASSO_IS_NODE(request_node) == TRUE) { - export = lasso_node_export(request_node); - profile->request = lasso_register_name_identifier_request_new_from_export(export, - lassoNodeExportTypeXml); - g_free(export); - lasso_node_destroy(request_node); - } - - /* rebuild response */ - response_node = lasso_node_get_child(node_dump, "RegisterNameIdentifierResponse", lassoLibHRef, NULL); - if (response_node != NULL) { - export = lasso_node_export(response_node); - profile->response = lasso_register_name_identifier_response_new_from_export(export, - lassoNodeExportTypeXml); - g_free(export); - lasso_node_destroy(response_node); - } - - /* provider type */ - type = lasso_node_get_child_content(node_dump, "ProviderType", lassoLassoHRef, NULL); - profile->provider_type = atoi(type); - xmlFree(type); + LassoNameRegistration *name_registration; + xmlDoc *doc; - /* name registration attributes */ - name_registration->oldNameIdentifier = lasso_node_get_child_content(node_dump, "OldNameIdentifier", - lassoLassoHRef, NULL); + name_registration = lasso_name_registration_new(server); + doc = xmlParseMemory(dump, strlen(dump)); + init_from_xml(LASSO_NODE(name_registration), xmlDocGetRootElement(doc)); - return name_registration; + return name_registration; } + +/** + * lasso_name_registration_dump: + * @name_registration: the register name identifier object + * + * This method builds a dump of the register name identifier object + * + * Return value: a newly allocated string or NULL + **/ +gchar * +lasso_name_registration_dump(LassoNameRegistration *name_registration) +{ + return lasso_node_dump(LASSO_NODE(name_registration), NULL, 1); +} + diff --git a/lasso/id-ff/name_registration.h b/lasso/id-ff/name_registration.h index 2819b950..3401685b 100644 --- a/lasso/id-ff/name_registration.h +++ b/lasso/id-ff/name_registration.h @@ -32,8 +32,8 @@ extern "C" { #include <lasso/environs/profile.h> -#include <lasso/protocols/register_name_identifier_request.h> -#include <lasso/protocols/register_name_identifier_response.h> +#include <lasso/xml/lib_register_name_identifier_request.h> +#include <lasso/xml/lib_register_name_identifier_response.h> #define LASSO_TYPE_NAME_REGISTRATION (lasso_name_registration_get_type()) #define LASSO_NAME_REGISTRATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_NAME_REGISTRATION, LassoNameRegistration)) @@ -46,25 +46,20 @@ typedef struct _LassoNameRegistration LassoNameRegistration; typedef struct _LassoNameRegistrationClass LassoNameRegistrationClass; struct _LassoNameRegistration { - LassoProfile parent; - - gchar *oldNameIdentifier; - - /*< private >*/ + LassoProfile parent; + gchar *oldNameIdentifier; }; struct _LassoNameRegistrationClass { - LassoProfileClass parent; - + LassoProfileClass parent; }; LASSO_EXPORT GType lasso_name_registration_get_type (void); -LASSO_EXPORT LassoNameRegistration* lasso_name_registration_new (LassoServer *server, - lassoProviderType provider_type); +LASSO_EXPORT LassoNameRegistration* lasso_name_registration_new(LassoServer *server); -LASSO_EXPORT LassoNameRegistration* lasso_name_registration_new_from_dump (LassoServer *server, - gchar *dump); +LASSO_EXPORT LassoNameRegistration* lasso_name_registration_new_from_dump( + LassoServer *server, const char *dump); LASSO_EXPORT gint lasso_name_registration_build_request_msg (LassoNameRegistration *name_registration); @@ -74,16 +69,14 @@ LASSO_EXPORT void lasso_name_registration_destroy (Lasso LASSO_EXPORT gchar* lasso_name_registration_dump (LassoNameRegistration *name_registration); -LASSO_EXPORT gint lasso_name_registration_init_request (LassoNameRegistration *name_registration, - gchar *remote_providerID); +LASSO_EXPORT gint lasso_name_registration_init_request(LassoNameRegistration *name_registration, + char *remote_providerID, lassoHttpMethod http_method); LASSO_EXPORT gint lasso_name_registration_process_request_msg (LassoNameRegistration *name_registration, - gchar *request_msg, - lassoHttpMethod request_method); + gchar *request_msg); LASSO_EXPORT gint lasso_name_registration_process_response_msg (LassoNameRegistration *name_registration, - gchar *response_msg, - lassoHttpMethod response_method); + gchar *response_msg); LASSO_EXPORT gint lasso_name_registration_validate_request (LassoNameRegistration *name_registration); diff --git a/lasso/id-ff/profile.c b/lasso/id-ff/profile.c index 16b0408b..981b5adf 100644 --- a/lasso/id-ff/profile.c +++ b/lasso/id-ff/profile.c @@ -26,76 +26,108 @@ #include <glib.h> #include <glib/gprintf.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> + #include <lasso/xml/errors.h> #include <lasso/xml/samlp_response.h> -#include <lasso/protocols/request.h> -#include <lasso/protocols/response.h> -#include <lasso/protocols/authn_response.h> +#include <lasso/xml/samlp_request.h> +#include <lasso/xml/lib_authn_response.h> +#include <lasso/xml/lib_status_response.h> #include <lasso/environs/profile.h> #include <lasso/lasso_config.h> struct _LassoProfilePrivate { - gboolean dispose_has_run; + gboolean dispose_has_run; }; -static GObjectClass *parent_class = NULL; - /*****************************************************************************/ /* public functions */ /*****************************************************************************/ +LassoSamlNameIdentifier* +lasso_profile_get_nameIdentifier(LassoProfile *ctx) +{ + LassoProvider *remote_provider; + LassoFederation *federation; + + g_return_val_if_fail(LASSO_IS_PROFILE(ctx), NULL); + + g_return_val_if_fail(LASSO_IS_SERVER(ctx->server), NULL); + g_return_val_if_fail(LASSO_IS_IDENTITY(ctx->identity), NULL); + g_return_val_if_fail(ctx->remote_providerID != NULL, NULL); + + remote_provider = g_hash_table_lookup(ctx->server->providers, ctx->remote_providerID); + if (remote_provider == NULL) + return NULL; + + federation = g_hash_table_lookup(ctx->identity->federations, ctx->remote_providerID); + if (federation == NULL) + return NULL; + + if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { + if (federation->remote_nameIdentifier) + return federation->remote_nameIdentifier; + return federation->local_nameIdentifier; + } + + if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) { + if (federation->local_nameIdentifier) + return federation->local_nameIdentifier; + return federation->remote_nameIdentifier; + } + + return NULL; +} + lassoRequestType lasso_profile_get_request_type_from_soap_msg(const gchar *soap) { - LassoNode *soap_node, *body_node, *request_node; - GPtrArray *children; - xmlChar *name; - lassoRequestType type = lassoRequestTypeInvalid; - - soap_node = lasso_node_new_from_dump(soap); - if (soap_node == NULL) { - message(G_LOG_LEVEL_WARNING, "Error while build node from soap msg\n"); - return -1; - } - - body_node = lasso_node_get_child(soap_node, "Body", NULL, NULL); - if(body_node == NULL) { - message(G_LOG_LEVEL_WARNING, "Body node not found\n"); - return -2; - } - - children = lasso_node_get_children(body_node); - if(children->len > 0) { - request_node = g_ptr_array_index(children, 0); - name = lasso_node_get_name(request_node); - - if(xmlStrEqual(name, "Request")) { - type = lassoRequestTypeLogin; - } - else if(xmlStrEqual(name, "LogoutRequest")) { - type = lassoRequestTypeLogout; - } - else if(xmlStrEqual(name, "FederationTerminationNotification")) { - type = lassoRequestTypeDefederation; - } - else if(xmlStrEqual(name, "RegisterNameIdentifierRequest")) { - type = lassoRequestTypeNameRegistration; - } - else if(xmlStrEqual(name, "NameIdentifierMappingRequest")) { - type = lassoRequestTypeNameIdentifierMapping; - } - else if(xmlStrEqual(name, "AuthnRequest")) { - type = lassoRequestTypeLecp; - } - else { - message(G_LOG_LEVEL_WARNING, "Unkown node name : %s\n", name); - } - xmlFree(name); - } - - return type; + xmlDoc *doc; + xmlXPathContext *xpathCtx; + xmlXPathObject *xpathObj; + const xmlChar *name; + + lassoRequestType type = LASSO_REQUEST_TYPE_INVALID; + + /* FIXME: totally lacking error checking */ + + doc = xmlParseMemory(soap, strlen(soap)); + xpathCtx = xmlXPathNewContext(doc); + xmlXPathRegisterNs(xpathCtx, "s", LASSO_SOAP_ENV_HREF); + xpathObj = xmlXPathEvalExpression("//s:Body/*", xpathCtx); + + name = xpathObj->nodesetval->nodeTab[0]->name; + + if (xmlStrEqual(name, "Request")) { + type = LASSO_REQUEST_TYPE_LOGIN; + } + else if (xmlStrEqual(name, "LogoutRequest")) { + type = LASSO_REQUEST_TYPE_LOGOUT; + } + else if (xmlStrEqual(name, "FederationTerminationNotification")) { + type = LASSO_REQUEST_TYPE_DEFEDERATION; + } + else if (xmlStrEqual(name, "RegisterNameIdentifierRequest")) { + type = LASSO_REQUEST_TYPE_NAME_REGISTRATION; + } + else if (xmlStrEqual(name, "NameIdentifierMappingRequest")) { + type = LASSO_REQUEST_TYPE_NAME_IDENTIFIER_MAPPING; + } + else if (xmlStrEqual(name, "AuthnRequest")) { + type = LASSO_REQUEST_TYPE_LECP; + } + else { + message(G_LOG_LEVEL_WARNING, "Unkown node name : %s\n", name); + } + + xmlFreeDoc(doc); + xmlXPathFreeContext(xpathCtx); + xmlXPathFreeObject(xpathObj); + + return type; } /** @@ -110,23 +142,23 @@ lasso_profile_get_request_type_from_soap_msg(const gchar *soap) gboolean lasso_profile_is_liberty_query(const gchar *query) { - /* logic is that a lasso query always has some parameters (RequestId, - * MajorVersion, MinorVersion, IssueInstant, ProviderID, - * NameIdentifier, NameQualifier, Format). If three of them are there; - * it's a lasso query, possibly broken, but a lasso query nevertheless. - */ - gchar *parameters[] = { - "RequestId=", "MajorVersion=", "MinorVersion=", "IssueInstant=", - "ProviderID=", "NameIdentifier=", "NameQualifier=", "Format=", - NULL }; - gint i, n = 0; - - for (i=0; parameters[i] && n < 3; i++) { - if (strstr(query, parameters[i])) - n++; - } - - return (n == 3); + /* logic is that a lasso query always has some parameters (RequestId, + * MajorVersion, MinorVersion, IssueInstant, ProviderID, + * NameIdentifier, NameQualifier, Format). If three of them are there; + * it's a lasso query, possibly broken, but a lasso query nevertheless. + */ + gchar *parameters[] = { + "RequestId=", "MajorVersion=", "MinorVersion=", "IssueInstant=", + "ProviderID=", "NameIdentifier=", "NameQualifier=", "Format=", + NULL }; + gint i, n = 0; + + for (i=0; parameters[i] && n < 3; i++) { + if (strstr(query, parameters[i])) + n++; + } + + return (n == 3); } @@ -134,443 +166,306 @@ lasso_profile_is_liberty_query(const gchar *query) /* public methods */ /*****************************************************************************/ -gchar* -lasso_profile_dump(LassoProfile *ctx, - const gchar *name) -{ - LassoNode *node; - LassoNode *request, *response = NULL; - gchar *dump = NULL; - gchar *request_type = g_new0(gchar, 6); - gchar *response_type = g_new0(gchar, 6); - gchar *provider_type = g_new0(gchar, 6); - - node = lasso_node_new(); - if (name != NULL) { - LASSO_NODE_GET_CLASS(node)->set_name(node, name); - } - else { - LASSO_NODE_GET_CLASS(node)->set_name(node, "LassoProfile"); - } - LASSO_NODE_GET_CLASS(node)->set_ns(node, lassoLassoHRef, NULL); - - /* Add lasso version in the xml node */ - LASSO_NODE_GET_CLASS(node)->set_prop(LASSO_NODE(node), "version", PACKAGE_VERSION); - - if (ctx->request != NULL) { - request = lasso_node_copy(ctx->request); - LASSO_NODE_GET_CLASS(node)->add_child(node, request, FALSE); - lasso_node_destroy(request); - } - if (ctx->response != NULL) { - response = lasso_node_copy(ctx->response); - LASSO_NODE_GET_CLASS(node)->add_child(node, response, FALSE); - lasso_node_destroy(response); - } - - if (ctx->nameIdentifier != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "NameIdentifier", - ctx->nameIdentifier, FALSE); - } - - if (ctx->remote_providerID != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "RemoteProviderID", - ctx->remote_providerID, FALSE); - } - - if (ctx->msg_url != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "MsgUrl", ctx->msg_url, FALSE); - } - if (ctx->msg_body != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "MsgBody", ctx->msg_body, FALSE); - } - if (ctx->msg_relayState != NULL) { - LASSO_NODE_GET_CLASS(node)->new_child(node, "MsgRelayState", - ctx->msg_relayState, FALSE); - } - - g_snprintf(request_type, 6, "%d", ctx->request_type); - LASSO_NODE_GET_CLASS(node)->new_child(node, "RequestType", request_type, FALSE); - g_free(request_type); - g_snprintf(response_type, 6, "%d", ctx->response_type); - LASSO_NODE_GET_CLASS(node)->new_child(node, "ResponseType", response_type, FALSE); - g_free(response_type); - g_snprintf(provider_type, 6, "%d", ctx->provider_type); - LASSO_NODE_GET_CLASS(node)->new_child(node, "ProviderType", provider_type, FALSE); - g_free(provider_type); - - dump = lasso_node_export(node); - lasso_node_destroy(node); - - return dump; -} LassoIdentity* lasso_profile_get_identity(LassoProfile *ctx) { - g_return_val_if_fail(LASSO_IS_PROFILE(ctx), NULL); - - if (ctx->identity != NULL) { - /* return identity copy only if identity isn't empty */ - if (ctx->identity->providerIDs->len > 0) { - return lasso_identity_copy(ctx->identity); - } - } - - return NULL; -} - -gchar* -lasso_profile_get_remote_providerID(LassoProfile *ctx) -{ - g_return_val_if_fail(LASSO_IS_PROFILE(ctx), NULL); - - if (ctx->remote_providerID != NULL) { - return g_strdup(ctx->remote_providerID); - } - - return NULL; + if (ctx->identity && g_hash_table_size(ctx->identity->federations)) + return ctx->identity; + return NULL; } LassoSession* lasso_profile_get_session(LassoProfile *ctx) { - g_return_val_if_fail(LASSO_IS_PROFILE(ctx), NULL); - - if (ctx->session != NULL) { - /* return session copy only if session isn't empty */ - if (ctx->session->providerIDs->len > 0) { - return lasso_session_copy(ctx->session); - } - } - - return NULL; + if (ctx->session && g_hash_table_size(ctx->session->assertions)) + return ctx->session; + return NULL; } gboolean lasso_profile_is_identity_dirty(LassoProfile *ctx) { - if (ctx->identity != NULL) { - return ctx->identity->is_dirty; - } - else { - return FALSE; - } + return (ctx->identity && ctx->identity->is_dirty); } gboolean lasso_profile_is_session_dirty(LassoProfile *ctx) { - if (ctx->session != NULL) { - return ctx->session->is_dirty; - } - else { - return FALSE; - } -} - -gint -lasso_profile_set_remote_providerID(LassoProfile *ctx, - gchar *providerID) -{ - g_free(ctx->remote_providerID); - ctx->remote_providerID = g_strdup(providerID); - - return 1; + return (ctx->session && ctx->session->is_dirty); } void -lasso_profile_set_response_status(LassoProfile *ctx, - const gchar *statusCodeValue) +lasso_profile_set_response_status(LassoProfile *ctx, const char *statusCodeValue) { - LassoNode *status, *status_code; - - status = lasso_samlp_status_new(); - - status_code = lasso_samlp_status_code_new(); - lasso_samlp_status_code_set_value(LASSO_SAMLP_STATUS_CODE(status_code), - statusCodeValue); - - lasso_samlp_status_set_statusCode(LASSO_SAMLP_STATUS(status), - LASSO_SAMLP_STATUS_CODE(status_code)); - - lasso_samlp_response_set_status(LASSO_SAMLP_RESPONSE(ctx->response), - LASSO_SAMLP_STATUS(status)); - lasso_node_destroy(status_code); - lasso_node_destroy(status); -} + LassoSamlpStatus *status; + /* XXX: cleanup before if necessary */ + + status = lasso_samlp_status_new(); + status->StatusCode = lasso_samlp_status_code_new(); + status->StatusCode->Value = g_strdup(statusCodeValue); + + if (LASSO_IS_SAMLP_RESPONSE(ctx->response)) { + LASSO_SAMLP_RESPONSE(ctx->response)->Status = status; + return; + } + if (LASSO_IS_LIB_STATUS_RESPONSE(ctx->response)) { + LASSO_LIB_STATUS_RESPONSE(ctx->response)->Status = status; + return; + } + + message(G_LOG_LEVEL_CRITICAL, "Failed to set status"); + g_assert_not_reached(); +} gint -lasso_profile_set_identity(LassoProfile *ctx, - LassoIdentity *identity) +lasso_profile_set_identity_from_dump(LassoProfile *ctx, const gchar *dump) { - g_return_val_if_fail(LASSO_IS_IDENTITY(identity), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(dump != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - ctx->identity = lasso_identity_copy(identity); - ctx->identity->is_dirty = FALSE; + ctx->identity = lasso_identity_new_from_dump(dump); + if (ctx->identity == NULL) { + message(G_LOG_LEVEL_WARNING, "Failed to create the identity from the identity dump"); + return -1; + } + ctx->identity->is_dirty = FALSE; - return 0; + return 0; } gint -lasso_profile_set_identity_from_dump(LassoProfile *ctx, - const gchar *dump) +lasso_profile_set_session_from_dump(LassoProfile *ctx, const gchar *dump) { - g_return_val_if_fail(dump != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + g_return_val_if_fail(dump != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - ctx->identity = lasso_identity_new_from_dump((gchar *)dump); - if (ctx->identity == NULL) { - message(G_LOG_LEVEL_WARNING, "Failed to create the identity from the identity dump\n"); - return -1; - } - ctx->identity->is_dirty = FALSE; + ctx->session = lasso_session_new_from_dump(dump); + if (ctx->session == NULL) { + message(G_LOG_LEVEL_WARNING, "Failed to create the session from the session dump"); + return -1; + } + ctx->session->is_dirty = FALSE; return 0; } -gint -lasso_profile_set_session(LassoProfile *ctx, - LassoSession *session) -{ - g_return_val_if_fail(LASSO_IS_SESSION(session), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - ctx->session = lasso_session_copy(session); - ctx->session->is_dirty = FALSE; +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ - return 0; -} +static LassoNodeClass *parent_class = NULL; -gint -lasso_profile_set_session_from_dump(LassoProfile *ctx, - const gchar *dump) +static xmlNode* +get_xmlNode(LassoNode *node) { - g_return_val_if_fail(dump != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - - ctx->session = lasso_session_new_from_dump((gchar *)dump); - if (ctx->session == NULL) { - message(G_LOG_LEVEL_WARNING, "Failed to create the session from the session dump\n"); - return -1; - } - ctx->session->is_dirty = FALSE; + xmlNode *xmlnode, *t; + LassoProfile *profile = LASSO_PROFILE(node); + + xmlnode = xmlNewNode(NULL, "Profile"); + xmlSetNs(xmlnode, xmlNewNs(xmlnode, LASSO_LASSO_HREF, NULL)); + xmlSetProp(xmlnode, "Version", "2"); + + /* XXX: server is not saved in profile dump */ + /* (what was the reason ?) + if (profile->server) { + xmlAddChild(xmlnode, lasso_node_get_xmlNode(LASSO_NODE(profile->server))); + } + */ + + if (profile->request) { + t = xmlNewTextChild(xmlnode, NULL, "Request", NULL); + xmlAddChild(t, lasso_node_get_xmlNode(profile->request)); + } + if (profile->response) { + t = xmlNewTextChild(xmlnode, NULL, "Response", NULL); + xmlAddChild(t, lasso_node_get_xmlNode(profile->response)); + } + if (profile->nameIdentifier) + xmlNewTextChild(xmlnode, NULL, "NameIdentifier", profile->nameIdentifier); + if (profile->remote_providerID) + xmlNewTextChild(xmlnode, NULL, "RemoteProviderID", profile->remote_providerID); + if (profile->msg_url) + xmlNewTextChild(xmlnode, NULL, "MsgUrl", profile->msg_url); + if (profile->msg_body) + xmlNewTextChild(xmlnode, NULL, "MsgBody", profile->msg_body); + if (profile->msg_relayState) + xmlNewTextChild(xmlnode, NULL, "MsgRelayState", profile->msg_relayState); + /* XXX: save signature status ? */ + + return xmlnode; +} - return 0; +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) +{ + LassoProfile *profile = LASSO_PROFILE(node); + xmlNode *t; + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + if (strcmp(t->name, "NameIdentifier") == 0) + profile->nameIdentifier = xmlNodeGetContent(t); + if (strcmp(t->name, "RemoteProviderID") == 0) + profile->remote_providerID = xmlNodeGetContent(t); + if (strcmp(t->name, "MsgUrl") == 0) + profile->msg_url = xmlNodeGetContent(t); + if (strcmp(t->name, "MsgBody") == 0) + profile->msg_body = xmlNodeGetContent(t); + if (strcmp(t->name, "MsgRelayState") == 0) + profile->msg_relayState = xmlNodeGetContent(t); + + if (strcmp(t->name, "Server") == 0) { + LassoServer *s; + s = g_object_new(LASSO_TYPE_SERVER, NULL); + LASSO_NODE_GET_CLASS(s)->init_from_xml(LASSO_NODE(s), t); + } + + if (strcmp(t->name, "Request") == 0) { + xmlNode *t2 = t->children; + while (t2 && t2->type != XML_ELEMENT_NODE) + t2 = t2->next; + if (t2) + profile->request = lasso_node_new_from_xmlNode(t2); + } + if (strcmp(t->name, "Response") == 0) { + xmlNode *t2 = t->children; + while (t2 && t2->type != XML_ELEMENT_NODE) + t2 = t2->next; + if (t2) + profile->response = lasso_node_new_from_xmlNode(t2); + } + t = t->next; + } } + /*****************************************************************************/ /* overrided parent class methods */ /*****************************************************************************/ static void -lasso_profile_dispose(LassoProfile *ctx) +dispose(GObject *object) { - if (ctx->private->dispose_has_run) { - return; - } - ctx->private->dispose_has_run = TRUE; + LassoProfile *profile = LASSO_PROFILE(object); - debug("Profile object 0x%x disposed ...\n", ctx); + if (profile->private->dispose_has_run) { + return; + } + profile->private->dispose_has_run = TRUE; - /* unref reference counted objects */ - lasso_server_destroy(ctx->server); - lasso_identity_destroy(ctx->identity); - lasso_session_destroy(ctx->session); + debug("Profile object 0x%x disposed ...\n", profile); - lasso_node_destroy(ctx->request); - lasso_node_destroy(ctx->response); + /* XXX unref reference counted objects */ + /* lasso_server_destroy(profile->server); + lasso_identity_destroy(profile->identity); + lasso_session_destroy(profile->session); - parent_class->dispose(G_OBJECT(ctx)); + lasso_node_destroy(profile->request); + lasso_node_destroy(profile->response); + */ + + G_OBJECT_CLASS(parent_class)->dispose(G_OBJECT(profile)); } static void -lasso_profile_finalize(LassoProfile *ctx) +finalize(GObject *object) { - debug("Profile object 0x%x finalized ...\n", ctx); + LassoProfile *profile = LASSO_PROFILE(object); + + debug("Profile object 0x%x finalized ...\n", ctx); - g_free(ctx->nameIdentifier); - g_free(ctx->remote_providerID); - g_free(ctx->msg_url); - g_free(ctx->msg_body); - g_free(ctx->msg_relayState); + g_free(profile->nameIdentifier); + g_free(profile->remote_providerID); + g_free(profile->msg_url); + g_free(profile->msg_body); + g_free(profile->msg_relayState); - g_free (ctx->private); + g_free (profile->private); - parent_class->finalize(G_OBJECT(ctx)); + G_OBJECT_CLASS(parent_class)->finalize(object); } /*****************************************************************************/ /* instance and class init functions */ /*****************************************************************************/ -enum { - LASSO_PROFILE_SERVER = 1, - LASSO_PROFILE_IDENTITY, - LASSO_PROFILE_SESSION, - LASSO_PROFILE_PROVIDER_TYPE -}; - static void -lasso_profile_instance_init(GTypeInstance *instance, - gpointer g_class) +instance_init(LassoProfile *profile) { - LassoProfile *ctx = LASSO_PROFILE(instance); - - ctx->private = g_new (LassoProfilePrivate, 1); - ctx->private->dispose_has_run = FALSE; - - ctx->server = NULL; - ctx->request = NULL; - ctx->response = NULL; - ctx->nameIdentifier = NULL; - ctx->remote_providerID = NULL; - ctx->msg_url = NULL; - ctx->msg_body = NULL; - ctx->msg_relayState = NULL; - - ctx->identity = NULL; - ctx->session = NULL; - ctx->request_type = lassoMessageTypeNone; - ctx->response_type = lassoMessageTypeNone; - ctx->provider_type = lassoProviderTypeNone; - ctx->signature_status = 0; + profile->private = g_new (LassoProfilePrivate, 1); + profile->private->dispose_has_run = FALSE; + + profile->server = NULL; + profile->request = NULL; + profile->response = NULL; + profile->nameIdentifier = NULL; + profile->remote_providerID = NULL; + profile->msg_url = NULL; + profile->msg_body = NULL; + profile->msg_relayState = NULL; + + profile->identity = NULL; + profile->session = NULL; + profile->signature_status = 0; } static void -lasso_profile_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +class_init(LassoProfileClass *klass) { - LassoProfile *self = LASSO_PROFILE(object); - - switch (property_id) { - case LASSO_PROFILE_SERVER: { - if (self->server) { - g_object_unref(self->server); - } - self->server = g_value_get_pointer (value); - } - break; - case LASSO_PROFILE_IDENTITY: { - if (self->identity) { - g_object_unref(self->identity); - } - self->identity = g_value_get_pointer (value); - } - break; - case LASSO_PROFILE_SESSION: { - if (self->session) { - g_object_unref(self->session); - } - self->session = g_value_get_pointer (value); - } - break; - case LASSO_PROFILE_PROVIDER_TYPE: { - self->provider_type = g_value_get_uint (value); - } - break; - default: - /* We don't have any other property... */ - g_assert (FALSE); - break; - } -} + parent_class = g_type_class_peek_parent(klass); -static void -lasso_profile_get_property(GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ -} + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; -static void -lasso_profile_class_init(gpointer g_class, - gpointer g_class_data) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); - GParamSpec *pspec; - - parent_class = g_type_class_peek_parent(g_class); - /* override parent class methods */ - gobject_class->set_property = lasso_profile_set_property; - gobject_class->get_property = lasso_profile_get_property; - - pspec = g_param_spec_pointer ("server", - "server metadata and keys/certs", - "Data of server", - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - g_object_class_install_property (gobject_class, - LASSO_PROFILE_SERVER, - pspec); - - pspec = g_param_spec_pointer ("identity", - "user's federations", - "User's federations", - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - g_object_class_install_property (gobject_class, - LASSO_PROFILE_IDENTITY, - pspec); - - pspec = g_param_spec_pointer ("session", - "user's assertions", - "User's assertions", - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - g_object_class_install_property (gobject_class, - LASSO_PROFILE_SESSION, - pspec); - - pspec = g_param_spec_uint ("provider_type", - "provider type", - "The provider type", - 0, - G_MAXINT, - 0, - G_PARAM_READABLE | G_PARAM_WRITABLE); - g_object_class_install_property (gobject_class, - LASSO_PROFILE_PROVIDER_TYPE, - pspec); - - gobject_class->dispose = (void *)lasso_profile_dispose; - gobject_class->finalize = (void *)lasso_profile_finalize; + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; } -GType lasso_profile_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoProfileClass), - NULL, - NULL, - (GClassInitFunc) lasso_profile_class_init, - NULL, - NULL, - sizeof(LassoProfile), - 0, - (GInstanceInitFunc) lasso_profile_instance_init, - }; - - this_type = g_type_register_static(G_TYPE_OBJECT, - "LassoProfile", - &this_info, 0); - } - return this_type; +GType +lasso_profile_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof(LassoProfileClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoProfile), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_NODE, + "LassoProfile", &this_info, 0); + } + return this_type; } LassoProfile* -lasso_profile_new(LassoServer *server, - LassoIdentity *identity, - LassoSession *session) +lasso_profile_new(LassoServer *server, LassoIdentity *identity, LassoSession *session) { - LassoProfile *ctx; + LassoProfile *profile = NULL; + + g_return_val_if_fail(server != NULL, NULL); - g_return_val_if_fail(server != NULL, NULL); + profile = g_object_new(LASSO_TYPE_PROFILE, NULL); + profile->identity = identity; + profile->session = session; - ctx = LASSO_PROFILE(g_object_new(LASSO_TYPE_PROFILE, - "server", lasso_server_copy(server), - "identity", lasso_identity_copy(identity), - "session", lasso_session_copy(session), - NULL)); + return profile; +} - return ctx; +gchar* +lasso_profile_dump(LassoProfile *profile) +{ + return lasso_node_dump(LASSO_NODE(profile), NULL, 1); } + diff --git a/lasso/id-ff/profile.h b/lasso/id-ff/profile.h index 5c46d61f..0e66e245 100644 --- a/lasso/id-ff/profile.h +++ b/lasso/id-ff/profile.h @@ -51,67 +51,53 @@ typedef struct _LassoProfilePrivate LassoProfilePrivate; /* Request types (used by SOAP endpoint) */ typedef enum { - lassoRequestTypeInvalid = 0, - lassoRequestTypeLogin = 1, - lassoRequestTypeLogout = 2, - lassoRequestTypeDefederation = 3, - lassoRequestTypeRegisterNameIdentifier = 4, /* obsolete, use lassoRequestTypeNameRegistration instead */ - lassoRequestTypeNameRegistration = 4, - lassoRequestTypeNameIdentifierMapping = 5, - lassoRequestTypeLecp = 6 + LASSO_REQUEST_TYPE_INVALID = 0, + LASSO_REQUEST_TYPE_LOGIN = 1, + LASSO_REQUEST_TYPE_LOGOUT = 2, + LASSO_REQUEST_TYPE_DEFEDERATION = 3, + LASSO_REQUEST_TYPE_NAME_REGISTRATION = 4, + LASSO_REQUEST_TYPE_NAME_IDENTIFIER_MAPPING = 5, + LASSO_REQUEST_TYPE_LECP = 6 } lassoRequestType; typedef enum { - lassoHttpMethodAny = -1, - lassoHttpMethodSelfAddressed, - lassoHttpMethodGet, - lassoHttpMethodPost, - lassoHttpMethodRedirect, - lassoHttpMethodSoap -} lassoHttpMethod; - -typedef enum { - lassoMessageTypeNone = 0, - lassoMessageTypeAuthnRequest, - lassoMessageTypeAuthnResponse, - lassoMessageTypeRequest, - lassoMessageTypeResponse, - lassoMessageTypeArtifact + LASSO_MESSAGE_TYPE_NONE = 0, + LASSO_MESSAGE_TYPE_AUTHN_REQUEST, + LASSO_MESSAGE_TYPE_AUTHN_RESPONSE, + LASSO_MESSAGE_TYPE_REQUEST, + LASSO_MESSAGE_TYPE_RESPONSE, + LASSO_MESSAGE_TYPE_ARTIFACT } lassoMessageType; struct _LassoProfile { - GObject parent; + LassoNode parent; - /*< public >*/ - LassoServer *server; + /*< public >*/ + LassoServer *server; - LassoNode *request; - LassoNode *response; + LassoNode *request; + LassoNode *response; - gchar *nameIdentifier; + gchar *nameIdentifier; /* XXX: shouldn't it be LassoSamlNameIdentifier ? */ - gchar *remote_providerID; + gchar *remote_providerID; - gchar *msg_url; - gchar *msg_body; - gchar *msg_relayState; + gchar *msg_url; + gchar *msg_body; + gchar *msg_relayState; - /*< private >*/ - LassoIdentity *identity; - LassoSession *session; + /*< private >*/ + LassoIdentity *identity; + LassoSession *session; - lassoMessageType request_type; - lassoMessageType response_type; - lassoProviderType provider_type; + lassoHttpMethod http_request_method; + gint signature_status; - lassoHttpMethod http_request_method; - gint signature_status; - - LassoProfilePrivate *private; + LassoProfilePrivate *private; }; struct _LassoProfileClass { - GObjectClass parent; + LassoNodeClass parent; }; /* public functions */ @@ -128,37 +114,27 @@ LASSO_EXPORT LassoProfile* lasso_profile_new (LassoS LassoIdentity *identity, LassoSession *session); -LASSO_EXPORT gchar* lasso_profile_dump (LassoProfile *ctx, - const gchar *name); +LASSO_EXPORT gchar* lasso_profile_dump (LassoProfile *ctx); LASSO_EXPORT LassoIdentity* lasso_profile_get_identity (LassoProfile *ctx); -LASSO_EXPORT gchar* lasso_profile_get_remote_providerID (LassoProfile *ctx); - LASSO_EXPORT LassoSession* lasso_profile_get_session (LassoProfile *ctx); LASSO_EXPORT gboolean lasso_profile_is_identity_dirty (LassoProfile *ctx); LASSO_EXPORT gboolean lasso_profile_is_session_dirty (LassoProfile *ctx); -LASSO_EXPORT gint lasso_profile_set_remote_providerID (LassoProfile *ctx, - gchar *providerID); - LASSO_EXPORT void lasso_profile_set_response_status (LassoProfile *ctx, const gchar *statusCodeValue); -LASSO_EXPORT gint lasso_profile_set_identity (LassoProfile *ctx, - LassoIdentity *identity); - LASSO_EXPORT gint lasso_profile_set_identity_from_dump (LassoProfile *ctx, const gchar *dump); -LASSO_EXPORT gint lasso_profile_set_session (LassoProfile *ctx, - LassoSession *session); - LASSO_EXPORT gint lasso_profile_set_session_from_dump (LassoProfile *ctx, const gchar *dump); +LASSO_EXPORT LassoSamlNameIdentifier* lasso_profile_get_nameIdentifier(LassoProfile *ctx); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/id-ff/provider.c b/lasso/id-ff/provider.c new file mode 100644 index 00000000..69bce2b0 --- /dev/null +++ b/lasso/id-ff/provider.c @@ -0,0 +1,517 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: Nicolas Clapies <nclapies@entrouvert.com> + * Valery Febvre <vfebvre@easter-eggs.com> + * + * 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 <libxml/xpath.h> +#include <libxml/xpathInternals.h> + +#include <xmlsec/xmldsig.h> +#include <xmlsec/xmltree.h> + +#include <lasso/environs/provider.h> +#include <lasso/xml/errors.h> + +struct _LassoProviderPrivate +{ + gboolean dispose_has_run; + GHashTable *SPDescriptor; + GHashTable *IDPDescriptor; +}; + +static char *protocol_uris[] = { + "http://projectliberty.org/profiles/fedterm", + "http://projectliberty.org/profiles/nim", + "http://projectliberty.org/profiles/rni", + "http://projectliberty.org/profiles/slo", + NULL /* none for single sign on */ +}; +static char *protocol_md_nodename[] = { + "FederationTerminationNotificationProtocolProfile", + "NameIdentifierMappingProtocolProfile", + "RegisterNameIdentifierProtocolProfile", + "SingleLogoutProtocolProfile", + "SingleSignOnProtocolProfile" +}; +static char *protocol_roles[] = { NULL, "sp", "idp"}; +char *protocol_methods[] = {"", "", "", "", "", "-http", "-soap"}; + + + +/*****************************************************************************/ +/* public methods */ +/*****************************************************************************/ + +gchar* +lasso_provider_get_metadata_one(LassoProvider *provider, gchar *name) +{ + GList *l; + GHashTable *descriptor; + + descriptor = provider->private->SPDescriptor; /* default to SP */ + if (provider->role == LASSO_PROVIDER_ROLE_IDP) + descriptor = provider->private->IDPDescriptor; + + l = g_hash_table_lookup(descriptor, name); + if (l) + return g_strdup(l->data); + + return NULL; +} + +GList* +lasso_provider_get_metadata_list(LassoProvider *provider, gchar *name) +{ + GHashTable *descriptor; + + descriptor = provider->private->SPDescriptor; /* default to SP */ + if (provider->role == LASSO_PROVIDER_ROLE_IDP) + descriptor = provider->private->IDPDescriptor; + + return g_hash_table_lookup(descriptor, name); +} + + +lassoHttpMethod lasso_provider_get_first_http_method(LassoProvider *provider, + LassoProvider *remote_provider, lassoMdProtocolType protocol_type) +{ + char *protocol_profile_prefix; + GList *local_supported_profiles; + GList *remote_supported_profiles; + GList *t1, *t2; + gboolean found; + + 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; + + protocol_profile_prefix = g_strdup_printf("%s-%s", + protocol_uris[protocol_type], protocol_roles[provider->role]); + + local_supported_profiles = lasso_provider_get_metadata_list( + provider, protocol_md_nodename[protocol_type]); + remote_supported_profiles = lasso_provider_get_metadata_list( + remote_provider, protocol_md_nodename[protocol_type]); + + found = FALSE; + t1 = local_supported_profiles; + while (t1 && !found) { + if (g_str_has_prefix(t1->data, protocol_profile_prefix)) { + t2 = remote_supported_profiles; + while (t2 && !found) { + if (strcmp(t1->data, t2->data) == 0) { + found = TRUE; + break; /* avoid the g_list_next */ + } + t2 = g_list_next(t2); + } + } + t1 = g_list_next(t1); + } + g_free(protocol_profile_prefix); + + if (found) { + if (g_str_has_suffix(t2->data, "http")) + return LASSO_HTTP_METHOD_REDIRECT; + if (g_str_has_suffix(t2->data, "soap")) + return LASSO_HTTP_METHOD_SOAP; + g_assert_not_reached(); + } + + return LASSO_HTTP_METHOD_NONE; +} + +gboolean +lasso_provider_accept_http_method(LassoProvider *provider, LassoProvider *remote_provider, + lassoMdProtocolType protocol_type, lassoHttpMethod http_method, + gboolean initiate_profile) +{ + LassoProviderRole initiating_role; + char *protocol_profile; + GList *local_supported_profiles; + GList *remote_supported_profiles; + + 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%s", + protocol_uris[protocol_type], + protocol_roles[initiating_role], + protocol_methods[http_method+1]); + + local_supported_profiles = lasso_provider_get_metadata_list( + provider, protocol_md_nodename[protocol_type]); + remote_supported_profiles = lasso_provider_get_metadata_list( + remote_provider, protocol_md_nodename[protocol_type]); + + if (g_list_find_custom(local_supported_profiles, protocol_profile, + (GCompareFunc)strcmp) == NULL) + return FALSE; + + if (g_list_find_custom(remote_supported_profiles, protocol_profile, + (GCompareFunc)strcmp) == NULL) + return FALSE; + + return TRUE; +} + + +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ + +static LassoNodeClass *parent_class = NULL; + +static void +load_descriptor(xmlNode *xmlnode, GHashTable *descriptor) +{ + xmlNode *t; + GList *elements; + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + /* XXX: AssertionConsumerServiceURL nodes have attributes */ + elements = g_hash_table_lookup(descriptor, t->name); + elements = g_list_append(elements, g_strdup(xmlNodeGetContent(t))); + g_hash_table_insert(descriptor, g_strdup(t->name), elements); + t = t->next; + } +} + +static void +add_descriptor_childnodes(gchar *key, GList *value, xmlNode *xmlnode) +{ + while (value) { + xmlNewTextChild(xmlnode, NULL, key, value->data); + value = g_list_next(value); + } +} + +static xmlNode* +get_xmlNode(LassoNode *node) +{ + xmlNode *xmlnode, *t; + LassoProvider *provider = LASSO_PROVIDER(node); + char *roles[] = { "None", "SP", "IdP"}; + + xmlnode = xmlNewNode(NULL, "Provider"); + xmlSetNs(xmlnode, xmlNewNs(xmlnode, LASSO_LASSO_HREF, NULL)); + xmlSetProp(xmlnode, "Version", "2"); + if (provider->role) + xmlSetProp(xmlnode, "ProviderRole", roles[provider->role]); + xmlSetProp(xmlnode, "ProviderID", provider->ProviderID); + + if (provider->public_key) + xmlNewTextChild(xmlnode, NULL, "PublicKeyFilePath", provider->public_key); + if (provider->ca_cert_chain) + xmlNewTextChild(xmlnode, NULL, "CaCertChainFilePath", provider->ca_cert_chain); + + if (g_hash_table_size(provider->private->SPDescriptor)) { + t = xmlNewTextChild(xmlnode, NULL, "SPDescriptor", NULL); + g_hash_table_foreach(provider->private->SPDescriptor, + (GHFunc)add_descriptor_childnodes, t); + } + + if (g_hash_table_size(provider->private->IDPDescriptor)) { + t = xmlNewTextChild(xmlnode, NULL, "IDPDescriptor", NULL); + g_hash_table_foreach(provider->private->IDPDescriptor, + (GHFunc)add_descriptor_childnodes, t); + } + + + return xmlnode; +} + + +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) +{ + LassoProvider *provider = LASSO_PROVIDER(node); + xmlNode *t; + xmlChar *s; + + s = xmlGetProp(xmlnode, "ProviderRole"); + if (s && strcmp(s, "SP") == 0) + provider->role = LASSO_PROVIDER_ROLE_SP; + if (s && strcmp(s, "IdP") == 0) + provider->role = LASSO_PROVIDER_ROLE_IDP; + if (s) + xmlFree(s); + + provider->ProviderID = xmlGetProp(xmlnode, "ProviderID"); + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + if (strcmp(t->name, "PublicKeyFilePath") == 0) + provider->public_key = xmlNodeGetContent(t); + if (strcmp(t->name, "CaCertChainFilePath") == 0) + provider->ca_cert_chain = xmlNodeGetContent(t); + if (strcmp(t->name, "SPDescriptor") == 0) + load_descriptor(t, provider->private->SPDescriptor); + if (strcmp(t->name, "IDPDescriptor") == 0) + load_descriptor(t, provider->private->IDPDescriptor); + t = t->next; + } + +} + +/*****************************************************************************/ +/* overrided parent class methods */ +/*****************************************************************************/ + +static void +dispose(GObject *object) +{ + LassoProvider *provider = LASSO_PROVIDER(object); + + if (provider->private->dispose_has_run) { + return; + } + provider->private->dispose_has_run = TRUE; + + debug("Provider object 0x%x disposed ...\n", provider); + + /* XXX: free hash tables (here or in finalize() below) ? */ + + G_OBJECT_CLASS(parent_class)->dispose(G_OBJECT(provider)); +} + +static void +finalize(GObject *object) +{ + LassoProvider *provider = LASSO_PROVIDER(object); + + debug("Provider object 0x%x finalized ...\n", provider); + + g_free(provider->public_key); + g_free(provider->ca_cert_chain); + g_free(provider->private); + + G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(provider)); +} + +/*****************************************************************************/ +/* instance and class init functions */ +/*****************************************************************************/ + +static void +instance_init(LassoProvider *provider) +{ + provider->private = g_new (LassoProviderPrivate, 1); + provider->private->dispose_has_run = FALSE; + provider->role = LASSO_PROVIDER_ROLE_NONE; + provider->public_key = NULL; + provider->ca_cert_chain = NULL; + provider->ProviderID = NULL; + provider->private->IDPDescriptor = g_hash_table_new_full( + g_str_hash, g_str_equal, g_free, NULL); + provider->private->SPDescriptor = g_hash_table_new_full( + g_str_hash, g_str_equal, g_free, NULL); +} + +static void +class_init(LassoProviderClass *klass) +{ + parent_class = g_type_class_peek_parent(klass); + + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; +} + +GType +lasso_provider_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoProviderClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoProvider), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_NODE, + "LassoProvider", &this_info, 0); + } + return this_type; +} + +gboolean +lasso_provider_load_metadata(LassoProvider *provider, const gchar *metadata) +{ + xmlDoc *doc; + xmlXPathContext *xpathCtx; + xmlXPathObject *xpathObj; + xmlNode *node; + + doc = xmlParseFile(metadata); + /* FIXME: lacking error checking */ + + xpathCtx = xmlXPathNewContext(doc); + xmlXPathRegisterNs(xpathCtx, "md", LASSO_METADATA_HREF); + xpathObj = xmlXPathEvalExpression("/md:EntityDescriptor", xpathCtx); + /* if empty: not a metadata file -> bails out */ + if (xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr == 0) { + return FALSE; + } + node = xpathObj->nodesetval->nodeTab[0]; + provider->ProviderID = xmlGetProp(node, "providerID"); + + xpathObj = xmlXPathEvalExpression("md:EntityDescriptor/md:IDPDescriptor", xpathCtx); + if (xpathObj && xpathObj->nodesetval->nodeNr == 1) + load_descriptor(xpathObj->nodesetval->nodeTab[0], provider->private->IDPDescriptor); + xmlXPathFreeObject(xpathObj); + xpathObj = xmlXPathEvalExpression("md:EntityDescriptor/md:SPDescriptor", xpathCtx); + if (xpathObj && xpathObj->nodesetval->nodeNr == 1) + load_descriptor(xpathObj->nodesetval->nodeTab[0], provider->private->SPDescriptor); + xmlXPathFreeObject(xpathObj); + + xmlFreeDoc(doc); + xmlXPathFreeContext(xpathCtx); + + return TRUE; +} + +LassoProvider* +lasso_provider_new(LassoProviderRole role, gchar *metadata, gchar *public_key, gchar *ca_cert_chain) +{ + LassoProvider *provider; + + provider = LASSO_PROVIDER(g_object_new(LASSO_TYPE_PROVIDER, NULL)); + provider->role = role; + if (lasso_provider_load_metadata(provider, metadata) == FALSE) { + /* XXX */ + } + + provider->public_key = g_strdup(public_key); + provider->ca_cert_chain = g_strdup(ca_cert_chain); + + return provider; +} + +LassoProvider* +lasso_provider_new_from_dump(const gchar *dump) +{ + LassoProvider *provider; + xmlDoc *doc; + + provider = g_object_new(LASSO_TYPE_PROVIDER, NULL); + doc = xmlParseMemory(dump, strlen(dump)); + init_from_xml(LASSO_NODE(provider), xmlDocGetRootElement(doc)); + + return provider; +} + +int lasso_provider_verify_signature(LassoProvider *provider, + const char *message, const char *id_attr_name) +{ + return 0; /* XXX */ + + if (message[0] == '<') { + xmlDoc *doc; + xmlNode *xmlnode, *sign, *x509data; + xmlSecKeysMngr *keys_mngr = NULL; + xmlSecDSigCtx *dsigCtx; + lassoPemFileType public_key_file_type; + + doc = xmlParseMemory(message, strlen(message)); + xmlnode = xmlDocGetRootElement(doc); + sign = xmlSecFindNode(xmlnode, xmlSecNodeSignature, xmlSecDSigNs); + if (sign == NULL) { + xmlFreeDoc(doc); + return LASSO_DS_ERROR_SIGNATURE_NOT_FOUND; + } + + x509data = xmlSecFindNode(xmlnode, xmlSecNodeX509Data, xmlSecDSigNs); + if (x509data != NULL && provider->ca_cert_chain != NULL) { + keys_mngr = lasso_load_certs_from_pem_certs_chain_file( + provider->ca_cert_chain); + if (keys_mngr == NULL) + return LASSO_DS_ERROR_CA_CERT_CHAIN_LOAD_FAILED; + } + + dsigCtx = xmlSecDSigCtxCreate(keys_mngr); + if (keys_mngr == NULL) { + if (provider->public_key) { + public_key_file_type = lasso_get_pem_file_type( + provider->public_key); + if (public_key_file_type == LASSO_PEM_FILE_TYPE_CERT) { + /* public_key_file is a certificate file + * => get public key in it */ + dsigCtx->signKey = lasso_get_public_key_from_pem_cert_file( + provider->public_key); + } else { + /* load public key */ + dsigCtx->signKey = xmlSecCryptoAppKeyLoad( + provider->public_key, + xmlSecKeyDataFormatPem, + NULL, NULL, NULL); + } + } + if (dsigCtx->signKey == NULL) { + return LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED; + } + } + + if (xmlSecDSigCtxVerify(dsigCtx, sign) < 0) { + return LASSO_DS_ERROR_SIGNATURE_VERIFICATION_FAILED; + } + if (dsigCtx->status != xmlSecDSigStatusSucceeded) { + return LASSO_DS_ERROR_INVALID_SIGNATURE; + } + + return 0; + } + + if (strchr(message, '&')) { + return lasso_query_verify_signature(message, provider->public_key); + } + + return -1; +} + diff --git a/lasso/id-ff/provider.h b/lasso/id-ff/provider.h new file mode 100644 index 00000000..f27ed8b5 --- /dev/null +++ b/lasso/id-ff/provider.h @@ -0,0 +1,111 @@ +/* $Id$ + * + * Lasso - A free implementation of the Liberty Alliance specifications. + * + * Copyright (C) 2004 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: Nicolas Clapies <nclapies@entrouvert.com> + * Valery Febvre <vfebvre@easter-eggs.com> + * + * 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_PROVIDER_H__ +#define __LASSO_PROVIDER_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <lasso/xml/xml.h> + +#define LASSO_TYPE_PROVIDER (lasso_provider_get_type()) +#define LASSO_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_PROVIDER, LassoProvider)) +#define LASSO_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), LASSO_TYPE_PROVIDER, LassoProviderClass)) +#define LASSO_IS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), LASSO_TYPE_PROVIDER)) +#define LASSO_IS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LASSO_TYPE_PROVIDER)) +#define LASSO_PROVIDER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), LASSO_TYPE_PROVIDER, LassoProviderClass)) + +typedef struct _LassoProvider LassoProvider; +typedef struct _LassoProviderClass LassoProviderClass; +typedef struct _LassoProviderPrivate LassoProviderPrivate; + +typedef enum { + LASSO_HTTP_METHOD_NONE = -1, + LASSO_HTTP_METHOD_ANY, + LASSO_HTTP_METHOD_IDP_INITIATED, + LASSO_HTTP_METHOD_GET, + LASSO_HTTP_METHOD_POST, + LASSO_HTTP_METHOD_REDIRECT, + LASSO_HTTP_METHOD_SOAP +} lassoHttpMethod; + +typedef enum { + LASSO_MD_PROTOCOL_TYPE_FEDERATION_TERMINATION = 0, + LASSO_MD_PROTOCOL_TYPE_NAME_IDENTIFIER_MAPPING, + LASSO_MD_PROTOCOL_TYPE_REGISTER_NAME_IDENTIFIER, + LASSO_MD_PROTOCOL_TYPE_SINGLE_LOGOUT, + LASSO_MD_PROTOCOL_TYPE_SINGLE_SIGN_ON +} lassoMdProtocolType; + +typedef enum { + LASSO_PROVIDER_ROLE_NONE = 0, + LASSO_PROVIDER_ROLE_SP, + LASSO_PROVIDER_ROLE_IDP +} LassoProviderRole; + +struct _LassoProvider { + LassoNode parent; + + gchar *ProviderID; + LassoProviderRole role; + + gchar *public_key; + gchar *ca_cert_chain; + + /*< private >*/ + LassoProviderPrivate *private; +}; + +struct _LassoProviderClass { + LassoNodeClass parent; +}; + +LASSO_EXPORT GType lasso_provider_get_type(void); +LASSO_EXPORT LassoProvider* lasso_provider_new(LassoProviderRole role, gchar *metadata, + gchar *public_key, gchar *ca_cert_chain); +LASSO_EXPORT gchar* lasso_provider_get_metadata_one(LassoProvider *provider, gchar *name); +LASSO_EXPORT GList* lasso_provider_get_metadata_list(LassoProvider *provider, gchar *name); + +LASSO_EXPORT gboolean lasso_provider_load_metadata(LassoProvider *provider, const gchar *metadata); + +LASSO_EXPORT LassoProvider* lasso_provider_new_from_dump(const gchar *dump); + +LASSO_EXPORT int lasso_provider_verify_signature(LassoProvider *provider, + const char *message, const char *id_attr_name); + +LASSO_EXPORT lassoHttpMethod lasso_provider_get_first_http_method(LassoProvider *provider, + LassoProvider *remote_provider, lassoMdProtocolType protocol_type); + +LASSO_EXPORT gboolean lasso_provider_accept_http_method(LassoProvider *provider, + LassoProvider *remote_provider, lassoMdProtocolType protocol_type, + lassoHttpMethod http_method, gboolean initiate_profile); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LASSO_PROVIDER_H__ */ diff --git a/lasso/id-ff/server.c b/lasso/id-ff/server.c index 28d1fc8e..9cf036e4 100644 --- a/lasso/id-ff/server.c +++ b/lasso/id-ff/server.c @@ -32,38 +32,11 @@ #include <lasso/lasso_config.h> -#define LASSO_SERVER_NODE "Server" -#define LASSO_SERVER_METADATA_NODE "ServerMetadata" -#define LASSO_SERVER_PROVIDERS_NODE "Providers" -#define LASSO_SERVER_PROVIDERID_NODE "ProviderID" -#define LASSO_SERVER_PRIVATE_KEY_NODE "PrivateKey" -#define LASSO_SERVER_SECRET_KEY_NODE "SecretKey" -#define LASSO_SERVER_CERTIFICATE_NODE "Certificate" -#define LASSO_SERVER_SIGNATURE_METHOD_NODE "SignatureMethod" - struct _LassoServerPrivate { - gboolean dispose_has_run; + gboolean dispose_has_run; }; -static GObjectClass *parent_class = NULL; - -/*****************************************************************************/ -/* private methods */ -/*****************************************************************************/ - -static gint -lasso_server_add_lasso_provider(LassoServer *server, - LassoProvider *provider) -{ - g_return_val_if_fail(LASSO_IS_SERVER(server), -1); - g_return_val_if_fail(LASSO_IS_PROVIDER(provider), -2); - - g_ptr_array_add(server->providers, provider); - - return 0; -} - /*****************************************************************************/ /* public methods */ /*****************************************************************************/ @@ -80,281 +53,181 @@ lasso_server_add_lasso_provider(LassoServer *server, * Return value: 0 on success or a negative value if an error occurs. **/ gint -lasso_server_add_provider(LassoServer *server, - gchar *metadata, - gchar *public_key, - gchar *ca_cert_chain) +lasso_server_add_provider(LassoServer *server, LassoProviderRole role, + gchar *metadata, gchar *public_key, gchar *ca_cert_chain) { - LassoProvider *provider; + LassoProvider *provider; - g_return_val_if_fail(LASSO_IS_SERVER(server), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(metadata != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + g_return_val_if_fail(LASSO_IS_SERVER(server), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(metadata != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - provider = lasso_provider_new(metadata, public_key, ca_cert_chain); - if (provider != NULL) { - g_ptr_array_add(server->providers, provider); - } - else { - message(G_LOG_LEVEL_CRITICAL, "Failed to add new provider.\n"); - return LASSO_SERVER_ERROR_ADD_PROVIDER_FAILED; - } + provider = lasso_provider_new(role, metadata, public_key, ca_cert_chain); + if (provider == NULL) { + message(G_LOG_LEVEL_CRITICAL, "Failed to add new provider.\n"); + return LASSO_SERVER_ERROR_ADD_PROVIDER_FAILED; + } - return 0; + g_hash_table_insert(server->providers, g_strdup(provider->ProviderID), provider); + + return 0; } -LassoServer* -lasso_server_copy(LassoServer *server) +gchar* +lasso_server_get_authnRequestsSigned(LassoServer *server, GError **err) { - LassoServer *copy; - LassoProvider *p; - guint i; - - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - - copy = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL)); - - /* herited provider attrs */ - LASSO_PROVIDER(copy)->metadata = lasso_node_copy(LASSO_PROVIDER(server)->metadata); - LASSO_PROVIDER(copy)->public_key = g_strdup(LASSO_PROVIDER(server)->public_key); - LASSO_PROVIDER(copy)->ca_cert_chain = g_strdup(LASSO_PROVIDER(server)->ca_cert_chain); - /* server attrs */ - copy->providers = g_ptr_array_new(); - for (i=0; i<server->providers->len; i++) { - p = g_ptr_array_index(server->providers, i); - g_ptr_array_add(copy->providers, lasso_provider_copy(p)); - } - copy->providerID = g_strdup(server->providerID); - copy->private_key = g_strdup(server->private_key); - copy->secret_key = g_strdup(server->secret_key); - copy->certificate = g_strdup(server->certificate); - copy->signature_method = server->signature_method; - - return copy; + /* XXX to do differently (add a boolean to struct) */ + g_assert_not_reached(); + return NULL; } + void lasso_server_destroy(LassoServer *server) { - g_object_unref(G_OBJECT(server)); + g_object_unref(G_OBJECT(server)); } -gchar * -lasso_server_dump(LassoServer *server) + +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ + +static LassoNodeClass *parent_class = NULL; + +static void add_provider_childnode(gchar *key, LassoProvider *value, xmlNode *xmlnode) { - LassoProvider *provider; - LassoNode *server_node, *providers_node, *provider_node, *metadata_copy, *metadata_node; - LassoNodeClass *metadata_class, *server_class, *providers_class; - xmlChar *signature_method_str, *dump; - gint i; - - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - - server_node = lasso_node_new(); - server_class = LASSO_NODE_GET_CLASS(server_node); - server_class->set_name(server_node, LASSO_SERVER_NODE); - server_class->set_ns(server_node, lassoLassoHRef, NULL); - - /* Add lasso version in the xml node */ - server_class->set_prop(LASSO_NODE(server_node), "version", PACKAGE_VERSION); - - /* signature method */ - signature_method_str = g_new(gchar, 6); - g_snprintf(signature_method_str, 6, "%d", server->signature_method); - server_class->set_prop(server_node, LASSO_SERVER_SIGNATURE_METHOD_NODE, signature_method_str); - g_free(signature_method_str); - - /* providerID */ - if (server->providerID != NULL) { - server_class->set_prop(server_node, LASSO_SERVER_PROVIDERID_NODE, server->providerID); - } - /* private key */ - if (server->private_key != NULL) { - server_class->set_prop(server_node, LASSO_SERVER_PRIVATE_KEY_NODE, server->private_key); - } - /* secret key */ - if (server->secret_key != NULL) { - server_class->set_prop(server_node, LASSO_SERVER_SECRET_KEY_NODE, server->secret_key); - } - /* certificate */ - if (server->certificate != NULL) { - server_class->set_prop(server_node, LASSO_SERVER_CERTIFICATE_NODE, server->certificate); - } - /* metadata */ - provider = LASSO_PROVIDER(server); - if (provider->metadata != NULL) { - metadata_node = lasso_node_new(); - metadata_class = LASSO_NODE_GET_CLASS(metadata_node); - metadata_class->set_name(metadata_node, LASSO_SERVER_METADATA_NODE); - metadata_class->set_ns(metadata_node, lassoLassoHRef, NULL); - - metadata_copy = lasso_node_copy(provider->metadata); - metadata_class->add_child(metadata_node, metadata_copy, FALSE); - lasso_node_destroy(metadata_copy); - server_class->add_child(server_node, metadata_node, FALSE); - } - - /* providers */ - providers_node = lasso_node_new(); - providers_class = LASSO_NODE_GET_CLASS(providers_node); - providers_class->set_name(providers_node, LASSO_SERVER_PROVIDERS_NODE); - for (i = 0; i<server->providers->len; i++) { - dump = lasso_provider_dump(g_ptr_array_index(server->providers, i)); - provider_node = lasso_node_new_from_dump(dump); - xmlFree(dump); - providers_class->add_child(providers_node, provider_node, TRUE); - lasso_node_destroy(provider_node); - } - server_class->add_child(server_node, providers_node, FALSE); - lasso_node_destroy(providers_node); - - dump = lasso_node_export(server_node); - lasso_node_destroy(server_node); - - return dump; + xmlAddChild(xmlnode, lasso_node_get_xmlNode(LASSO_NODE(value))); } -gchar* -lasso_server_get_first_providerID(LassoServer *server) +static xmlNode* +get_xmlNode(LassoNode *node) { - LassoProvider *provider; - - if (server->providers->len > 0) { - provider = (LassoProvider *)g_ptr_array_index(server->providers, 0); - return lasso_provider_get_providerID(provider); - } - else { - return NULL; - } + LassoServer *server = LASSO_SERVER(node); + char *signature_methods[] = { NULL, "RSA_SHA1", "DSA_SHA1"}; + xmlNode *xmlnode; + + xmlnode = parent_class->get_xmlNode(node); + xmlNodeSetName(xmlnode, "Server"); + xmlSetProp(xmlnode, "ServerDumpVersion", "2"); + + xmlNewTextChild(xmlnode, NULL, "PrivateKeyFilePath", server->private_key); + if (server->secret_key) + xmlNewTextChild(xmlnode, NULL, "SecretKey", server->secret_key); + xmlNewTextChild(xmlnode, NULL, "CertificateFilePath", server->certificate); + xmlSetProp(xmlnode, "SignatureMethod", signature_methods[server->signature_method]); + + if (g_hash_table_size(server->providers)) { + xmlNode *t; + t = xmlNewTextChild(xmlnode, NULL, "Providers", NULL); + g_hash_table_foreach(server->providers, + (GHFunc)add_provider_childnode, t); + } + + return xmlnode; } -LassoProvider* -lasso_server_get_provider(LassoServer *server, - gchar *providerID, - GError **err) + +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) { - LassoProvider *provider; - GError *tmp_err = NULL; - - if (err != NULL && *err != NULL) { - g_set_error(err, g_quark_from_string("Lasso"), - LASSO_PARAM_ERROR_CHECK_FAILED, - lasso_strerror(LASSO_PARAM_ERROR_CHECK_FAILED)); - g_return_val_if_fail (err == NULL || *err == NULL, NULL); - } - - provider = lasso_server_get_provider_ref(server, providerID, &tmp_err); - - if (provider != NULL) { - return lasso_provider_copy(provider); - } - else { - g_propagate_error (err, tmp_err); - } - - return NULL; + LassoServer *server = LASSO_SERVER(node); + xmlNode *t; + xmlChar *s; + + parent_class->init_from_xml(node, xmlnode); + + s = xmlGetProp(xmlnode, "SignatureMethod"); + if (s && strcmp(s, "RSA_SHA1") == 0) + server->signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA1; + if (s && strcmp(s, "DSA_SHA1") == 0) + server->signature_method = LASSO_SIGNATURE_METHOD_DSA_SHA1; + if (s) + xmlFree(s); + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + if (strcmp(t->name, "PrivateKeyFilePath") == 0) + server->private_key = xmlNodeGetContent(t); + if (strcmp(t->name, "SecretKey") == 0) + server->secret_key = xmlNodeGetContent(t); + if (strcmp(t->name, "CertificateFilePath") == 0) + server->certificate = xmlNodeGetContent(t); + if (strcmp(t->name, "Providers") == 0) { + xmlNode *t2 = t->children; + LassoProvider *p; + while (t2) { + if (t2->type != XML_ELEMENT_NODE) { + t2 = t2->next; + continue; + } + p = g_object_new(LASSO_TYPE_PROVIDER, NULL); + LASSO_NODE_GET_CLASS(p)->init_from_xml(LASSO_NODE(p), t2); + g_hash_table_insert(server->providers, + g_strdup(p->ProviderID), p); + t2 = t2->next; + } + } + t = t->next; + } } -LassoProvider* -lasso_server_get_provider_ref(LassoServer *server, - gchar *providerID, - GError **err) + + +static gboolean +get_first_providerID(gchar *key, gpointer value, char **providerID) { - LassoProvider *provider; - xmlChar *id; - int index, len; - - if (err != NULL && *err != NULL) { - g_set_error(err, g_quark_from_string("Lasso"), - LASSO_PARAM_ERROR_CHECK_FAILED, - lasso_strerror(LASSO_PARAM_ERROR_CHECK_FAILED)); - g_return_val_if_fail (err == NULL || *err == NULL, NULL); - } - if (LASSO_IS_SERVER(server) == FALSE) { - g_set_error(err, g_quark_from_string("Lasso"), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ, - lasso_strerror(LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ)); - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - } - if (providerID == NULL) { - g_set_error(err, g_quark_from_string("Lasso"), - LASSO_PARAM_ERROR_INVALID_VALUE, - lasso_strerror(LASSO_PARAM_ERROR_INVALID_VALUE)); - g_return_val_if_fail(providerID != NULL, NULL); - } - - len = server->providers->len; - for (index = 0; index<len; index++) { - provider = g_ptr_array_index(server->providers, index); - - id = lasso_provider_get_providerID(provider); - if (id != NULL) { - if (xmlStrEqual(providerID, id)) { - xmlFree(id); - return provider; - } - xmlFree(id); - } - } - - /* no provider was found */ - g_set_error(err, g_quark_from_string("Lasso"), - LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND, - lasso_strerror(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND), - providerID); - /* print error msg here so that caller just check err->code */ - message(G_LOG_LEVEL_CRITICAL, err[0]->message); - - return NULL; + *providerID = key; + return TRUE; } -gchar * -lasso_server_get_providerID_from_hash(LassoServer *server, - gchar *b64_hash) +gchar* +lasso_server_get_first_providerID(LassoServer *server) { - LassoProvider *provider; - xmlChar *providerID, *hash_providerID; - xmlChar *b64_hash_providerID; - int i; - - g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); - g_return_val_if_fail(b64_hash != NULL, NULL); - - for (i=0; i<server->providers->len; i++) { - provider = g_ptr_array_index(server->providers, i); - providerID = lasso_provider_get_providerID(provider); - if (providerID != NULL) { - hash_providerID = lasso_sha1(providerID); - b64_hash_providerID = xmlSecBase64Encode(hash_providerID, 20, 0); - xmlFree(hash_providerID); - if (xmlStrEqual(b64_hash_providerID, b64_hash)) { - xmlFree(b64_hash_providerID); - return providerID; - } - else { - xmlFree(b64_hash_providerID); - xmlFree(providerID); - } - } - } + gchar *providerID = NULL; - /* failed to get the providerID */ - message(G_LOG_LEVEL_CRITICAL, - "Failed to get a providerID corresponding to the hash.\n") + g_hash_table_find(server->providers, (GHRFunc)get_first_providerID, &providerID); + return g_strdup(providerID); +} - return NULL; +LassoProvider* +lasso_server_get_provider(LassoServer *server, gchar *providerID) +{ + return g_hash_table_lookup(server->providers, providerID); } -lassoSignatureMethod -lasso_server_get_signature_method(LassoServer *server) + +static gboolean +get_providerID_with_hash(gchar *key, gpointer value, char **providerID) { - return server->signature_method; + char *hash = *providerID; + char *hash_providerID, *b64_hash_providerID; + + hash_providerID = lasso_sha1(key); + b64_hash_providerID = xmlSecBase64Encode(hash_providerID, 20, 0); + xmlFree(hash_providerID); + + if (strcmp(b64_hash_providerID, hash) == 0) { + xmlFree(b64_hash_providerID); + *providerID = key; + return TRUE; + } + xmlFree(b64_hash_providerID); + + return FALSE; } -void -lasso_server_set_signature_method(LassoServer *server, - lassoSignatureMethod signature_method) + +gchar* +lasso_server_get_providerID_from_hash(LassoServer *server, gchar *b64_hash) { - server->signature_method = signature_method; + gchar *providerID = b64_hash; /* kludge */ + + g_hash_table_find(server->providers, (GHRFunc)get_providerID_with_hash, &providerID); + return g_strdup(providerID); } /*****************************************************************************/ @@ -362,39 +235,37 @@ lasso_server_set_signature_method(LassoServer *server, /*****************************************************************************/ static void -lasso_server_dispose(LassoServer *server) +dispose(GObject *object) { - guint i; + LassoServer *server = LASSO_SERVER(object); - if (server->private->dispose_has_run == TRUE) { - return; - } - server->private->dispose_has_run = TRUE; + if (server->private->dispose_has_run == TRUE) { + return; + } + server->private->dispose_has_run = TRUE; - debug("Server object 0x%x disposed ...\n", server); + debug("Server object 0x%x disposed ...\n", server); - /* free allocated memory for providers array */ - for (i=0; i<server->providers->len; i++) { - lasso_provider_destroy(server->providers->pdata[i]); - } - g_ptr_array_free(server->providers, TRUE); + /* free allocated memory for providers array */ + /* XXX */ - parent_class->dispose(G_OBJECT(server)); + G_OBJECT_CLASS(parent_class)->dispose(G_OBJECT(server)); } static void -lasso_server_finalize(LassoServer *server) +finalize(GObject *object) { - debug("Server object 0x%x finalized ...\n", server); + LassoServer *server = LASSO_SERVER(object); - g_free(server->providerID); - g_free(server->private_key); - g_free(server->secret_key); - g_free(server->certificate); + debug("Server object 0x%x finalized ...\n", server); - g_free(server->private); + g_free(server->private_key); + g_free(server->secret_key); + g_free(server->certificate); - parent_class->finalize(G_OBJECT(server)); + g_free(server->private); + + G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(server)); } /*****************************************************************************/ @@ -402,50 +273,54 @@ lasso_server_finalize(LassoServer *server) /*****************************************************************************/ static void -lasso_server_instance_init(LassoServer *server) +instance_init(LassoServer *server) { - server->private = g_new (LassoServerPrivate, 1); - server->private->dispose_has_run = FALSE; - - server->providers = g_ptr_array_new(); - server->providerID = NULL; - server->private_key = NULL; - server->secret_key = NULL; - server->certificate = NULL; - server->signature_method = lassoSignatureMethodRsaSha1; + server->private = g_new(LassoServerPrivate, 1); + server->private->dispose_has_run = FALSE; + + server->providers = g_hash_table_new_full( + g_str_hash, g_str_equal, g_free, + (GDestroyNotify)lasso_node_destroy); + server->private_key = NULL; + server->secret_key = NULL; + server->certificate = NULL; + server->signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA1; } static void -lasso_server_class_init(LassoServerClass *class) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - /* override parent class methods */ - gobject_class->dispose = (void *)lasso_server_dispose; - gobject_class->finalize = (void *)lasso_server_finalize; +class_init(LassoServerClass *klass) +{ + parent_class = g_type_class_peek_parent(klass); + + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; } -GType lasso_server_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoServerClass), - NULL, - NULL, - (GClassInitFunc) lasso_server_class_init, - NULL, - NULL, - sizeof(LassoServer), - 0, - (GInstanceInitFunc) lasso_server_instance_init, - }; - - this_type = g_type_register_static(LASSO_TYPE_PROVIDER, - "LassoServer", - &this_info, 0); - } - return this_type; +GType +lasso_server_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoServerClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoServer), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_PROVIDER, + "LassoServer", &this_info, 0); + } + return this_type; } /** @@ -460,161 +335,46 @@ GType lasso_server_get_type() { * * Return value: a newly allocated #LassoServer object or NULL if an error occurs. **/ -LassoServer * +LassoServer* lasso_server_new(const gchar *metadata, const gchar *private_key, const gchar *secret_key, const gchar *certificate) { - LassoServer *server; - xmlDocPtr doc; - xmlNodePtr root; - LassoNode *md_node = NULL; - gchar *providerID = NULL; - GError *err = NULL; - - /* metadata can be NULL (if server is a LECP) */ - - /* put server metadata in a LassoNode */ - if (metadata != NULL) { - doc = xmlParseFile(metadata); - if (doc == NULL) { - message(G_LOG_LEVEL_CRITICAL, "Failed to parse file \"%s\"\n", metadata); - return NULL; - } - root = xmlCopyNode(xmlDocGetRootElement(doc), 1); - xmlFreeDoc(doc); - md_node = lasso_node_new(); - LASSO_NODE_GET_CLASS(md_node)->set_xmlNode(md_node, root); - - /* get ProviderID in metadata */ - providerID = lasso_node_get_attr_value(md_node, "providerID", &err); - if (providerID == NULL) { - message(G_LOG_LEVEL_WARNING, err->message); - g_error_free(err); - lasso_node_destroy(md_node); - return NULL; - } - } - - /* Ok, we can create server */ - server = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL)); - - if (md_node != NULL) { - LASSO_PROVIDER(server)->metadata = md_node; - } - if (providerID != NULL) { - server->providerID = providerID; - } - server->private_key = g_strdup(private_key); - server->secret_key = g_strdup(secret_key); - server->certificate = g_strdup(certificate); - - return server; -} + LassoServer *server; -LassoServer * -lasso_server_new_from_dump(gchar *dump) -{ - LassoNodeClass *server_class, *providers_class; - LassoNode *server_node, *providers_node, *provider_node, *entity_node, *server_metadata_node; - LassoServer *server; - LassoProvider *provider; - xmlNodePtr providers_xmlNode, provider_xmlNode; - xmlChar *public_key, *ca_cert_chain, *signature_method; - - server = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL)); - - server_node = lasso_node_new_from_dump(dump); - if (server_node == NULL) { - message(G_LOG_LEVEL_WARNING, "Error while loading server dump\n"); - return NULL; - } - server_class = LASSO_NODE_GET_CLASS(server_node); - if (strcmp(server_class->get_name(server_node), LASSO_SERVER_NODE) != 0) { - message(G_LOG_LEVEL_WARNING, "XML is not a server dump\n"); - lasso_node_destroy(server_node); - return NULL; - } - - /* providerID */ - server->providerID = lasso_node_get_attr_value(server_node, LASSO_SERVER_PROVIDERID_NODE, NULL); - - /* private key */ - server->private_key = lasso_node_get_attr_value(server_node, LASSO_SERVER_PRIVATE_KEY_NODE, NULL); - - /* secret key */ - server->secret_key = lasso_node_get_attr_value(server_node, LASSO_SERVER_SECRET_KEY_NODE, NULL); - - /* certificate */ - server->certificate = lasso_node_get_attr_value(server_node, LASSO_SERVER_CERTIFICATE_NODE, NULL); - - /* signature method */ - signature_method = lasso_node_get_attr_value(server_node, LASSO_SERVER_SIGNATURE_METHOD_NODE, NULL); - if (signature_method != NULL) { - server->signature_method = atoi(signature_method); - xmlFree(signature_method); - } - - /* metadata */ - server_metadata_node = lasso_node_get_child(server_node, LASSO_SERVER_METADATA_NODE, NULL, NULL); - if (server_metadata_node != NULL) { - entity_node = lasso_node_get_child(server_metadata_node, "EntityDescriptor", NULL, NULL); - LASSO_PROVIDER(server)->metadata = lasso_node_copy(entity_node); - lasso_node_destroy(entity_node); - } - - /* public key */ - LASSO_PROVIDER(server)->public_key = lasso_node_get_attr_value(server_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, NULL); - - /* ca_cert_chain */ - LASSO_PROVIDER(server)->ca_cert_chain = lasso_node_get_attr_value(server_node, LASSO_PROVIDER_CA_CERT_CHAIN_NODE, NULL); - - /* providers */ - providers_node = lasso_node_get_child(server_node, LASSO_SERVER_PROVIDERS_NODE, lassoLassoHRef, NULL); - if (providers_node != NULL) { - providers_class = LASSO_NODE_GET_CLASS(providers_node); - providers_xmlNode = providers_class->get_xmlNode(providers_node); - provider_xmlNode = providers_xmlNode->children; - - while (provider_xmlNode != NULL) { - if (provider_xmlNode->type == XML_ELEMENT_NODE && \ - xmlStrEqual(provider_xmlNode->name, LASSO_PROVIDER_NODE)) { - /* provider node */ - provider_node = lasso_node_new_from_xmlNode(provider_xmlNode); - - /* metadata */ - entity_node = lasso_node_get_child(provider_node, "EntityDescriptor", NULL, NULL); - - /* public key */ - public_key = lasso_node_get_attr_value(provider_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, NULL); - - /* ca certificate */ - ca_cert_chain = lasso_node_get_attr_value(provider_node, LASSO_PROVIDER_CA_CERT_CHAIN_NODE, NULL); - - /* add provider */ - provider = lasso_provider_new_from_metadata_node(entity_node); - lasso_node_destroy(entity_node); - if (public_key != NULL) { - lasso_provider_set_public_key(provider, public_key); - xmlFree(public_key); - } - if (ca_cert_chain != NULL) { - lasso_provider_set_ca_cert_chain(provider, ca_cert_chain); - xmlFree(ca_cert_chain); + server = g_object_new(LASSO_TYPE_SERVER, NULL); + + /* metadata can be NULL (if server is a LECP) */ + if (metadata != NULL) { + lasso_provider_load_metadata(LASSO_PROVIDER(server), metadata); + /* XXX: error checking */ } - lasso_server_add_lasso_provider(server, provider); - lasso_node_destroy(provider_node); - } + server->private_key = g_strdup(private_key); + server->secret_key = g_strdup(secret_key); + server->certificate = g_strdup(certificate); - provider_xmlNode = provider_xmlNode->next; - } + return server; +} - lasso_node_destroy(providers_node); - } +LassoServer* +lasso_server_new_from_dump(const gchar *dump) +{ + LassoServer *server; + xmlDoc *doc; - lasso_node_destroy(server_node); + server = g_object_new(LASSO_TYPE_SERVER, NULL); + doc = xmlParseMemory(dump, strlen(dump)); + init_from_xml(LASSO_NODE(server), xmlDocGetRootElement(doc)); + xmlFreeDoc(doc); - return server; + return server; } + +gchar* +lasso_server_dump(LassoServer *server) +{ + return lasso_node_dump(LASSO_NODE(server), NULL, 1); +} + diff --git a/lasso/id-ff/server.h b/lasso/id-ff/server.h index f35783ff..c7df3040 100644 --- a/lasso/id-ff/server.h +++ b/lasso/id-ff/server.h @@ -30,7 +30,7 @@ extern "C" { #endif /* __cplusplus */ -#include <lasso/protocols/provider.h> +#include <lasso/environs/provider.h> #define LASSO_TYPE_SERVER (lasso_server_get_type()) #define LASSO_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_SERVER, LassoServer)) @@ -44,17 +44,17 @@ typedef struct _LassoServerClass LassoServerClass; typedef struct _LassoServerPrivate LassoServerPrivate; struct _LassoServer { - LassoProvider parent; - - GPtrArray *providers; - - gchar *providerID; - gchar *private_key; - gchar *secret_key; - gchar *certificate; - lassoSignatureMethod signature_method; - /*< private >*/ - LassoServerPrivate *private; + LassoProvider parent; + + GHashTable *providers; + + gchar *private_key; + gchar *secret_key; + gchar *certificate; + lassoSignatureMethod signature_method; + + /*< private >*/ + LassoServerPrivate *private; }; struct _LassoServerClass { @@ -68,36 +68,25 @@ LASSO_EXPORT LassoServer* lasso_server_new (const g const gchar *secret_key, const gchar *certificate); -LASSO_EXPORT LassoServer* lasso_server_new_from_dump (gchar *dump); +LASSO_EXPORT LassoServer* lasso_server_new_from_dump (const gchar *dump); LASSO_EXPORT gint lasso_server_add_provider (LassoServer *server, - gchar *metadata, - gchar *public_key, - gchar *ca_cert_chain); - -LASSO_EXPORT LassoServer* lasso_server_copy (LassoServer *server); + LassoProviderRole role, + gchar *metadata, + gchar *public_key, + gchar *ca_cert_chain); LASSO_EXPORT void lasso_server_destroy (LassoServer *server); -LASSO_EXPORT gchar* lasso_server_dump (LassoServer *server); - LASSO_EXPORT gchar* lasso_server_get_first_providerID (LassoServer *server); LASSO_EXPORT LassoProvider* lasso_server_get_provider (LassoServer *server, - gchar *providerID, - GError **err); - -LASSO_EXPORT LassoProvider* lasso_server_get_provider_ref (LassoServer *server, - gchar *providerID, - GError **err); + gchar *providerID); LASSO_EXPORT gchar* lasso_server_get_providerID_from_hash (LassoServer *server, gchar *b64_hash); -LASSO_EXPORT lassoSignatureMethod lasso_server_get_signature_method (LassoServer *server); - -LASSO_EXPORT void lasso_server_set_signature_method (LassoServer *server, - lassoSignatureMethod signature_method); +LASSO_EXPORT gchar* lasso_server_dump(LassoServer *server); #ifdef __cplusplus } diff --git a/lasso/id-ff/session.c b/lasso/id-ff/session.c index 8e935529..bac9a784 100644 --- a/lasso/id-ff/session.c +++ b/lasso/id-ff/session.c @@ -24,332 +24,198 @@ */ #include <lasso/environs/session.h> +#include <lasso/xml/errors.h> #include <lasso/lasso_config.h> - -#define LASSO_SESSION_NODE "Session" -#define LASSO_SESSION_ASSERTIONS_NODE "Assertions" -#define LASSO_SESSION_ASSERTION_NODE "AuthnAssertion" -#define LASSO_SESSION_REMOTE_PROVIDERID_ATTR "RemoteProviderID" +#include <libxml/tree.h> struct _LassoSessionPrivate { - gboolean dispose_has_run; + gboolean dispose_has_run; + GList *providerIDs; }; -static GObjectClass *parent_class = NULL; - /*****************************************************************************/ -/* private functions */ +/* public methods */ /*****************************************************************************/ -static void -lasso_session_copy_assertion(gpointer key, - gpointer value, - gpointer assertions) +gint +lasso_session_add_assertion(LassoSession *session, gchar *providerID, LassoSamlAssertion *assertion) { - g_hash_table_insert((GHashTable *)assertions, g_strdup((gchar *)key), - lasso_node_copy(LASSO_NODE(value))); -} + g_return_val_if_fail(session != NULL, -1); + g_return_val_if_fail(providerID != NULL, -2); + g_return_val_if_fail(assertion != NULL, -3); -static void -lasso_session_dump_assertion(gpointer key, - gpointer value, - LassoNode *assertions) -{ - LassoNode *assertion_node, *assertion_copy; - LassoNodeClass *assertion_class, *assertions_class; - - /* new lasso assertion node */ - assertion_node = lasso_node_new(); - assertion_class = LASSO_NODE_GET_CLASS(assertion_node); - assertion_class->set_name(assertion_node, LASSO_SESSION_ASSERTION_NODE); - - /* set the remote provider id */ - assertion_class->set_prop(assertion_node, LASSO_SESSION_REMOTE_PROVIDERID_ATTR, key); - - /* set assertion node */ - assertion_copy = lasso_node_copy(LASSO_NODE(value)); - assertion_class->add_child(assertion_node, assertion_copy, FALSE); - lasso_node_destroy(assertion_copy); - - /* add lasso assertion node to lasso assertions node */ - assertions_class = LASSO_NODE_GET_CLASS(assertions); - assertions_class->add_child(assertions, assertion_node, TRUE); - lasso_node_destroy(assertion_node); -} + if (g_hash_table_lookup(session->assertions, providerID)) { + debug("An assertion existed already for this providerID, replaced by new one."); + } -/*****************************************************************************/ -/* public methods */ -/*****************************************************************************/ + g_hash_table_insert(session->assertions, g_strdup(providerID), assertion); -gint -lasso_session_add_assertion(LassoSession *session, - gchar *providerID, - LassoNode *assertion) -{ - int i; - gboolean found = FALSE; - - g_return_val_if_fail(session != NULL, -1); - g_return_val_if_fail(providerID != NULL, -2); - g_return_val_if_fail(assertion != NULL, -3); - - /* add the remote provider id */ - for(i = 0; i<session->providerIDs->len; i++) { - if(xmlStrEqual(providerID, g_ptr_array_index(session->providerIDs, i))) { - found = TRUE; - break; - } - } - if(found == TRUE) { - debug("An assertion existed already for this providerID, it was replaced by the new one.\n"); - } - else { - g_ptr_array_add(session->providerIDs, g_strdup(providerID)); - } - - /* add the assertion */ - g_hash_table_insert(session->assertions, g_strdup(providerID), - lasso_node_copy(assertion)); - - session->is_dirty = TRUE; - - return 0; + session->is_dirty = TRUE; + + return 0; } -LassoSession* -lasso_session_copy(LassoSession *session) +LassoSamlAssertion* +lasso_session_get_assertion(LassoSession *session, gchar *providerID) { - LassoSession *copy; - guint i; - - if (session == NULL) { - return NULL; - } - - copy = LASSO_SESSION(g_object_new(LASSO_TYPE_SESSION, NULL)); - - copy->providerIDs = g_ptr_array_new(); - for(i=0; i<session->providerIDs->len; i++) { - g_ptr_array_add(copy->providerIDs, - g_strdup(g_ptr_array_index(session->providerIDs, i))); - } - copy->assertions = g_hash_table_new_full(g_str_hash, g_str_equal, - (GDestroyNotify)g_free, - (GDestroyNotify)lasso_node_destroy); - g_hash_table_foreach(session->assertions, (GHFunc)lasso_session_copy_assertion, - (gpointer)copy->assertions); - copy->is_dirty = session->is_dirty; - - return copy; + return g_hash_table_lookup(session->assertions, providerID); } -void -lasso_session_destroy(LassoSession *session) +gchar* +lasso_session_get_authentication_method(LassoSession *session, gchar *remote_providerID) { - if (LASSO_IS_SESSION(session)) { - g_object_unref(G_OBJECT(session)); - } + /* XXX: somewhere in + * session/Assertion[remote_providerID]/AuthenticationStatement + */ + + g_assert_not_reached(); + return NULL; } gchar* -lasso_session_dump(LassoSession *session) +lasso_session_get_first_providerID(LassoSession *session) { - LassoNode *session_node, *assertions_node; - LassoNodeClass *session_class, *assertions_class; - int table_size; - gchar *dump; - - g_return_val_if_fail(session != NULL, NULL); - - session_node = lasso_node_new(); - session_class = LASSO_NODE_GET_CLASS(session_node); - session_class->set_name(session_node, LASSO_SESSION_NODE); - session_class->set_ns(session_node, lassoLassoHRef, NULL); - - /* dump the assertions */ - table_size = g_hash_table_size(session->assertions); - if (table_size > 0) { - assertions_node = lasso_node_new(); - assertions_class = LASSO_NODE_GET_CLASS(assertions_node); - assertions_class->set_name(assertions_node, LASSO_SESSION_ASSERTIONS_NODE); - g_hash_table_foreach(session->assertions, (GHFunc)lasso_session_dump_assertion, - assertions_node); - session_class->add_child(session_node, assertions_node, FALSE); - lasso_node_destroy(assertions_node); - } - - /* Add lasso version in the xml node */ - session_class->set_prop(LASSO_NODE(session_node), "version", PACKAGE_VERSION); - - dump = lasso_node_export(session_node); - - lasso_node_destroy(session_node); - - return dump; + /* XXX: why didn't it use get_provider_index directly ? */ + return lasso_session_get_provider_index(session, 0); } -LassoNode* -lasso_session_get_assertion(LassoSession *session, - gchar *providerID) +static void +add_providerID(gchar *key, LassoLibAssertion *assertion, LassoSession *session) { - LassoNode *assertion; - - g_return_val_if_fail(session != NULL, NULL); - g_return_val_if_fail(providerID != NULL, NULL); - - assertion = (LassoNode *)g_hash_table_lookup(session->assertions, - providerID); - if (assertion == NULL) { - return NULL; - } - - return lasso_node_copy(assertion); + session->private->providerIDs = g_list_append(session->private->providerIDs, key); } gchar* -lasso_session_get_authentication_method(LassoSession *session, - gchar *remote_providerID) +lasso_session_get_provider_index(LassoSession *session, gint index) { - LassoNode *assertion, *as; - gchar *providerID = remote_providerID; - gchar *authentication_method; - GError *err = NULL; - - if (providerID == NULL) { - providerID = lasso_session_get_first_providerID(session); - } - assertion = lasso_session_get_assertion(session, providerID); - if (providerID == NULL) { - g_free(providerID); - } - as = lasso_node_get_child(assertion, "AuthenticationStatement", NULL, NULL); - authentication_method = lasso_node_get_attr_value(as, "AuthenticationMethod", &err); - if (authentication_method == NULL) { - message(G_LOG_LEVEL_CRITICAL, err->message); - g_error_free(err); - goto done; - } - - done: - lasso_node_destroy(as); - lasso_node_destroy(assertion); - return authentication_method; + GList *element; + + if (session->private->providerIDs == NULL) { + g_hash_table_foreach(session->assertions, (GHFunc)add_providerID, session); + /* XXX? create list */ + } + + if (g_hash_table_size(session->assertions) == 0) + return NULL; + + element = g_list_nth(session->private->providerIDs, index); + if (element == NULL) + return NULL; + + return g_strdup(element->data); } -gchar* -lasso_session_get_first_providerID(LassoSession *session) +gint +lasso_session_remove_assertion(LassoSession *session, gchar *providerID) { - gchar *providerID; + if (g_hash_table_remove(session->assertions, providerID)) { + session->is_dirty = TRUE; + return 0; + } - g_return_val_if_fail(session != NULL, NULL); + return LASSO_ERROR_UNDEFINED; /* assertion not found */ +} - if(session->providerIDs->len == 0) { - return NULL; - } +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ - providerID = g_ptr_array_index(session->providerIDs, 0); - if (providerID == NULL) { - return NULL; - } +static LassoNodeClass *parent_class = NULL; - return g_strdup(providerID); +static void +add_assertion_childnode(gchar *key, LassoLibAssertion *value, xmlNode *xmlnode) +{ + xmlNode *t; + t = xmlNewTextChild(xmlnode, NULL, "Assertion", NULL); + xmlSetProp(t, "RemoteProviderID", key); + xmlAddChild(t, lasso_node_get_xmlNode(LASSO_NODE(value))); } -gchar* -lasso_session_get_provider_index(LassoSession *session, - gint index) +static xmlNode* +get_xmlNode(LassoNode *node) { - gchar *providerID; - - g_return_val_if_fail(session != NULL, NULL); + xmlNode *xmlnode; + LassoSession *session = LASSO_SESSION(node); - /* verify index is valid */ - if ((session->providerIDs == NULL) && (session->providerIDs->len < 0)) { - return NULL; - } - if ((index < 0) || (index >= session->providerIDs->len)) { - return NULL; - } + xmlnode = xmlNewNode(NULL, "Session"); + xmlSetNs(xmlnode, xmlNewNs(xmlnode, LASSO_LASSO_HREF, NULL)); + xmlSetProp(xmlnode, "Version", "2"); - /* get the provider id */ - providerID = g_ptr_array_index(session->providerIDs, index); - if (providerID == NULL) { - return NULL; - } + if (g_hash_table_size(session->assertions)) + g_hash_table_foreach(session->assertions, (GHFunc)add_assertion_childnode, xmlnode); - return g_strdup(providerID); + return xmlnode; } -gint -lasso_session_remove_assertion(LassoSession *session, - gchar *providerID) +static void +init_from_xml(LassoNode *node, xmlNode *xmlnode) { - LassoNode *assertion; - int i; - - g_return_val_if_fail(session != NULL, -1); - g_return_val_if_fail(providerID != NULL, -1); - - /* remove the assertion */ - assertion = lasso_session_get_assertion(session, providerID); - if (assertion != NULL) { - g_hash_table_remove(session->assertions, providerID); - lasso_node_destroy(assertion); - } - - /* remove the remote provider id */ - for(i = 0; i<session->providerIDs->len; i++) { - if(xmlStrEqual(providerID, g_ptr_array_index(session->providerIDs, i))) { - g_ptr_array_remove_index(session->providerIDs, i); - break; - } - } - - session->is_dirty = TRUE; - - return 0; + LassoSession *session = LASSO_SESSION(node); + xmlNode *t, *n; + + t = xmlnode->children; + while (t) { + if (t->type != XML_ELEMENT_NODE) { + t = t->next; + continue; + } + + if (strcmp(t->name, "Assertion") == 0) { + n = t->children; + while (n && n->type != XML_ELEMENT_NODE) n = n->next; + + if (n) { + LassoLibAssertion *assertion; + assertion = LASSO_LIB_ASSERTION(lasso_node_new_from_xmlNode(n)); + g_hash_table_insert( + session->assertions, + xmlGetProp(t, "RemoteProviderID"), + assertion); + } + } + t = t->next; + } } + + + /*****************************************************************************/ /* overrided parent class methods */ /*****************************************************************************/ static void -lasso_session_dispose(LassoSession *session) +dispose(GObject *object) { - if (session->private->dispose_has_run == TRUE) { - return; - } - session->private->dispose_has_run = TRUE; + LassoSession *session = LASSO_SESSION(object); - debug("Session object 0x%x disposed ...\n", session); + if (session->private->dispose_has_run == TRUE) { + return; + } + session->private->dispose_has_run = TRUE; + + debug("Session object 0x%x disposed ...\n", session); - g_hash_table_destroy(session->assertions); - session->assertions = NULL; + /* XXX: here or not ? + g_hash_table_destroy(session->assertions); + session->assertions = NULL; + */ - parent_class->dispose(G_OBJECT(session)); + G_OBJECT_CLASS(parent_class)->dispose(object); } static void -lasso_session_finalize(LassoSession *session) +finalize(GObject *object) { - gint i; + LassoSession *session = LASSO_SESSION(object); - debug("Session object 0x%x finalized ...\n", session); + debug("Session object 0x%x finalized ...\n", session); - /* free allocated memory for providerIDs array */ - for (i=0; i<session->providerIDs->len; i++) { - g_free(session->providerIDs->pdata[i]); - session->providerIDs->pdata[i] = NULL; - } - g_ptr_array_free(session->providerIDs, TRUE); - session->providerIDs = NULL; + g_free(session->private); + session->private = NULL; - g_free(session->private); - session->private = NULL; - - parent_class->finalize(G_OBJECT(session)); + G_OBJECT_CLASS(parent_class)->finalize(object); } /*****************************************************************************/ @@ -357,126 +223,85 @@ lasso_session_finalize(LassoSession *session) /*****************************************************************************/ static void -lasso_session_instance_init(LassoSession *session) +instance_init(LassoSession *session) { - session->private = g_new (LassoSessionPrivate, 1); - session->private->dispose_has_run = FALSE; - - session->providerIDs = g_ptr_array_new(); - 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 = g_new (LassoSessionPrivate, 1); + session->private->dispose_has_run = FALSE; + session->private->providerIDs = NULL; + + 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 -lasso_session_class_init(LassoSessionClass *class) +class_init(LassoSessionClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - /* override parent class methods */ - gobject_class->dispose = (void *)lasso_session_dispose; - gobject_class->finalize = (void *)lasso_session_finalize; + parent_class = g_type_class_peek_parent(klass); + + LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; + LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; + + G_OBJECT_CLASS(klass)->dispose = dispose; + G_OBJECT_CLASS(klass)->finalize = finalize; } -GType lasso_session_get_type() { - static GType this_type = 0; - - if (!this_type) { - static const GTypeInfo this_info = { - sizeof (LassoSessionClass), - NULL, - NULL, - (GClassInitFunc) lasso_session_class_init, - NULL, - NULL, - sizeof(LassoSession), - 0, - (GInstanceInitFunc) lasso_session_instance_init, - }; - - this_type = g_type_register_static(G_TYPE_OBJECT, - "LassoSession", - &this_info, 0); - } - return this_type; +GType +lasso_session_get_type() +{ + static GType this_type = 0; + + if (!this_type) { + static const GTypeInfo this_info = { + sizeof (LassoSessionClass), + NULL, + NULL, + (GClassInitFunc) class_init, + NULL, + NULL, + sizeof(LassoSession), + 0, + (GInstanceInitFunc) instance_init, + }; + + this_type = g_type_register_static(LASSO_TYPE_NODE, + "LassoSession", &this_info, 0); + } + return this_type; } LassoSession* lasso_session_new() { - LassoSession *session; + return g_object_new(LASSO_TYPE_SESSION, NULL); +} - session = LASSO_SESSION(g_object_new(LASSO_TYPE_SESSION, NULL)); +LassoSession* +lasso_session_new_from_dump(const gchar *dump) +{ + LassoSession *session; + xmlDoc *doc; + + session = lasso_session_new(); + doc = xmlParseMemory(dump, strlen(dump)); + init_from_xml(LASSO_NODE(session), xmlDocGetRootElement(doc)); + xmlFreeDoc(doc); - return session; + return session; } -LassoSession* -lasso_session_new_from_dump(gchar *dump) +gchar* +lasso_session_dump(LassoSession *session) { - LassoSession *session; - LassoNode *session_node; - LassoNode *assertions_node, *assertion_node, *assertion; - xmlNodePtr assertions_xmlNode, assertion_xmlNode; - xmlChar *providerID; - GError *err = NULL; - - g_return_val_if_fail(dump != NULL, NULL); - - session = LASSO_SESSION(g_object_new(LASSO_TYPE_SESSION, NULL)); - - /* get session */ - session_node = lasso_node_new_from_dump(dump); - if (session_node == NULL) { - message(G_LOG_LEVEL_WARNING, "Can't create a session from dump\n"); - return NULL; - } - - /* get assertions */ - assertions_node = lasso_node_get_child(session_node, - LASSO_SESSION_ASSERTIONS_NODE, - lassoLassoHRef, NULL); - if (assertions_node != NULL) { - assertions_xmlNode = LASSO_NODE_GET_CLASS(assertions_node)->get_xmlNode(assertions_node); - assertion_xmlNode = assertions_xmlNode->children; - - while (assertion_xmlNode != NULL) { - /* assertion xmlNode */ - if (assertion_xmlNode->type == XML_ELEMENT_NODE && \ - xmlStrEqual(assertion_xmlNode->name, LASSO_SESSION_ASSERTION_NODE)) { - /* assertion node */ - assertion_node = lasso_node_new_from_xmlNode(assertion_xmlNode); - providerID = lasso_node_get_attr_value(assertion_node, - LASSO_SESSION_REMOTE_PROVIDERID_ATTR, - &err); - if (providerID != NULL) { - assertion = lasso_node_get_child(assertion_node, - "Assertion", - NULL, /* lassoLibHRef, FIXME changed for SourceID */ - &err); - if (assertion != NULL) { - lasso_session_add_assertion(session, providerID, assertion); - lasso_node_destroy(assertion); - } - else { - message(G_LOG_LEVEL_CRITICAL, err->message); - g_clear_error(&err); - } - } - else { - message(G_LOG_LEVEL_CRITICAL, err->message); - g_clear_error(&err); - } - xmlFree(providerID); - lasso_node_destroy(assertion_node); - } - assertion_xmlNode = assertion_xmlNode->next; - } - } - lasso_node_destroy(assertions_node); - lasso_node_destroy(session_node); - - return session; + if (g_hash_table_size(session->assertions) == 0) + return g_strdup(""); + + return lasso_node_dump(LASSO_NODE(session), NULL, 1); +} + + +void lasso_session_destroy(LassoSession *session) +{ + /* XXX do nothing */ } diff --git a/lasso/id-ff/session.h b/lasso/id-ff/session.h index 89b4a703..054d5711 100644 --- a/lasso/id-ff/session.h +++ b/lasso/id-ff/session.h @@ -31,7 +31,7 @@ extern "C" { #endif /* __cplusplus */ #include <lasso/xml/xml.h> -#include <lasso/protocols/elements/assertion.h> +#include <lasso/xml/lib_assertion.h> #define LASSO_TYPE_SESSION (lasso_session_get_type()) #define LASSO_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_SESSION, LassoSession)) @@ -45,51 +45,44 @@ typedef struct _LassoSessionClass LassoSessionClass; typedef struct _LassoSessionPrivate LassoSessionPrivate; struct _LassoSession { - GObject parent; + LassoNode parent; - /*< public >*/ - GPtrArray *providerIDs; /* list of the remote provider IDs for assertions hash table */ - GHashTable *assertions; /* hash for assertions with remote providerID as key */ + GHashTable *assertions; /* hash for assertions with remote providerID as key */ + gboolean is_dirty; - gboolean is_dirty; - - /*< private >*/ - LassoSessionPrivate *private; /* Index of the current remote provider id in the providerIDs list */ + /*< private >*/ + LassoSessionPrivate *private; }; struct _LassoSessionClass { - GObjectClass parent; + LassoNodeClass parent; }; LASSO_EXPORT GType lasso_session_get_type (void); LASSO_EXPORT LassoSession* lasso_session_new (void); -LASSO_EXPORT LassoSession* lasso_session_new_from_dump (gchar *dump); +LASSO_EXPORT LassoSession* lasso_session_new_from_dump(const gchar *dump); -LASSO_EXPORT gint lasso_session_add_assertion (LassoSession *session, - gchar *providerID, - LassoNode *assertion); +LASSO_EXPORT gint lasso_session_add_assertion(LassoSession *session, + gchar *providerID, LassoSamlAssertion *assertion); -LASSO_EXPORT LassoSession* lasso_session_copy (LassoSession *session); +LASSO_EXPORT gchar* lasso_session_dump(LassoSession *session); -LASSO_EXPORT void lasso_session_destroy (LassoSession *session); +LASSO_EXPORT LassoSamlAssertion* lasso_session_get_assertion( + LassoSession *session, gchar *providerID); -LASSO_EXPORT gchar* lasso_session_dump (LassoSession *session); +LASSO_EXPORT gchar* lasso_session_get_authentication_method(LassoSession *session, + gchar *providerID); -LASSO_EXPORT LassoNode* lasso_session_get_assertion (LassoSession *session, - gchar *providerID); +LASSO_EXPORT gchar* lasso_session_get_first_providerID(LassoSession *session); -LASSO_EXPORT gchar* lasso_session_get_authentication_method (LassoSession *session, - gchar *providerID); +LASSO_EXPORT gchar* lasso_session_get_provider_index(LassoSession *session, gint index); -LASSO_EXPORT gchar* lasso_session_get_first_providerID (LassoSession *session); +LASSO_EXPORT gint lasso_session_remove_assertion(LassoSession *session, gchar *providerID); -LASSO_EXPORT gchar* lasso_session_get_provider_index (LassoSession *session, - gint index); +LASSO_EXPORT void lasso_session_destroy(LassoSession *session); -LASSO_EXPORT gint lasso_session_remove_assertion (LassoSession *session, - gchar *providerID); #ifdef __cplusplus } |