lasso/lasso/id-wsf-2.0/idwsf2_helper.c

383 lines
13 KiB
C

/* $Id: idwsf2_data_service.c 3101 2007-05-30 11:40:10Z dlaniel $
*
* Lasso - A free implementation of the Liberty Alliance specifications.
*
* Copyright (C) 2004-2007 Entr'ouvert
* http://lasso.entrouvert.org
*
* Authors: See AUTHORS file in top-level directory.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "./idwsf2_helper.h"
#include "../xml/id-wsf-2.0/idwsf2_strings.h"
#include "../xml/id-wsf-2.0/disco_abstract.h"
#include "../xml/id-wsf-2.0/disco_service_type.h"
#include "../xml/id-wsf-2.0/disco_provider_id.h"
#include "../xml/id-wsf-2.0/sec_token.h"
#include "../xml/id-wsf-2.0/sbf_framework.h"
#include "../xml/misc_text_node.h"
#include "../utils.h"
/**
* SECTION: idwsf2-helper
*
* Methods to help manipulate EPR elements
*/
/**
* lasso_wsa_endpoint_reference_get_idwsf2_service_type:
*
* Return the disco:ServiceType metadata element content
*
* Return value: (transfer none): the content of the first disco:ServiceType metadata, or NULL if
* none is found.
*/
const char*
lasso_wsa_endpoint_reference_get_idwsf2_service_type(const LassoWsAddrEndpointReference *epr)
{
LassoIdWsf2DiscoServiceType *disco2_service_type;
if (! LASSO_IS_WSA_ENDPOINT_REFERENCE (epr) || epr->Metadata == NULL)
return NULL;
disco2_service_type = lasso_extract_gobject_from_list (LassoIdWsf2DiscoServiceType,
LASSO_TYPE_IDWSF2_DISCO_SERVICE_TYPE, epr->Metadata->any);
if (disco2_service_type) {
return disco2_service_type->content;
}
return NULL;
}
/**
* lasso_wsa_endpoint_reference_get_idwsf2_provider_id
* @epr: a #LassoWsAddrEndpointReference object
*
* Return the provider ID from the the metadata element of the EPR.
*
* Return value: an entityID identifier or NULL if none is found, or the element is empty.
*/
const char*
lasso_wsa_endpoint_reference_get_idwsf2_provider_id(const LassoWsAddrEndpointReference *epr)
{
LassoIdWsf2DiscoProviderID *disco2_provider_id;
if (! LASSO_IS_WSA_ENDPOINT_REFERENCE (epr) || epr->Metadata == NULL)
return NULL;
/* Get the service type from the EPR */
disco2_provider_id = lasso_extract_gobject_from_list (LassoIdWsf2DiscoProviderID,
LASSO_TYPE_IDWSF2_DISCO_PROVIDER_ID, epr->Metadata->any);
if (disco2_provider_id) {
return disco2_provider_id->content;
}
return NULL;
}
/**
* lasso_wsa_endpoint_reference_get_idwsf2_security_context_for_security_mechanism:
* @epr: a #LassoWsAddrEndpointReference object
* @security_mech_predicate: (allow-none): a predicate to test for security mechanism
* @security_mech_id: (allow-none): a security mechanism identifier
* @create: allow to create the element if none if found, @security_mech_id is mandatory when create
* is TRUE.
*
* Return value: (transfer none): a #LassoIdWsf2DiscoSecurityContext, or NULL if none was found and
* created is FALSE.
*/
LassoIdWsf2DiscoSecurityContext*
lasso_wsa_endpoint_reference_get_idwsf2_security_context_for_security_mechanism(
const LassoWsAddrEndpointReference *epr,
gboolean (*sech_mech_predicate)(const char *),
const char *security_mech_id,
gboolean create)
{
LassoIdWsf2DiscoSecurityContext *created = NULL;
LassoMiscTextNode *new_security_mech_id_declaration;
if (! LASSO_IS_WSA_ENDPOINT_REFERENCE (epr) || epr->Metadata == NULL)
return NULL;
lasso_foreach_full_begin(LassoIdWsf2DiscoSecurityContext*, context, it1, epr->Metadata->any);
if (LASSO_IS_IDWSF2_DISCO_SECURITY_CONTEXT (context)) {
lasso_foreach_full_begin(char*, textnode, it2, context->SecurityMechID);
if (lasso_strisequal(textnode,security_mech_id) || sech_mech_predicate(textnode)) {
return context;
}
lasso_foreach_full_end()
}
lasso_foreach_full_end();
if (create && security_mech_id) {
created = lasso_idwsf2_disco_security_context_new();
new_security_mech_id_declaration =
lasso_misc_text_node_new_with_string(security_mech_id);
new_security_mech_id_declaration->name = "SecurityMechID";
new_security_mech_id_declaration->ns_href = LASSO_IDWSF2_DISCOVERY_HREF;
new_security_mech_id_declaration->ns_prefix = LASSO_IDWSF2_DISCOVERY_PREFIX;
lasso_list_add_new_gobject (created->SecurityMechID,
new_security_mech_id_declaration);
lasso_list_add_new_gobject (epr->Metadata->any, created);
}
if (create && ! security_mech_id) {
message(G_LOG_LEVEL_WARNING, "cannot create a LassoIdWsf2DiscoSecurityContext withou a security_mech_id");
}
return created;
}
/**
* lasso_wsa_endpoint_reference_get_token_by_usage:
* @epr: a #LassoWsAddrEndpointReference object
* @security_mech_predicate: (allow-none): a predicate to test for security mechanism
* @security_mech_id: (allow-none): a security mechanism identifier
* @usage: the usage to make of the token
*
* Try to find a token for the given usage and security mechanism, the security can be chosen by
* name or by a predicate.
*
* Return value: a #LassoNode object or a subclass, representing the token.
*/
static LassoNode*
lasso_wsa_endpoint_reference_get_token_by_usage(
const LassoWsAddrEndpointReference *epr,
gboolean (*sec_mech_predicate)(const char *),
const char *security_mech_id, const char* usage)
{
LassoIdWsf2DiscoSecurityContext *security_context;
security_context =
lasso_wsa_endpoint_reference_get_idwsf2_security_context_for_security_mechanism(
epr, sec_mech_predicate, security_mech_id, TRUE);
lasso_foreach_full_begin (LassoIdWsf2SecToken*, token, iter, security_context->Token);
if (LASSO_IS_IDWSF2_SEC_TOKEN (token)) {
if (usage && lasso_strisequal(token->usage,usage)) {
if (LASSO_IS_NODE(token->any)) {
return (LassoNode*)token->any;
} else if (token->ref) {
message(G_LOG_LEVEL_WARNING, "sec:Token ref attribute is not supported");
return NULL;
}
}
}
lasso_foreach_full_end();
return NULL;
}
/**
* lasso_wsa_endpoint_reference_get_security_token:
* @epr: a #LassoWsAddrEndpointReference object
* @sech_mech_predicate:(allow-none): a boolean function to select the security mechanism for which
* we want the security token
* @security_mech_id:(allow-none): an optional specific security mechanism identifier to select the
* security token.
*
* Return the first security token found in the metadata of the @epr object which qualify with
* respect to the predicate or the given security mechanism identifier. It is an error to pass both
* of @sech_mech_predicate and @security_mech_id as NULL.
*
* Return value:(transfer none): a #LassoNode object or NULL if the query cannot be satisfied.
*/
LassoNode*
lasso_wsa_endpoint_reference_get_security_token (const LassoWsAddrEndpointReference *epr,
gboolean (*sech_mech_predicate)(const char *), const char *security_mech_id)
{
return lasso_wsa_endpoint_reference_get_token_by_usage (epr, sech_mech_predicate,
security_mech_id, LASSO_IDWSF2_SEC_TOKEN_USAGE_SECURITY_TOKEN);
}
/**
* lasso_wsa_endpoint_reference_get_target_identity_token:
* @epr: a #LassoWsAddrEndpointReference object
* @sech_mech_predicate:(allow-none): a boolean function to select the security mechanism for which
* we want the security token
* @security_mech_id:(allow-none): an optional specific security mechanism identifier to select the
* security token.
*
* Return the first target identity token found in the metadata of the @epr object which qualify
* with respect to the predicate or the given security mechanism identifier. It is an error to pass
* both of @sech_mech_predicate and @security_mech_id as NULL.
*
* Return value:(transfer none): a #LassoNode object or NULL if the query cannot be satisfied.
*/
LassoNode*
lasso_wsa_endpoint_reference_get_target_identity_token(const LassoWsAddrEndpointReference *epr,
gboolean (*sech_mech_predicate)(const char *), const char *security_mech_id)
{
return lasso_wsa_endpoint_reference_get_token_by_usage (epr, sech_mech_predicate,
security_mech_id, LASSO_IDWSF2_SEC_TOKEN_USAGE_TARGET_IDENTITY);
}
/**
* lasso_wsa_endpoint_reference_new_for_idwsf2_service:
* @address: the URL of the SOAP endpoint where the service is anchored
* @service_type: an URI identifying the ID-WSF 2.0 service type
* @provider_id: an URI identifying the SAML 2.0 service provider hosting the service, this should
* help in finding key material for security mechanisms.
* @abstract: a human description of the service.
*
* Create and populate a new #LassoWsAddrEndpointReference object.
*
* Return value: a newly created #LassoWsAddrEndpointReference.
*/
LassoWsAddrEndpointReference*
lasso_wsa_endpoint_reference_new_for_idwsf2_service(const char *address,
const char *service_type, const char *provider_id, const char *abstract)
{
LassoWsAddrEndpointReference *epr = NULL;
LassoWsAddrMetadata *metadata = NULL;
/* Check parameters */
if (address == NULL || service_type == NULL || provider_id == NULL || abstract == NULL)
return NULL;
/* Build EndpointReference */
epr = lasso_wsa_endpoint_reference_new();
/* Address */
epr->Address = lasso_wsa_attributed_uri_new_with_string(address);
/* Metadatas */
metadata = lasso_wsa_metadata_new();
epr->Metadata = metadata;
/* Abstract */
lasso_list_add_new_gobject(metadata->any,
lasso_idwsf2_disco_abstract_new_with_string(abstract));
/* ProviderID */
lasso_list_add_new_gobject(metadata->any,
lasso_idwsf2_disco_provider_id_new_with_string(provider_id));
/* ServiceType */
lasso_list_add_new_gobject(metadata->any,
lasso_idwsf2_disco_service_type_new_with_string(service_type));
/* Framework */
lasso_list_add_new_gobject(metadata->any,
lasso_idwsf2_sbf_framework_new_full("2.0"));
return epr;
}
/**
* lasso_wsa_endpoint_reference_add_security_token:
* @epr: a #LassoWsAddrEndpointReference object
* @security_token: a security token as a #LassoNode object
* @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
* it with a security token.
*
* Return value: 0 if successfull, an error code otherwise.
*/
int
lasso_wsa_endpoint_reference_add_security_token(LassoWsAddrEndpointReference *epr,
LassoNode *security_token, GList *security_mechanisms)
{
LassoIdWsf2SecToken *sec_token = NULL;
LassoWsAddrMetadata *metadata = NULL;
LassoIdWsf2DiscoSecurityContext *security_context = NULL;
int rc = 0;
lasso_bad_param(WSA_ENDPOINT_REFERENCE, epr);
lasso_bad_param(NODE, security_token);
lasso_extract_node_or_fail(metadata, epr->Metadata, WSA_METADATA, LASSO_PARAM_ERROR_INVALID_VALUE);
sec_token = lasso_idwsf2_sec_token_new();
lasso_assign_gobject(sec_token->any, security_token);
lasso_assign_string(sec_token->usage, LASSO_IDWSF2_SEC_TOKEN_USAGE_SECURITY_TOKEN);
security_context = lasso_idwsf2_disco_security_context_new();
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:
return rc;
}
static GHashTable *_mapping = NULL;
static GHashTable *_get_mapping() {
if (_mapping == NULL) {
_mapping = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
}
return _mapping;
}
/**
* lasso_wsa_endpoint_reference_associate_service_to_type:
* @service_type_uri: a service type to associate
* @g_type: the type of the profile object handling this service type
*
* Associate a profile type to a service type.
*
* Return value: 0 if successful, an error code otherwise.
*/
int
lasso_wsa_endpoint_reference_associate_service_to_type(
const char *service_type_uri, GType g_type)
{
int rc = 0;
lasso_check_non_empty_string(service_type_uri);
if (! g_type_is_a(g_type, LASSO_TYPE_IDWSF2_PROFILE)) {
return LASSO_PARAM_ERROR_INVALID_VALUE;
}
g_hash_table_insert(_get_mapping(),
g_strdup(service_type_uri), (gpointer)g_type);
cleanup:
return rc;
}
/**
* lasso_wsa_endpoint_reference_get_service:
* @epr: a #LassoWsAddrEndpointReference object
*
* Get a profile object able to communicate with the service represented by this EPR.
*
* Return object: a newly created #LassoIdWsf2Profile instance.
*/
LassoIdWsf2Profile *
lasso_wsa_endpoint_reference_get_service(
LassoWsAddrEndpointReference *epr)
{
GType type;
const char *service_type_uri;
if (! LASSO_IS_WSA_ENDPOINT_REFERENCE(epr))
return NULL;
service_type_uri = lasso_wsa_endpoint_reference_get_idwsf2_service_type(epr);
type = (GType)g_hash_table_lookup(_get_mapping(), service_type_uri);
if (type) {
LassoIdWsf2Profile *profile;
profile = (LassoIdWsf2Profile*)g_object_new(type, NULL);
lasso_idwsf2_profile_set_epr(profile, epr);
return profile;
}
return NULL;
}