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.
This commit is contained in:
Benjamin Dauvergne 2010-02-22 13:30:33 +00:00
parent 432b54a79d
commit 1ee8f53663
10 changed files with 315 additions and 133 deletions

View File

@ -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"

View File

@ -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,20 +582,94 @@ 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);

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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"
@ -46,20 +47,88 @@
#include "../xml/private.h"
/**
* 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;
}

View File

@ -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 */

View File

@ -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);

View File

@ -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));
}