diff options
author | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2010-02-22 13:30:33 +0000 |
---|---|---|
committer | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2010-02-22 13:30:33 +0000 |
commit | 1ee8f53663dc8eb96c2671412c27dddc96a7a831 (patch) | |
tree | 8fcc12682ad2016c86e1053cc71cee93097d4049 | |
parent | 432b54a79dae62687c7eeee6d8cf2da90d38a7cb (diff) | |
download | lasso-1ee8f53663dc8eb96c2671412c27dddc96a7a831.tar.gz lasso-1ee8f53663dc8eb96c2671412c27dddc96a7a831.tar.xz lasso-1ee8f53663dc8eb96c2671412c27dddc96a7a831.zip |
ID-WSF 2.0: reorganize EPR minting, add a process_request method to disco service
* data_service.c:
remove dependency on discovery.h
* discovery.{c,h}:
- add a lasso_idwsf2_discovery_process_request_msg to extract request
data before validate request (SvcMDID, SvcMD or RequestService).
- store SvcMDID in a private field, add a setter for it.
- SvcMDID is now used for building response to MDAssociationQuery and
parsing request for MDQuery, MDDelete, MDAssociationAdd and
MDAssociationDelete.
* idwsf2_helper.{c,h}:
- change security mechanism argument of
lasso_wsa_endpoint_reference_add_security_token from a NULL
terminated string array to a GList.
* saml2_login.{c,h}:
- add a lasso_server_create_assertion_as_idwsf2_security_token for
minting assertion for ID-WSF 2.0 security, to be used in Discovery
bootstap EPR creation and EPR minting for Discovery service Query
responses.
- add a lasso_saml2_assertion_get_discovery_bootstrap_epr, and
rewirte lasso_login_idwsf2_get_discovery_bootstrap_epr to use it.
- make lasso_login_idwsf2_add_discovery_bootstrap_epr accept a list
of security mechanisms, not just one.
* tests/idwsf2_tests.c:
- adapt to new argument type of
lasso_login_idwsf2_add_discovery_bootstrap_epr.
-rw-r--r-- | lasso/id-wsf-2.0/data_service.c | 3 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/discovery.c | 249 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/discovery.h | 10 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/idwsf2_helper.c | 14 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/idwsf2_helper.h | 2 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/profile.c | 3 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/saml2_login.c | 148 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/saml2_login.h | 13 | ||||
-rw-r--r-- | lasso/id-wsf-2.0/soap_binding.c | 2 | ||||
-rw-r--r-- | tests/idwsf2_tests.c | 4 |
10 files changed, 315 insertions, 133 deletions
diff --git a/lasso/id-wsf-2.0/data_service.c b/lasso/id-wsf-2.0/data_service.c index d323a48d..916a9700 100644 --- a/lasso/id-wsf-2.0/data_service.c +++ b/lasso/id-wsf-2.0/data_service.c @@ -34,8 +34,7 @@ #include <libxml/xpath.h> #include <libxml/xpathInternals.h> -#include "discovery.h" -#include "data_service.h" +#include "./data_service.h" #include "../xml/id-wsf-2.0/disco_service_type.h" #include "../xml/id-wsf-2.0/dstref_query.h" diff --git a/lasso/id-wsf-2.0/discovery.c b/lasso/id-wsf-2.0/discovery.c index 5a4ef82a..25baedb1 100644 --- a/lasso/id-wsf-2.0/discovery.c +++ b/lasso/id-wsf-2.0/discovery.c @@ -85,6 +85,7 @@ #include "./discovery.h" #include "./soap_binding.h" #include "./idwsf2_helper.h" +#include "./saml2_login.h" #include "../utils.h" struct _LassoIdWsf2DiscoveryPrivate @@ -92,6 +93,7 @@ struct _LassoIdWsf2DiscoveryPrivate gboolean dispose_has_run; GList *metadatas; /* of LassoIdWsf2DiscoSvcMetadata* */ GList *requested_services; /* of LassoIdWsf2DiscoRequestedService */ + GList *svcmdids; /* of utf8 */ }; #define LASSO_IDWSF2_DISCOVERY_ELEMENT_METADATAS "Metadatas" @@ -99,11 +101,11 @@ struct _LassoIdWsf2DiscoveryPrivate #define LASSO_IDWSF2_DISCOVERY_ELEMENT_REQUESTED_SERVICES "RequestedServices" -static void +static int lasso_idwsf2_discovery_add_identity_to_epr(LassoIdWsf2Discovery *discovery, LassoWsAddrMetadata *epr_metadata, const char *provider_id, - const char *security_mech_id) + const char *security_mechanism) { LassoIdentity *identity = discovery->parent.parent.identity; LassoFederation *federation = NULL; @@ -111,38 +113,34 @@ lasso_idwsf2_discovery_add_identity_to_epr(LassoIdWsf2Discovery *discovery, LassoProvider *provider = NULL; LassoIdWsf2DiscoSecurityContext *security_context; LassoIdWsf2SecToken *sec_token; - LassoSaml2NameID *name_id; - if (LASSO_IS_IDENTITY(identity)) - return; + if (! LASSO_IS_IDENTITY(identity)) + return LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND; federation = lasso_identity_get_federation(identity, provider_id); - if (federation == NULL || ! LASSO_IS_SAML2_NAME_ID(federation->remote_nameIdentifier)) - return; - name_id = (LassoSaml2NameID*)federation->remote_nameIdentifier; - assertion = (LassoSaml2Assertion*)lasso_saml2_assertion_new(); - lasso_server_saml2_assertion_setup_signature(discovery->parent.parent.server, assertion); + if (federation == NULL || ! LASSO_IS_SAML2_NAME_ID(federation->local_nameIdentifier)) + return LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND; provider = lasso_server_get_provider(discovery->parent.parent.server, provider_id); - if (provider) - lasso_saml2_assertion_set_subject_name_id(assertion, - (LassoNode*)lasso_saml2_encrypted_element_build_encrypted_persistent_name_id( - name_id->content, - name_id->NameQualifier, - provider)); - else - lasso_saml2_assertion_set_subject_name_id(assertion, - (LassoNode*)lasso_saml2_name_id_build_persistent( - name_id->content, - name_id->NameQualifier, - provider_id)); + if (! provider) { + return LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND; + } + + assertion = + lasso_server_create_assertion_as_idwsf2_security_token(discovery->parent.parent.server, + LASSO_SAML2_NAME_ID(federation->local_nameIdentifier), + LASSO_DURATION_HOUR, 2 * LASSO_DURATION_DAY, provider ? TRUE : + FALSE, provider); sec_token = (LassoIdWsf2SecToken*)lasso_idwsf2_sec_token_new(); sec_token->any = (LassoNode*)assertion; security_context = (LassoIdWsf2DiscoSecurityContext*) lasso_idwsf2_disco_security_context_new(); lasso_list_add_string(security_context->SecurityMechID, - security_mech_id); + security_mechanism); + lasso_list_add_new_gobject(security_context->Token, sec_token); lasso_list_add_new_gobject(epr_metadata->any, security_context); + + return 0; } @@ -372,7 +370,8 @@ lasso_idwsf2_discovery_add_service_metadata(LassoIdWsf2Discovery *discovery, * @service_types:(element-type utf8)(allow-none): an array of service type URIs * @options:(element-type LassoIdWsf2DiscoOptions)(allow-none): an array of option string * @address:(allow-none): the URI of the service endpoint for the default EndpointContext - * @security_mech_ids:(allow-none)(element-type utf8): the security mechanisms supported by the service + * @security_mechanisms:(allow-none)(element-type utf8): the security mechanisms supported by the + * service * * Add new metadata to the current Metadata Register request. * @@ -381,7 +380,7 @@ lasso_idwsf2_discovery_add_service_metadata(LassoIdWsf2Discovery *discovery, int lasso_idwsf2_discovery_add_simple_service_metadata(LassoIdWsf2Discovery *idwsf2_discovery, const char *abstract, const char *provider_id, GList *service_types, GList *options, - const char *address, GList *security_mech_ids) + const char *address, GList *security_mechanisms) { LassoIdWsf2DiscoSvcMetadata *service_metadata; LassoIdWsf2DiscoServiceContext *service_context; @@ -408,9 +407,10 @@ lasso_idwsf2_discovery_add_simple_service_metadata(LassoIdWsf2Discovery *idwsf2_ if (address) { lasso_list_add_string(endpoint_context->Address, address); } - lasso_list_add_new_gobject(endpoint_context->Framework, lasso_idwsf2_sbf_framework_new_full("2.0")); - if (security_mech_ids) { - lasso_assign_list_of_strings(endpoint_context->SecurityMechID, security_mech_ids); + lasso_list_add_new_gobject(endpoint_context->Framework, + lasso_idwsf2_sbf_framework_new_full("2.0")); + if (security_mechanisms) { + lasso_assign_list_of_strings(endpoint_context->SecurityMechID, security_mechanisms); } lasso_list_add_new_gobject(service_context->EndpointContext, endpoint_context); @@ -472,54 +472,36 @@ cleanup: * * Return the list of SvcMDID, or service metadata ids, returned by the last discovery query. * - * Return value:(transfer none)(element-type utf8): a list of SvcMDID's. + * Return value:(transfer none)(element-type utf8)(allow-none): a list of SvcMDID's. */ GList* lasso_idwsf2_discovery_get_svcmdids(LassoIdWsf2Discovery *discovery) { - GList *content; - GList **svc_md_ids; - - if (! LASSO_IS_IDWSF2_DISCOVERY(discovery)) + if (! LASSO_IS_IDWSF2_DISCOVERY(discovery) || ! discovery->private_data) return NULL; - content = - lasso_soap_envelope_get_body_content( - lasso_idwsf2_profile_get_soap_envelope_request( - &discovery->parent)); - switch (lasso_idwsf2_discovery_get_request_type(discovery)) { - case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_QUERY: - svc_md_ids = &((LassoIdWsf2DiscoSvcMDQuery*) - lasso_list_get_first_child(content))->SvcMDID; - break; - case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_DELETE: - svc_md_ids = &((LassoIdWsf2DiscoSvcMDDelete*) - lasso_list_get_first_child(content))->SvcMDID; - case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_ASSOCIATION_ADD: - svc_md_ids = &((LassoIdWsf2DiscoSvcMDAssociationAdd*) - lasso_list_get_first_child(content))->SvcMDID; - break; - case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_ASSOCIATION_DELETE: - svc_md_ids = &((LassoIdWsf2DiscoSvcMDAssociationDelete*) - lasso_list_get_first_child(content))->SvcMDID; - break; - case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_ASSOCIATION_QUERY: - svc_md_ids = &((LassoIdWsf2DiscoSvcMDAssociationQuery*) - lasso_list_get_first_child(content))->SvcMDID; - break; - default: - break; - } - if (svc_md_ids) { - return *svc_md_ids; - } - return NULL; + return discovery->private_data->svcmdids; } +/** + * lasso_idwsf2_discovery_set_svcmdids: + * @discovery: a #LassoIdWsf2Discovery object + * @svcmdids:(element-type utf8)(allow-none): a list of service metadata IDs + * + * Set the list of SvcMDID, or service metadata ids. + * + */ +void +lasso_idwsf2_discovery_set_svcmdids(LassoIdWsf2Discovery *discovery, GList *svcmdids) +{ + if (! LASSO_IS_IDWSF2_DISCOVERY(discovery) || ! discovery->private_data) + return; + lasso_assign_list_of_strings(discovery->private_data->svcmdids, svcmdids); +} /** * lasso_idwsf2_discovery_build_request_msg: * @discovery: a #LassoIdWsf2Discovery object - * @security_mech_id:(allow-none):the security mech id to use, if NULL a Bearer mechanism is used. + * @security_mechanism:(allow-none):the security mech id to use, if NULL a Bearer mechanism is used. * * Build the request message using a security mechanism to authenticate the requester and the target * identity. If none is given Bearer mechanism is used. @@ -528,7 +510,7 @@ lasso_idwsf2_discovery_get_svcmdids(LassoIdWsf2Discovery *discovery) */ gint lasso_idwsf2_discovery_build_request_msg(LassoIdWsf2Discovery *discovery, - const char *security_mech_id) + const char *security_mechanism) { GList *content = NULL; LassoIdWsf2DiscoQuery *query = NULL; @@ -560,9 +542,11 @@ lasso_idwsf2_discovery_build_request_msg(LassoIdWsf2Discovery *discovery, check_svcMDID = TRUE; metadatas = &((LassoIdWsf2DiscoSvcMDReplace*) lasso_list_get_first_child(content))->SvcMD; + break; case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_DELETE: svc_md_ids = &((LassoIdWsf2DiscoSvcMDDelete*) lasso_list_get_first_child(content))->SvcMDID; + break; case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_ASSOCIATION_ADD: svc_md_ids = &((LassoIdWsf2DiscoSvcMDAssociationAdd*) lasso_list_get_first_child(content))->SvcMDID; @@ -598,21 +582,95 @@ lasso_idwsf2_discovery_build_request_msg(LassoIdWsf2Discovery *discovery, } } if (svc_md_ids) { - GList *i; - lasso_foreach(i, discovery->private_data->metadatas) - { - if (LASSO_IS_IDWSF2_DISCO_SVC_METADATA(i->data)) { - lasso_list_add_string(*svc_md_ids, - ((LassoIdWsf2DiscoSvcMetadata*)i->data)->svcMDID); - } - } + lasso_assign_list_of_strings(*svc_md_ids, discovery->private_data->svcmdids); } - rc = lasso_idwsf2_profile_build_request_msg(&discovery->parent, security_mech_id); + rc = lasso_idwsf2_profile_build_request_msg(&discovery->parent, security_mechanism); cleanup: return rc; } /** + * lasso_idwsf2_discovery_process_request_msg: + * @discovery: a #LassoIdWsf2Discovery object + * @message: a received SOAP message + * + * Parse a Discovery service request. + * + * Return value: 0 if sucessful, an error code otherwise among: + * <itemizedlist> + * <listitem><para>LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ if @profile is not a #LassoIdWsf2Profile + * object,</para></listitem> + * <listitem><para>LASSO_PARAM_ERROR_INVALID_VALUE if message is NULL,</para></listitem> + * <listitem><para>LASSO_PROFILE_ERROR_INVALID_MSG if we cannot parse the message,</para></listitem> + * <listitem><para>LASSO_SOAP_ERROR_MISSING_BODY if the message has no body + * content.</para></listitem> + * </itemizedlist> + */ +int +lasso_idwsf2_discovery_process_request_msg(LassoIdWsf2Discovery *discovery, const char *message) +{ + LassoProfile *profile; + LassoIdWsf2Profile *idwsf2_profile; + GList *content; + GList **svc_md_ids = NULL, **metadatas = NULL, **service_types = NULL; + int rc; + + lasso_bad_param(IDWSF2_DISCOVERY, discovery); + idwsf2_profile = &discovery->parent; + profile = &idwsf2_profile->parent; + + lasso_check_good_rc(lasso_idwsf2_profile_process_request_msg(idwsf2_profile, message)); + + content = + lasso_soap_envelope_get_body_content( + lasso_idwsf2_profile_get_soap_envelope_request( + &discovery->parent)); + switch (lasso_idwsf2_discovery_get_request_type(discovery)) { + case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_REGISTER: + metadatas = &((LassoIdWsf2DiscoSvcMDRegister*) + lasso_list_get_first_child(content))->SvcMD; + break; + case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_QUERY: + service_types = &((LassoIdWsf2DiscoQuery*) + lasso_list_get_first_child(content))->RequestedService; + case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_QUERY: + svc_md_ids = &((LassoIdWsf2DiscoSvcMDQuery*) + lasso_list_get_first_child(content))->SvcMDID; + break; + case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_DELETE: + svc_md_ids = &((LassoIdWsf2DiscoSvcMDDelete*) + lasso_list_get_first_child(content))->SvcMDID; + case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_ASSOCIATION_ADD: + svc_md_ids = &((LassoIdWsf2DiscoSvcMDAssociationAdd*) + lasso_list_get_first_child(content))->SvcMDID; + break; + case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_ASSOCIATION_DELETE: + svc_md_ids = &((LassoIdWsf2DiscoSvcMDAssociationDelete*) + lasso_list_get_first_child(content))->SvcMDID; + break; + case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_MD_ASSOCIATION_QUERY: + svc_md_ids = &((LassoIdWsf2DiscoSvcMDAssociationQuery*) + lasso_list_get_first_child(content))->SvcMDID; + break; + default: + break; + } + if (discovery->private_data && svc_md_ids) { + lasso_assign_list_of_strings(discovery->private_data->svcmdids, *svc_md_ids); + } + if (metadatas) { + lasso_assign_list_of_gobjects(discovery->private_data->metadatas, *metadatas); + } + if (service_types) { + lasso_assign_list_of_gobjects(discovery->private_data->requested_services, *service_types); + } + +cleanup: + return rc; +} + + +/** * lasso_idwsf2_discovery_get_request_type: * @discovery: a #LassoIdWsf2Discovery object * @@ -808,8 +866,8 @@ lasso_idwsf2_discovery_match_request_service_and_metadata2( GList *i; gboolean result = TRUE; gboolean option_result = TRUE; - LassoIdWsf2DiscoOptions *options; - GList *service_options; + LassoIdWsf2DiscoOptions *options = NULL; + GList *service_options = NULL; result = result && @@ -848,7 +906,14 @@ lasso_idwsf2_discovery_match_request_service_and_metadata2( _string_list_intersect(requested_service->Framework, endpoint_context->Framework); } else { /* FIXME: should be the value of the query SOAP header sbf:Framework */ - result = result && _string_list_contains(endpoint_context->Framework, "2.0"); + GList *k; + gboolean has20 = FALSE; + lasso_foreach (k, endpoint_context->Framework) { + LassoIdWsf2SbfFramework *framework = k->data; + if (LASSO_IS_IDWSF2_SBF_FRAMEWORK(framework) && g_strcmp0(framework->version, "2.0") == 0) + has20 = TRUE; + } + result = result && has20; } } if (result) { @@ -1020,6 +1085,9 @@ lasso_idwsf2_discovery_validate_request(LassoIdWsf2Discovery *discovery) lasso_list_add_gobject(md_query_response->SvcMD, i->data); } } + } else { + lasso_assign_list_of_gobjects(md_query_response->SvcMD, + discovery->private_data->metadatas); } status = &md_query_response->Status; break; @@ -1119,6 +1187,9 @@ lasso_idwsf2_discovery_process_metadata_register_response_msg(LassoIdWsf2Discove i = i->next; j = j->next; } + if (discovery->private_data && discovery->private_data->metadatas != request->SvcMD) { + lasso_assign_list_of_gobjects(discovery->private_data->metadatas, request->SvcMD); + } cleanup: return rc; } @@ -1130,10 +1201,11 @@ cleanup: * @service_types:(element-type utf8)(allow-none): the service type (or data profile) requested * @provider_ids:(element-type utf8)(allow-none): the providers ids to select * @options:(element-type utf8)(allow-none): the options to select - * @security_mech_ids:(element-type utf8)(allow-none): the security mechanisms to select + * @security_mechanisms:(element-type utf8)(allow-none): the security mechanisms to select * @frameworks:(element-type utf8)(allow-none): the ID-WSF framework version to select * @actions:(element-type utf8)(allow-none): the actions to select - * @result_type:(allow-none)(default LASSO_IDWSF2_DISCOVERY_QUERY_RESULT_TYPE_NONE): how to filter the generated EPRs + * @result_type:(allow-none)(default LASSO_IDWSF2_DISCOVERY_QUERY_RESULT_TYPE_NONE): how to filter + * the generated EPRs * @req_id:(allow-none): an eventual ID to put on the request, that can be matched with the * generated EndpointReferences * @@ -1144,7 +1216,7 @@ cleanup: **/ gint lasso_idwsf2_discovery_add_requested_service(LassoIdWsf2Discovery *discovery, - GList *service_types, GList *provider_ids, GList *options, GList *security_mech_ids, + GList *service_types, GList *provider_ids, GList *options, GList *security_mechanisms, GList *frameworks, GList *actions, LassoIdWsf2DiscoveryQueryResultType result_type, const char *req_id) { @@ -1159,7 +1231,7 @@ lasso_idwsf2_discovery_add_requested_service(LassoIdWsf2Discovery *discovery, lasso_assign_list_of_strings(service->ProviderID, provider_ids); lasso_assign_list_of_strings(service->Framework, frameworks); lasso_assign_list_of_strings(service->Action, actions); - lasso_assign_list_of_strings(service->SecurityMechID, security_mech_ids); + lasso_assign_list_of_strings(service->SecurityMechID, security_mechanisms); lasso_assign_list_of_gobjects(service->Options, options); switch (result_type) { case LASSO_IDWSF2_DISCOVERY_QUERY_RESULT_TYPE_BEST: @@ -1205,9 +1277,9 @@ lasso_idwsf2_discovery_process_response_msg(LassoIdWsf2Discovery *discovery, lasso_bad_param(IDWSF2_DISCOVERY, discovery); profile = &discovery->parent.parent; - response = profile->response; lasso_check_good_rc(lasso_idwsf2_profile_process_response_msg(&discovery->parent, msg)); + response = profile->response; switch (lasso_idwsf2_discovery_get_request_type(discovery)) { case LASSO_IDWSF2_DISCOVERY_REQUEST_TYPE_QUERY: @@ -1320,7 +1392,8 @@ get_xmlNode(LassoNode *node, gboolean lasso_dump) if (pdata->requested_services) { xmlNode *requested_services; GList *i; - requested_services = xmlNewChild(xmlnode, NULL, BAD_CAST LASSO_IDWSF2_DISCOVERY_ELEMENT_REQUESTED_SERVICES, NULL); + requested_services = xmlNewChild(xmlnode, NULL, BAD_CAST + LASSO_IDWSF2_DISCOVERY_ELEMENT_REQUESTED_SERVICES, NULL); lasso_foreach(i, pdata->requested_services) { xmlAddChild(requested_services, lasso_node_get_xmlNode(i->data, lasso_dump)); } @@ -1345,8 +1418,12 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode) if (xmlnode == NULL) return LASSO_XML_ERROR_OBJECT_CONSTRUCTION_FAILED; - metadatas_node = xmlSecFindChild(xmlnode, BAD_CAST LASSO_IDWSF2_DISCOVERY_ELEMENT_METADATAS, BAD_CAST LASSO_LASSO_HREF); - requested_services_node = xmlSecFindChild(xmlnode, BAD_CAST LASSO_IDWSF2_DISCOVERY_ELEMENT_REQUESTED_SERVICES, BAD_CAST LASSO_LASSO_HREF); + metadatas_node = xmlSecFindChild(xmlnode, + BAD_CAST LASSO_IDWSF2_DISCOVERY_ELEMENT_METADATAS, + BAD_CAST LASSO_LASSO_HREF); + requested_services_node = xmlSecFindChild(xmlnode, + BAD_CAST LASSO_IDWSF2_DISCOVERY_ELEMENT_REQUESTED_SERVICES, + BAD_CAST LASSO_LASSO_HREF); if (! discovery->private_data) { discovery->private_data = g_new0(LassoIdWsf2DiscoveryPrivate, 1); diff --git a/lasso/id-wsf-2.0/discovery.h b/lasso/id-wsf-2.0/discovery.h index ca75194e..bdb83595 100644 --- a/lasso/id-wsf-2.0/discovery.h +++ b/lasso/id-wsf-2.0/discovery.h @@ -105,6 +105,7 @@ LASSO_EXPORT gint lasso_idwsf2_discovery_init_query(LassoIdWsf2Discovery *discov LASSO_EXPORT gint lasso_idwsf2_discovery_init_metadata_query(LassoIdWsf2Discovery *discovery); LASSO_EXPORT gint lasso_idwsf2_discovery_init_metadata_register(LassoIdWsf2Discovery *discovery); LASSO_EXPORT gint lasso_idwsf2_discovery_init_metadata_replace(LassoIdWsf2Discovery *discovery); +LASSO_EXPORT gint lasso_idwsf2_discovery_init_metadata_delete(LassoIdWsf2Discovery *discovery); LASSO_EXPORT gint lasso_idwsf2_discovery_init_metadata_association_add( LassoIdWsf2Discovery *discovery); LASSO_EXPORT gint lasso_idwsf2_discovery_init_metadata_association_delete( @@ -118,18 +119,20 @@ LASSO_EXPORT int lasso_idwsf2_discovery_add_service_metadata( LASSO_EXPORT int lasso_idwsf2_discovery_add_simple_service_metadata( LassoIdWsf2Discovery *idwsf2_discovery, const char *abstract, const char *provider_id, GList *service_types, GList *options, const char *address, - GList *security_mech_ids); + GList *security_mechanisms); LASSO_EXPORT GList* lasso_idwsf2_discovery_get_metadatas(LassoIdWsf2Discovery *discovery); LASSO_EXPORT gint lasso_idwsf2_discovery_add_requested_service(LassoIdWsf2Discovery *discovery, - GList *service_types, GList *provider_ids, GList *options, GList *security_mech_ids, + GList *service_types, GList *provider_ids, GList *options, GList *security_mechanisms, GList *frameworks, GList *actions, LassoIdWsf2DiscoveryQueryResultType result_type, const char *req_id); /* Build the request message */ LASSO_EXPORT gint lasso_idwsf2_discovery_build_request_msg(LassoIdWsf2Discovery *discovery, - const char *security_mech_id); + const char *security_mechanism); /* Handle a request */ +LASSO_EXPORT int lasso_idwsf2_discovery_process_request_msg(LassoIdWsf2Discovery *discovery, + const char *message); LASSO_EXPORT LassoIdWsf2DiscoveryRequestType lasso_idwsf2_discovery_get_request_type(LassoIdWsf2Discovery *discovery); LASSO_EXPORT gint lasso_idwsf2_discovery_validate_request(LassoIdWsf2Discovery *discovery); LASSO_EXPORT gint lasso_idwsf2_discovery_fail_request(LassoIdWsf2Discovery *discovery, @@ -140,6 +143,7 @@ LASSO_EXPORT gint lasso_idwsf2_discovery_process_response_msg(LassoIdWsf2Discove const char *msg); LASSO_EXPORT GList* lasso_idwsf2_discovery_get_endpoint_references(LassoIdWsf2Discovery *discovery); LASSO_EXPORT GList* lasso_idwsf2_discovery_get_svcmdids(LassoIdWsf2Discovery *discovery); +LASSO_EXPORT void lasso_idwsf2_discovery_set_svcmdids(LassoIdWsf2Discovery *discovery, GList *svcmdids); #ifdef __cplusplus diff --git a/lasso/id-wsf-2.0/idwsf2_helper.c b/lasso/id-wsf-2.0/idwsf2_helper.c index c7173e1c..33326c75 100644 --- a/lasso/id-wsf-2.0/idwsf2_helper.c +++ b/lasso/id-wsf-2.0/idwsf2_helper.c @@ -279,7 +279,7 @@ lasso_wsa_endpoint_reference_new_for_idwsf2_service(const char *address, * lasso_wsa_endpoint_reference_add_security_token: * @epr: a #LassoWsAddrEndpointReference object * @security_token: a security token as a #LassoNode object - * @security_mechanisms:(in)(transfer none)(array zero-terminated=1): a list of security mechanism + * @security_mechanisms:(element-type utf8): a list of security mechanism * for whom the token is made * * Add a new security context declaration for the given security mechanisms identifiers and populate @@ -289,7 +289,7 @@ lasso_wsa_endpoint_reference_new_for_idwsf2_service(const char *address, */ int lasso_wsa_endpoint_reference_add_security_token(LassoWsAddrEndpointReference *epr, - LassoNode *security_token, const char **security_mechanisms) + LassoNode *security_token, GList *security_mechanisms) { LassoIdWsf2SecToken *sec_token = NULL; LassoWsAddrMetadata *metadata = NULL; @@ -298,10 +298,6 @@ lasso_wsa_endpoint_reference_add_security_token(LassoWsAddrEndpointReference *ep lasso_bad_param(WSA_ENDPOINT_REFERENCE, epr); lasso_bad_param(NODE, security_token); - lasso_null_param(security_mechanisms); - if (security_mechanisms[0] == NULL) { - return LASSO_PARAM_ERROR_INVALID_VALUE; - } lasso_extract_node_or_fail(metadata, epr->Metadata, WSA_METADATA, LASSO_PARAM_ERROR_INVALID_VALUE); @@ -310,10 +306,8 @@ lasso_wsa_endpoint_reference_add_security_token(LassoWsAddrEndpointReference *ep lasso_assign_string(sec_token->usage, LASSO_IDWSF2_SEC_TOKEN_USAGE_SECURITY_TOKEN); security_context = lasso_idwsf2_disco_security_context_new(); - while (security_mechanisms[0] != NULL) { - lasso_list_add_string(security_context->SecurityMechID, security_mechanisms[0]); - ++security_mechanisms; - } + lasso_assign_list_of_strings(security_context->SecurityMechID, + security_mechanisms); lasso_list_add_new_gobject(security_context->Token, sec_token); lasso_list_add_new_gobject(metadata->any, security_context); cleanup: diff --git a/lasso/id-wsf-2.0/idwsf2_helper.h b/lasso/id-wsf-2.0/idwsf2_helper.h index a9aeb38c..a2e469e2 100644 --- a/lasso/id-wsf-2.0/idwsf2_helper.h +++ b/lasso/id-wsf-2.0/idwsf2_helper.h @@ -59,7 +59,7 @@ LASSO_EXPORT LassoWsAddrEndpointReference* lasso_wsa_endpoint_reference_new_for_ const char *abstract); LASSO_EXPORT int lasso_wsa_endpoint_reference_add_security_token(LassoWsAddrEndpointReference *epr, - LassoNode *security_token, const char **security_mechanisms); + LassoNode *security_token, GList *security_mechanisms); LASSO_EXPORT LassoIdWsf2Profile *lasso_wsa_endpoint_reference_get_service( LassoWsAddrEndpointReference *epr); diff --git a/lasso/id-wsf-2.0/profile.c b/lasso/id-wsf-2.0/profile.c index 51d8251b..7f9ca7e8 100644 --- a/lasso/id-wsf-2.0/profile.c +++ b/lasso/id-wsf-2.0/profile.c @@ -422,6 +422,9 @@ lasso_idwsf2_profile_check_security_mechanism(LassoIdWsf2Profile *profile, provider_id = lasso_soap_envelope_sb2_get_provider_id(envelope); if (! provider_id) goto cleanup; + if (! profile->parent.server) + goto_cleanup_with_rc(LASSO_PROFILE_ERROR_MISSING_SERVER); + lasso_check_good_rc(lasso_saml2_assertion_decrypt_subject(assertion, profile->parent.server)); if (! assertion || ! assertion->Subject || ! assertion->Subject->NameID || ! assertion->Subject->NameID->SPNameQualifier) goto cleanup; diff --git a/lasso/id-wsf-2.0/saml2_login.c b/lasso/id-wsf-2.0/saml2_login.c index 1d6f4f69..dafe58a3 100644 --- a/lasso/id-wsf-2.0/saml2_login.c +++ b/lasso/id-wsf-2.0/saml2_login.c @@ -28,6 +28,7 @@ #include "session.h" #include "../id-ff/login.h" #include "../saml-2.0/saml2_helper.h" +#include "../saml-2.0/provider.h" #include "../xml/saml-2.0/saml2_assertion.h" #include "../xml/ws/wsa_endpoint_reference.h" #include "../xml/id-wsf-2.0/disco_abstract.h" @@ -47,19 +48,87 @@ /** + * lasso_server_create_assertion_as_idwsf2_security_token: + * @server: a #LassoServer object + * @name_id: a #LassoSaml2NameID object + * @tolerance: tolerance around the normal duration which is accepted + * @duration: life duration for this assertion in seconds + * @cipher: whether to cipher the NameID + * @audience:(allow-none)(optional): if @cipher is true, the provider for which to encrypt the NameID + * + * Create a new assertion usable as a security token in an ID-WSF 2.0 EndpointReference. See + * lasso_saml2_assertion_set_basic_conditions() for detail about @tolerance and @duration. + * + * Return value:(transfer full)(allow-none): a newly allocated #LassoSaml2Assertion object, or NULL. + */ +LassoSaml2Assertion* +lasso_server_create_assertion_as_idwsf2_security_token(LassoServer *server, + LassoSaml2NameID *name_id, + int tolerance, + int duration, + gboolean cipher, + LassoProvider *audience) +{ + LassoSaml2Assertion *assertion; + int rc; + + if (! LASSO_IS_SERVER(server)) + return NULL; + if (! LASSO_IS_SAML2_NAME_ID(name_id)) + return NULL; + if (cipher && ! LASSO_IS_PROVIDER(audience)) + return NULL; + + assertion = (LassoSaml2Assertion*)lasso_saml2_assertion_new(); + assertion->ID = lasso_build_unique_id(32); + assertion->Issuer = (LassoSaml2NameID*)lasso_saml2_name_id_new_with_string(server->parent.ProviderID); + assertion->Subject = (LassoSaml2Subject*)lasso_saml2_subject_new(); + if (cipher) { + LassoSaml2EncryptedElement *encrypted_id = + lasso_provider_saml2_node_encrypt(audience, (LassoNode*)name_id); + if (! encrypted_id) { + lasso_release_gobject(assertion); + goto cleanup; + } + lasso_assign_gobject(assertion->Subject->EncryptedID, encrypted_id); + } else { + lasso_assign_new_gobject(assertion->Subject->NameID, name_id); + } + lasso_saml2_assertion_set_basic_conditions(assertion, + tolerance, duration, FALSE); + rc = lasso_server_saml2_assertion_setup_signature(server, assertion); + if (rc != 0) { + lasso_release_gobject(assertion); + } +cleanup: + return assertion; +} + + + + +/** * lasso_login_idwsf2_add_discovery_bootstrap_epr: * @login: a #LassoLogin object + * @url: the Disco service address + * @abstract: the Disco service description + * @security_mechanisms:(allow-none)(element-type utf8): the list of supported security mechanisms + * @tolerance:(default -1): see lasso_saml2_assertion_set_basic_conditions(). + * @duration:(default 0): see lasso_saml2_assertion_set_basic_conditions(). * * Add the needed bootstrap attribute to the #LassoSaml2Assertion currently container in the * #LassoLogin object. This function should be called after lasso_login_build_assertion() by an IdP * also having the Discovery service role. * + * The default @tolerance and @duration are respectively ten minutes and two days. + * * Return value: 0 if successfull, otherwise #LASSO_PROFILE_ERROR_MISSING_ASSERTION if no assertion is present * in the #LassoLogin object, #LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ if login is not a #LassoLogin * object. */ int -lasso_login_idwsf2_add_discovery_bootstrap_epr(LassoLogin *login, const char *url, const char *abstract, const char *security_mech_id) +lasso_login_idwsf2_add_discovery_bootstrap_epr(LassoLogin *login, const char *url, + const char *abstract, GList *security_mechanisms, int tolerance, int duration) { LassoWsAddrEndpointReference *epr = NULL; LassoWsAddrMetadata *metadata = NULL; @@ -71,8 +140,8 @@ lasso_login_idwsf2_add_discovery_bootstrap_epr(LassoLogin *login, const char *ur LassoSaml2Assertion *assertion_identity_token = NULL; LassoSaml2Assertion *assertion = NULL; LassoServer *server = NULL; + LassoSaml2NameID *name_id = NULL; int rc = 0; - const char *security_mechanisms[] = { security_mech_id, NULL }; lasso_bad_param(LOGIN, login); lasso_null_param(url); @@ -97,21 +166,26 @@ lasso_login_idwsf2_add_discovery_bootstrap_epr(LassoLogin *login, const char *ur url, LASSO_IDWSF2_DISCOVERY_HREF, server->parent.ProviderID, abstract); /* Security/Identity token */ - assertion_identity_token = LASSO_SAML2_ASSERTION(lasso_saml2_assertion_new()); - assertion_identity_token->ID = lasso_build_unique_id(32); - assertion_identity_token->Issuer = (LassoSaml2NameID*)lasso_saml2_name_id_new_with_string(server->parent.ProviderID); - lasso_assign_gobject(assertion_identity_token->Subject, - assertion->Subject); - lasso_saml2_assertion_set_basic_conditions(assertion_identity_token, - 5, 2*LASSO_DURATION_DAY, FALSE); - - /* Do we sign the assertion ? */ - if (lasso_security_mech_id_is_saml_authentication(security_mech_id) || lasso_security_mech_id_is_bearer_authentication(security_mech_id)) { - lasso_check_good_rc(lasso_server_saml2_assertion_setup_signature(login->parent.server, - assertion_identity_token)); + if (duration <= 0) { + duration = 2 * LASSO_DURATION_DAY; } + if (tolerance < 0) { + tolerance = 10*LASSO_DURATION_MINUTE; + } + /* If the NameID is encrypted try to get to he unencrypted one */ + if (assertion->Subject->NameID) { + name_id = assertion->Subject->NameID; + } else if (assertion->Subject->EncryptedID && + LASSO_IS_SAML2_NAME_ID(assertion->Subject->EncryptedID->original_data)) { + name_id = (LassoSaml2NameID*)assertion->Subject->EncryptedID->original_data; + } + goto_cleanup_if_fail_with_rc (name_id, LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER); + assertion_identity_token = lasso_server_create_assertion_as_idwsf2_security_token(server, + name_id, tolerance, duration, TRUE, &server->parent); - rc = lasso_wsa_endpoint_reference_add_security_token(epr, (LassoNode*)assertion_identity_token, security_mechanisms); + /* Add the assertion to the EPR */ + rc = lasso_wsa_endpoint_reference_add_security_token(epr, + (LassoNode*)assertion_identity_token, security_mechanisms); goto_cleanup_if_fail(rc == 0); /* Add the EPR to the assertion as a SAML attribute */ @@ -133,29 +207,22 @@ cleanup: } /** - * lasso_login_idwsf2_get_discovery_bootstrap_epr: - * @login: a #LassoLogin object + * lasso_saml2_assertion_idwsf2_get_discovery_bootstrap_epr: + * @assertion: a #LassoSaml2Assertion object * - * Extract the Discovery boostrap EPR from the attribute named #LASSO_SAML2_ATTRIBUTE_NAME_EPR. + * Extract the Discovery bootstrap EPR from @assertion. * - * Return value: a caller owned #LassoWsAddrEndpointReference object, or NULL if none can be found. + * Return value:(transfer none): a #LassoWsAddrEndpointReference or NULL if no bootstrap EPR is found. */ -LassoWsAddrEndpointReference * -lasso_login_idwsf2_get_discovery_bootstrap_epr(LassoLogin *login) +LassoWsAddrEndpointReference* +lasso_saml2_assertion_idwsf2_get_discovery_bootstrap_epr(LassoSaml2Assertion *assertion) { - LassoProfile *profile = NULL; - LassoSession *session = NULL; - LassoSaml2Assertion *assertion = NULL; LassoSaml2AttributeStatement *attribute_statement = NULL; LassoSaml2Attribute *attribute = NULL; LassoSaml2AttributeValue *attribute_value = NULL; GList *i = NULL, *j = NULL, *k = NULL; LassoWsAddrEndpointReference *rc = NULL; - g_return_val_if_fail (LASSO_IS_LOGIN (login), NULL); - profile = &login->parent; - lasso_extract_node_or_fail (session, profile->session, SESSION, NULL); - assertion = (LassoSaml2Assertion*)lasso_login_get_assertion(login); if (! LASSO_IS_SAML2_ASSERTION (assertion)) { return NULL; } @@ -198,4 +265,29 @@ lasso_login_idwsf2_get_discovery_bootstrap_epr(LassoLogin *login) cleanup: return rc; + +} + +/** + * lasso_login_idwsf2_get_discovery_bootstrap_epr: + * @login: a #LassoLogin object + * + * Extract the Discovery boostrap EPR from the attribute named #LASSO_SAML2_ATTRIBUTE_NAME_EPR. + * + * Return value:(transfer none): a caller owned #LassoWsAddrEndpointReference object, or NULL if none can be found. + */ +LassoWsAddrEndpointReference * +lasso_login_idwsf2_get_discovery_bootstrap_epr(LassoLogin *login) +{ + LassoProfile *profile = NULL; + LassoSaml2Assertion *assertion = NULL; + LassoWsAddrEndpointReference *rc = NULL; + + g_return_val_if_fail (LASSO_IS_LOGIN (login), NULL); + profile = &login->parent; + assertion = (LassoSaml2Assertion*)lasso_login_get_assertion(login); + rc = lasso_saml2_assertion_idwsf2_get_discovery_bootstrap_epr(assertion); + lasso_release_gobject(assertion); + + return rc; } diff --git a/lasso/id-wsf-2.0/saml2_login.h b/lasso/id-wsf-2.0/saml2_login.h index db4bcd51..681ac707 100644 --- a/lasso/id-wsf-2.0/saml2_login.h +++ b/lasso/id-wsf-2.0/saml2_login.h @@ -30,15 +30,24 @@ extern "C" { #endif /* __cplusplus */ #include "../id-ff/login.h" +#include "../id-ff/provider.h" #include "../xml/saml-2.0/saml2_assertion.h" +#include "../xml/saml-2.0/saml2_name_id.h" #include "../xml/ws/wsa_endpoint_reference.h" LASSO_EXPORT int lasso_login_idwsf2_add_discovery_bootstrap_epr(LassoLogin *login, const char *url, - const char *abstract, const char *security_mech_id); - + const char *abstract, GList *security_mechanisms, int tolerance, int duration); + LASSO_EXPORT LassoWsAddrEndpointReference *lasso_login_idwsf2_get_discovery_bootstrap_epr( LassoLogin *login); +LASSO_EXPORT LassoWsAddrEndpointReference* + lasso_saml2_assertion_idwsf2_get_discovery_bootstrap_epr(LassoSaml2Assertion *assertion); + +LASSO_EXPORT LassoSaml2Assertion* lasso_server_create_assertion_as_idwsf2_security_token( + LassoServer *server, LassoSaml2NameID *name_id, int tolerance, int duration, + gboolean cipher, LassoProvider *audience); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/id-wsf-2.0/soap_binding.c b/lasso/id-wsf-2.0/soap_binding.c index e5a7f446..e4724eb7 100644 --- a/lasso/id-wsf-2.0/soap_binding.c +++ b/lasso/id-wsf-2.0/soap_binding.c @@ -199,6 +199,8 @@ lasso_soap_envelope_get_saml2_security_token(LassoSoapEnvelope *soap_envelope) GList *it; security = lasso_soap_envelope_wssec_get_security_header (soap_envelope); + if (! security) + return NULL; lasso_foreach (it, security->any) { if (LASSO_IS_SAML2_ASSERTION (it->data)) { return (LassoSaml2Assertion*)g_object_ref(it->data); diff --git a/tests/idwsf2_tests.c b/tests/idwsf2_tests.c index 25360801..027c02bb 100644 --- a/tests/idwsf2_tests.c +++ b/tests/idwsf2_tests.c @@ -165,6 +165,8 @@ prepare_saml2_authn_request(LassoLogin *splogin, LassoLogin *idplogin) static void process_authn_request(LassoLogin *splogin, LassoLogin *idplogin) { + GList node = { .data = LASSO_SECURITY_MECH_BEARER, .next = NULL }; + check_good_rc(lasso_login_process_authn_request_msg(idplogin, strchr(splogin->parent.msg_url,'?')+1)); lasso_login_must_authenticate(idplogin); check_false(lasso_login_must_ask_for_consent(idplogin)); @@ -177,7 +179,7 @@ process_authn_request(LassoLogin *splogin, LassoLogin *idplogin) "FIXME: notOnOrAfter")); check_good_rc(lasso_login_idwsf2_add_discovery_bootstrap_epr(idplogin, "http://example.com/disco", "Discovery Service Description", - LASSO_SECURITY_MECH_BEARER)); + &node, -1, 0)); check_good_rc(lasso_login_build_artifact_msg(idplogin, LASSO_HTTP_METHOD_ARTIFACT_GET)); } |