SAML 2.0&ID-FF 1.2: simplify and complete metadata loading for multi-role support
This commit is contained in:
parent
16d4b4df24
commit
c07cd3898c
|
@ -149,6 +149,13 @@ LassoEncryptionSymKeyType
|
|||
lasso_provider_verify_single_node_signature
|
||||
lasso_provider_get_default_name_id_format
|
||||
lasso_provider_get_sp_name_qualifier
|
||||
lasso_provider_get_idp_supported_attributes
|
||||
lasso_provider_get_valid_until
|
||||
lasso_provider_get_cache_duration
|
||||
lasso_provider_get_metadata_one_for_role
|
||||
lasso_provider_get_metadata_list_for_role
|
||||
lasso_provider_get_metadata_keys_for_role
|
||||
lasso_provider_get_roles
|
||||
<SUBSECTION Standard>
|
||||
LASSO_PROVIDER
|
||||
LASSO_IS_PROVIDER
|
||||
|
|
|
@ -203,7 +203,8 @@ LASSO_EXPORT gint lasso_profile_set_soap_fault_response(LassoProfile *profile, c
|
|||
LASSO_EXPORT void lasso_profile_set_signature_verify_hint(LassoProfile *profile,
|
||||
LassoProfileSignatureVerifyHint signature_verify_hint);
|
||||
LASSO_EXPORT LassoProfileSignatureVerifyHint lasso_profile_get_signature_verify_hint(LassoProfile *profile);
|
||||
LASSO_EXPORT LassoProviderRole lasso_profile_sso_role_with(LassoProfile *profile, const char *remote_provider_id);
|
||||
LASSO_EXPORT LassoProviderRole lasso_profile_sso_role_with(LassoProfile *profile,
|
||||
const char *remote_provider_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -26,7 +26,27 @@
|
|||
* SECTION:provider
|
||||
* @short_description: Service or identity provider
|
||||
*
|
||||
* It holds all the data about a provider.
|
||||
* <para>The #LassoProvider object holds metadata about a provider. Metadata are sorted into descriptors,
|
||||
* each descriptor being assigned a role. We refer you to <CiteTitle>Liberty Metadata Description
|
||||
* and Discovery
|
||||
Specification </CiteTitle> and <CiteTitle>Metadata for the OASIS Security Assertion Markup Language
|
||||
(SAML) V2.0</CiteTitle>.</para>
|
||||
|
||||
<para>Roles are represented by the enumeration #LassoProviderRole, you can access descriptors
|
||||
content using lasso_provider_get_metadata_list_by_role() and lasso_provider_get_metadata_by_role().
|
||||
Descriptors resources are flattened inside a simple hashtable. For example to get the URL(s) for the
|
||||
SAML 2.0 single logout response endpoint using binding HTTP-POST of the SP descriptor of a provider
|
||||
called x, you would call:</para>
|
||||
|
||||
<programlisting>
|
||||
GList *urls = lasso_provider_get_metadata_list_by_role(x, LASSO_PROVIDER_ROLE_SP, "SingleLogoutService HTTP-POST ResponseLocation");
|
||||
</programlisting>
|
||||
|
||||
<para>A provider usually possess a default role stored in the #LassoProvider.role field, which is
|
||||
initialized by the lasso_server_add_provider() method when registering a new remote provider to our
|
||||
current provider. The methods lasso_provider_get_metadata() and lasso_provider_get_metadata_list()
|
||||
use this default role to access descriptors.</para>
|
||||
|
||||
**/
|
||||
|
||||
#include "../xml/private.h"
|
||||
|
@ -62,14 +82,19 @@ static char *protocol_md_nodename[LASSO_MD_PROTOCOL_TYPE_LAST] = {
|
|||
"SingleSignOnProtocolProfile"
|
||||
};
|
||||
static char *protocol_roles[LASSO_PROVIDER_ROLE_LAST] = {
|
||||
NULL, "sp", "idp",
|
||||
NULL, "idp", "sp",
|
||||
"authn-authority", "pdp", "attribute-authority"
|
||||
};
|
||||
char *protocol_methods[LASSO_HTTP_METHOD_LAST] = {
|
||||
"", "", "", "",
|
||||
"", "-http", "-soap"
|
||||
};
|
||||
static gboolean lasso_provider_load_metadata_from_doc(LassoProvider *provider, xmlDoc *doc);
|
||||
|
||||
static gboolean _lasso_provider_load_metadata_from_doc(LassoProvider *provider, xmlDoc *doc);
|
||||
static int _lasso_provider_get_role_index(LassoProviderRole role);
|
||||
void _lasso_provider_add_metadata_value_for_role(LassoProvider *provider,
|
||||
LassoProviderRole role, const char *name, const char *value);
|
||||
typedef int LassoProviderRoleIndex;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* public methods */
|
||||
|
@ -87,28 +112,115 @@ static gboolean lasso_provider_load_metadata_from_doc(LassoProvider *provider, x
|
|||
* string must be freed by the caller.
|
||||
**/
|
||||
gchar*
|
||||
lasso_provider_get_assertion_consumer_service_url(const LassoProvider *provider, const char *service_id)
|
||||
lasso_provider_get_assertion_consumer_service_url(LassoProvider *provider, const char *service_id)
|
||||
{
|
||||
char *name = NULL;
|
||||
char *assertion_consumer_service_url = NULL;
|
||||
|
||||
if (service_id == NULL)
|
||||
service_id = provider->private_data->default_assertion_consumer;
|
||||
name = g_strdup_printf("AssertionConsumerServiceURL %s", service_id);
|
||||
assertion_consumer_service_url = lasso_provider_get_metadata_one_for_role(provider, LASSO_PROVIDER_ROLE_SP, name);
|
||||
g_free(name);
|
||||
|
||||
return assertion_consumer_service_url;
|
||||
}
|
||||
|
||||
static LassoProviderRoleIndex
|
||||
_lasso_provider_get_role_index(LassoProviderRole role) {
|
||||
switch (role) {
|
||||
case LASSO_PROVIDER_ROLE_IDP:
|
||||
return 1;
|
||||
case LASSO_PROVIDER_ROLE_SP:
|
||||
return 2;
|
||||
case LASSO_PROVIDER_ROLE_AUTHN_AUTHORITY:
|
||||
return 3;
|
||||
case LASSO_PROVIDER_ROLE_AUTHZ_AUTHORITY:
|
||||
return 4;
|
||||
case LASSO_PROVIDER_ROLE_ATTRIBUTE_AUTHORITY:
|
||||
return 5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_lasso_provider_add_metadata_value_for_role(LassoProvider *provider, LassoProviderRole role, const char *name, const char *value)
|
||||
{
|
||||
GHashTable *descriptor;
|
||||
GList *l;
|
||||
char *sid = (char*)service_id;
|
||||
char *name;
|
||||
GHashTable *descriptor;
|
||||
char *symbol;
|
||||
LassoProviderRoleIndex role_index;
|
||||
|
||||
g_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL);
|
||||
if (sid == NULL)
|
||||
sid = provider->private_data->default_assertion_consumer;
|
||||
g_return_if_fail(LASSO_IS_PROVIDER(provider) && name && value);
|
||||
role_index = _lasso_provider_get_role_index(role);
|
||||
g_return_if_fail ( role_index);
|
||||
descriptor = provider->private_data->Descriptors; /* default to SP */
|
||||
g_return_if_fail (descriptor);
|
||||
l = (GList*)lasso_provider_get_metadata_list_for_role(provider, role, name);
|
||||
lasso_list_add_string(l, value);
|
||||
symbol = g_strdup_printf("%s %s", protocol_roles[role_index], name);
|
||||
g_hash_table_insert(descriptor, symbol, l);
|
||||
}
|
||||
|
||||
descriptor = provider->private_data->Descriptors;
|
||||
/**
|
||||
* lasso_provider_get_metadata_list_for_role:
|
||||
* @provider: a #LassoProvider
|
||||
* @role: a #LassoProviderRole value
|
||||
* @name: the element name
|
||||
*
|
||||
* Extracts zero to many elements from the @provider descriptor for the given @role.
|
||||
*
|
||||
* Return value:(transfer none)(element-type string): a #GList with the elements. This GList is internally
|
||||
* allocated and points to internally allocated strings. It must
|
||||
* not be freed, modified or stored.
|
||||
**/
|
||||
GList*
|
||||
lasso_provider_get_metadata_list_for_role(const LassoProvider *provider, LassoProviderRole role, const char *name)
|
||||
{
|
||||
GList *l;
|
||||
GHashTable *descriptor;
|
||||
char *symbol;
|
||||
LassoProviderRoleIndex role_index;
|
||||
|
||||
g_return_val_if_fail(LASSO_IS_PROVIDER(provider) && name, NULL);
|
||||
|
||||
role_index = _lasso_provider_get_role_index(role);
|
||||
if (! role_index)
|
||||
return NULL;
|
||||
|
||||
descriptor = provider->private_data->Descriptors; /* default to SP */
|
||||
if (descriptor == NULL)
|
||||
return NULL;
|
||||
|
||||
name = g_strdup_printf("AssertionConsumerServiceURL %s", sid);
|
||||
l = g_hash_table_lookup(descriptor, name);
|
||||
g_free(name);
|
||||
if (l == NULL)
|
||||
return NULL;
|
||||
symbol = g_strdup_printf("%s %s", protocol_roles[role_index], name);
|
||||
l = g_hash_table_lookup(descriptor, symbol);
|
||||
g_free(symbol);
|
||||
|
||||
return g_strdup(l->data);
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_provider_get_metadata_one_for_role:
|
||||
* @provider: a #LassoProvider object
|
||||
* @role: a #LassoProviderRole value
|
||||
* @name: a metadata information name
|
||||
*
|
||||
* Return the given information extracted from the metadata of the given #LassoProvider for the
|
||||
* given @role descriptor.
|
||||
*
|
||||
* Retun value: a newly allocated string or NULL. If non-NULL must be freed by the caller.
|
||||
*/
|
||||
char*
|
||||
lasso_provider_get_metadata_one_for_role(LassoProvider *provider, LassoProviderRole role, const char *name)
|
||||
{
|
||||
const GList *l;
|
||||
|
||||
l = lasso_provider_get_metadata_list_for_role(provider, role, name);
|
||||
|
||||
if (l)
|
||||
return g_strdup(l->data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,24 +234,11 @@ lasso_provider_get_assertion_consumer_service_url(const LassoProvider *provider,
|
|||
* string must be freed by the caller.
|
||||
**/
|
||||
gchar*
|
||||
lasso_provider_get_metadata_one(const LassoProvider *provider, const char *name)
|
||||
lasso_provider_get_metadata_one(LassoProvider *provider, const char *name)
|
||||
{
|
||||
GList *l;
|
||||
GHashTable *descriptor;
|
||||
|
||||
g_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL);
|
||||
|
||||
descriptor = provider->private_data->Descriptors; /* default to SP */
|
||||
if (descriptor == NULL)
|
||||
return NULL;
|
||||
l = g_hash_table_lookup(descriptor, name);
|
||||
if (l)
|
||||
return g_strdup(l->data);
|
||||
|
||||
return NULL;
|
||||
return lasso_provider_get_metadata_one_for_role(provider, provider->role, name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lasso_provider_get_metadata_list:
|
||||
* @provider: a #LassoProvider
|
||||
|
@ -151,18 +250,12 @@ lasso_provider_get_metadata_one(const LassoProvider *provider, const char *name)
|
|||
* allocated and points to internally allocated strings. It must
|
||||
* not be freed, modified or stored.
|
||||
**/
|
||||
const GList*
|
||||
lasso_provider_get_metadata_list(const LassoProvider *provider, const char *name)
|
||||
GList*
|
||||
lasso_provider_get_metadata_list(LassoProvider *provider, const char *name)
|
||||
{
|
||||
GHashTable *descriptor;
|
||||
|
||||
g_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL);
|
||||
descriptor = provider->private_data->Descriptors;
|
||||
|
||||
return g_hash_table_lookup(descriptor, name);
|
||||
return lasso_provider_get_metadata_list_for_role(provider, provider->role, name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lasso_provider_get_first_http_method:
|
||||
* @provider: (transfer none): a #LassoProvider
|
||||
|
@ -176,7 +269,7 @@ lasso_provider_get_metadata_list(const LassoProvider *provider, const char *name
|
|||
**/
|
||||
LassoHttpMethod
|
||||
lasso_provider_get_first_http_method(LassoProvider *provider,
|
||||
const LassoProvider *remote_provider, const LassoMdProtocolType protocol_type)
|
||||
LassoProvider *remote_provider, LassoMdProtocolType protocol_type)
|
||||
{
|
||||
char *protocol_profile_prefix;
|
||||
const GList *local_supported_profiles;
|
||||
|
@ -245,7 +338,7 @@ lasso_provider_get_first_http_method(LassoProvider *provider,
|
|||
* Return value: %TRUE if it is appropriate
|
||||
**/
|
||||
gboolean
|
||||
lasso_provider_accept_http_method(LassoProvider *provider, const LassoProvider *remote_provider,
|
||||
lasso_provider_accept_http_method(LassoProvider *provider, LassoProvider *remote_provider,
|
||||
LassoMdProtocolType protocol_type, LassoHttpMethod http_method,
|
||||
gboolean initiate_profile)
|
||||
{
|
||||
|
@ -302,7 +395,7 @@ lasso_provider_accept_http_method(LassoProvider *provider, const LassoProvider *
|
|||
* Return value: %TRUE if it is supported
|
||||
**/
|
||||
gboolean
|
||||
lasso_provider_has_protocol_profile(const LassoProvider *provider,
|
||||
lasso_provider_has_protocol_profile(LassoProvider *provider,
|
||||
LassoMdProtocolType protocol_type, const char *protocol_profile)
|
||||
{
|
||||
const GList *supported;
|
||||
|
@ -339,7 +432,6 @@ lasso_provider_get_base64_succinct_id(const LassoProvider *provider)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lasso_provider_get_organization
|
||||
* @provider: a #LassoProvider
|
||||
|
@ -375,6 +467,14 @@ static struct XmlSnippet schema_snippets[] = {
|
|||
|
||||
static LassoNodeClass *parent_class = NULL;
|
||||
|
||||
/**
|
||||
* lasso_provider_get_public_key:
|
||||
* @provider: a #LassoProvider object
|
||||
*
|
||||
* Return the public key associated with this provider.
|
||||
*
|
||||
* Return value: an #xmlSecKey object.
|
||||
*/
|
||||
xmlSecKey*
|
||||
lasso_provider_get_public_key(const LassoProvider *provider)
|
||||
{
|
||||
|
@ -403,56 +503,47 @@ lasso_provider_get_encryption_public_key(const LassoProvider *provider)
|
|||
}
|
||||
|
||||
static void
|
||||
load_descriptor(xmlNode *xmlnode, GHashTable *descriptor, LassoProvider *provider)
|
||||
_lasso_provider_load_endpoint_type(LassoProvider *provider, xmlNode *endpoint,
|
||||
LassoProviderRole role)
|
||||
{
|
||||
char *name = (char*)endpoint->name;
|
||||
xmlChar *value = NULL;
|
||||
|
||||
if (strcmp(name, "AssertionConsumerServiceURL") == 0) {
|
||||
char *isDefault = (char*)xmlGetProp(endpoint, (xmlChar*)"isDefault");
|
||||
char *id = (char*)xmlGetProp(endpoint, (xmlChar*)"id");
|
||||
name = g_strdup_printf("%s %s", name, id);
|
||||
if (isDefault) {
|
||||
if (strcmp(isDefault, "true") == 0 || strcmp(isDefault, "1") == 0)
|
||||
lasso_assign_string(provider->private_data->default_assertion_consumer,
|
||||
id);
|
||||
xmlFree(isDefault);
|
||||
}
|
||||
xmlFree(id);
|
||||
} else {
|
||||
name = g_strdup_printf("%s", (char*)name);
|
||||
}
|
||||
value = xmlNodeGetContent(endpoint);
|
||||
_lasso_provider_add_metadata_value_for_role(provider, role, name, (char*)value);
|
||||
lasso_release_string(name);
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
static void
|
||||
_lasso_provider_load_descriptor(LassoProvider *provider, xmlNode *xmlnode, LassoProviderRole role)
|
||||
{
|
||||
xmlNode *t;
|
||||
GList *elements;
|
||||
char *name;
|
||||
xmlChar *value;
|
||||
xmlChar *use;
|
||||
|
||||
t = xmlnode->children;
|
||||
t = xmlSecGetNextElementNode(xmlnode->children);
|
||||
while (t) {
|
||||
if (t->type != XML_ELEMENT_NODE) {
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
if (strcmp((char*)t->name, "KeyDescriptor") == 0) {
|
||||
use = xmlGetProp(t, (xmlChar*)"use");
|
||||
if (use == NULL || strcmp((char*)use, "signing") == 0) {
|
||||
provider->private_data->signing_key_descriptor = xmlCopyNode(t, 1);
|
||||
}
|
||||
if (use == NULL || strcmp((char*)use, "encryption") == 0) {
|
||||
provider->private_data->encryption_key_descriptor =
|
||||
xmlCopyNode(t, 1);
|
||||
}
|
||||
if (use) {
|
||||
xmlFree(use);
|
||||
}
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
if (strcmp((char*)t->name, "AssertionConsumerServiceURL") == 0) {
|
||||
char *isDefault = (char*)xmlGetProp(t, (xmlChar*)"isDefault");
|
||||
char *id = (char*)xmlGetProp(t, (xmlChar*)"id");
|
||||
name = g_strdup_printf("%s %s", t->name, id);
|
||||
if (isDefault) {
|
||||
if (strcmp(isDefault, "true") == 0 || strcmp(isDefault, "1") == 0)
|
||||
lasso_assign_string(provider->private_data->default_assertion_consumer,
|
||||
id);
|
||||
xmlFree(isDefault);
|
||||
}
|
||||
xmlFree(id);
|
||||
if (xmlSecCheckNodeName(t,
|
||||
BAD_CAST "KeyDescriptor",
|
||||
BAD_CAST LASSO_METADATA_HREF)) {
|
||||
_lasso_provider_load_key_descriptor(provider, t);
|
||||
} else {
|
||||
name = g_strdup((char*)t->name);
|
||||
_lasso_provider_load_endpoint_type(provider, t, role);
|
||||
}
|
||||
elements = g_hash_table_lookup(descriptor, name);
|
||||
value = xmlNodeGetContent(t);
|
||||
elements = g_list_append(elements, g_strdup((char*)value));
|
||||
// Do not mix g_free strings with xmlFree strings
|
||||
xmlFree(value);
|
||||
g_hash_table_insert(descriptor, name, elements);
|
||||
t = t->next;
|
||||
t = xmlSecGetNextElementNode(t->next);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,8 +552,20 @@ get_xmlNode(LassoNode *node, gboolean lasso_dump)
|
|||
{
|
||||
xmlNode *xmlnode;
|
||||
LassoProvider *provider = LASSO_PROVIDER(node);
|
||||
char *roles[LASSO_PROVIDER_ROLE_LAST] = { "None", "SP", "IdP", "AuthnAuthority", "PDP", "AttributeAuthority"};
|
||||
char *encryption_mode[] = { "None", "NameId", "Assertion", "Both" };
|
||||
char *roles[LASSO_PROVIDER_ROLE_LAST] = {
|
||||
"None",
|
||||
"SP",
|
||||
"IdP",
|
||||
"AuthnAuthority",
|
||||
"PDP",
|
||||
"AttributeAuthority"
|
||||
};
|
||||
char *encryption_mode[] = {
|
||||
"None",
|
||||
"NameId",
|
||||
"Assertion",
|
||||
"Both"
|
||||
};
|
||||
|
||||
xmlnode = parent_class->get_xmlNode(node, lasso_dump);
|
||||
|
||||
|
@ -479,12 +582,39 @@ get_xmlNode(LassoNode *node, gboolean lasso_dump)
|
|||
return xmlnode;
|
||||
}
|
||||
|
||||
void
|
||||
_lasso_provider_load_key_descriptor(LassoProvider *provider, xmlNode *key_descriptor)
|
||||
{
|
||||
LassoProviderPrivate *private_data;
|
||||
xmlChar *use;
|
||||
|
||||
g_return_if_fail(LASSO_IS_PROVIDER(provider));
|
||||
g_return_if_fail(provider->private_data);
|
||||
|
||||
private_data = provider->private_data;
|
||||
use = xmlGetProp(key_descriptor, (xmlChar*)"use");
|
||||
if (use == NULL || g_strcmp0((char*)use, "signing") == 0) {
|
||||
lasso_assign_xml_node(private_data->signing_key_descriptor, key_descriptor);
|
||||
}
|
||||
if (use == NULL || strcmp((char*)use, "encryption") == 0) {
|
||||
lasso_assign_xml_node(private_data->encryption_key_descriptor, key_descriptor);
|
||||
}
|
||||
lasso_release_xml_string(use);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
||||
{
|
||||
LassoProvider *provider = LASSO_PROVIDER(node);
|
||||
char *roles[LASSO_PROVIDER_ROLE_LAST] = { "None", "SP", "IdP", "AuthnAuthority", "PDP", "AttributeAuthority"};
|
||||
static char * const roles[LASSO_PROVIDER_ROLE_LAST] = {
|
||||
"None",
|
||||
"SP",
|
||||
"IdP",
|
||||
"AuthnAuthority",
|
||||
"PDP",
|
||||
"AttributeAuthority"
|
||||
};
|
||||
xmlChar *s;
|
||||
int i;
|
||||
|
||||
|
@ -497,16 +627,16 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
|||
/* Load provider role */
|
||||
s = xmlGetProp(xmlnode, (xmlChar*)"ProviderRole");
|
||||
provider->role = LASSO_PROVIDER_ROLE_NONE;
|
||||
i = LASSO_PROVIDER_ROLE_NONE;
|
||||
while (i < LASSO_PROVIDER_ROLE_LAST) {
|
||||
if (strcmp((char*)s, roles[i]) == 0) {
|
||||
provider->role = i;
|
||||
break;
|
||||
if (s) {
|
||||
i = LASSO_PROVIDER_ROLE_NONE;
|
||||
while (i < LASSO_PROVIDER_ROLE_LAST) {
|
||||
if (strcmp((char*)s, roles[i]) == 0) {
|
||||
provider->role = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (s != NULL) {
|
||||
xmlFree(s);
|
||||
lasso_release_xml_string(s);
|
||||
}
|
||||
|
||||
/* Load encryption mode */
|
||||
|
@ -540,6 +670,67 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void*
|
||||
_lasso_provider_get_pdata_thing(LassoProvider *provider, ptrdiff_t offset)
|
||||
{
|
||||
LassoProviderPrivate *pdata;
|
||||
|
||||
lasso_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL);
|
||||
pdata = provider->private_data;
|
||||
if (pdata)
|
||||
return G_STRUCT_MEMBER_P(pdata, offset);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_provider_get_idp_supported_attributes:
|
||||
* @provider: a #LassoProvider object
|
||||
*
|
||||
* If the provider supports the IDP SSO role, then return the list of Attribute definition that this
|
||||
* provider declared supporting.
|
||||
*
|
||||
* Return value:(transfer none)(element-type LassoNode): a list of #LassoSaml2Attribute or #LassoSamlAttribute
|
||||
*/
|
||||
GList*
|
||||
lasso_provider_get_idp_supported_attributes(LassoProvider *provider)
|
||||
{
|
||||
return _lasso_provider_get_pdata_thing(provider, G_STRUCT_OFFSET(LassoProviderPrivate,
|
||||
attributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_provider_get_valid_until:
|
||||
* @provider: a #LassoProvider object
|
||||
*
|
||||
* Return the time after which the metadata for this provider will become invalid. This is an
|
||||
* ISO-8601 formatted string.
|
||||
*
|
||||
* Return value:(transfer none): an internally allocated string, you can copy it but not store it.
|
||||
*/
|
||||
char*
|
||||
lasso_provider_get_valid_until(LassoProvider *provider)
|
||||
{
|
||||
return _lasso_provider_get_pdata_thing(provider,
|
||||
G_STRUCT_OFFSET(LassoProviderPrivate, valid_until));
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_provider_get_cache_duration:
|
||||
* @provider: a #LassoProvider object
|
||||
*
|
||||
* Return the time during which the metadata for this provider can be kept.
|
||||
*
|
||||
* Return value:(transfer none): an internally allocated string, you can copy it but not store it.
|
||||
*/
|
||||
char*
|
||||
lasso_provider_get_cache_duration(LassoProvider *provider)
|
||||
{
|
||||
return _lasso_provider_get_pdata_thing(provider,
|
||||
G_STRUCT_OFFSET(LassoProviderPrivate, cache_duration));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* overridden parent class methods */
|
||||
/*****************************************************************************/
|
||||
|
@ -727,7 +918,7 @@ _lasso_provider_load_metadata_from_buffer(LassoProvider *provider, const gchar *
|
|||
if (doc == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
goto_cleanup_if_fail_with_rc (lasso_provider_load_metadata_from_doc(provider, doc), FALSE);
|
||||
goto_cleanup_if_fail_with_rc (_lasso_provider_load_metadata_from_doc(provider, doc), FALSE);
|
||||
lasso_assign_string(provider->metadata_filename, metadata);
|
||||
cleanup:
|
||||
lasso_release_doc(doc);
|
||||
|
@ -774,7 +965,7 @@ lasso_provider_load_metadata(LassoProvider *provider, const gchar *path)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
lasso_provider_load_metadata_from_doc(LassoProvider *provider, xmlDoc *doc)
|
||||
_lasso_provider_load_metadata_from_doc(LassoProvider *provider, xmlDoc *doc)
|
||||
{
|
||||
xmlXPathContext *xpathCtx;
|
||||
xmlXPathObject *xpathObj;
|
||||
|
@ -833,8 +1024,8 @@ lasso_provider_load_metadata_from_doc(LassoProvider *provider, xmlDoc *doc)
|
|||
|
||||
xpathObj = xmlXPathEvalExpression((xmlChar*)xpath_idp, xpathCtx);
|
||||
if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr == 1) {
|
||||
load_descriptor(xpathObj->nodesetval->nodeTab[0],
|
||||
provider->private_data->Descriptors, provider);
|
||||
_lasso_provider_load_descriptor(provider, xpathObj->nodesetval->nodeTab[0],
|
||||
LASSO_PROVIDER_ROLE_IDP);
|
||||
if (provider->private_data->conformance < LASSO_PROTOCOL_LIBERTY_1_2) {
|
||||
/* lookup ProviderID */
|
||||
node = xpathObj->nodesetval->nodeTab[0]->children;
|
||||
|
@ -853,8 +1044,8 @@ lasso_provider_load_metadata_from_doc(LassoProvider *provider, xmlDoc *doc)
|
|||
|
||||
xpathObj = xmlXPathEvalExpression((xmlChar*)xpath_sp, xpathCtx);
|
||||
if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr == 1) {
|
||||
load_descriptor(xpathObj->nodesetval->nodeTab[0],
|
||||
provider->private_data->Descriptors, provider);
|
||||
_lasso_provider_load_descriptor(provider, xpathObj->nodesetval->nodeTab[0],
|
||||
LASSO_PROVIDER_ROLE_SP);
|
||||
if (provider->private_data->conformance < LASSO_PROTOCOL_LIBERTY_1_2) {
|
||||
/* lookup ProviderID */
|
||||
node = xpathObj->nodesetval->nodeTab[0]->children;
|
||||
|
@ -890,8 +1081,9 @@ lasso_provider_load_metadata_from_doc(LassoProvider *provider, xmlDoc *doc)
|
|||
* Help to factorize common code.
|
||||
*/
|
||||
static LassoProvider*
|
||||
lasso_provider_new_helper(LassoProviderRole role, const char *metadata,
|
||||
const char *public_key, const char *ca_cert_chain, gboolean (*loader)(LassoProvider *provider, const gchar *metadata))
|
||||
_lasso_provider_new_helper(LassoProviderRole role, const char *metadata,
|
||||
const char *public_key, const char *ca_cert_chain, gboolean (*loader)(
|
||||
LassoProvider *provider, const gchar *metadata))
|
||||
{
|
||||
LassoProvider *provider;
|
||||
|
||||
|
@ -936,7 +1128,7 @@ LassoProvider*
|
|||
lasso_provider_new(LassoProviderRole role, const char *metadata,
|
||||
const char *public_key, const char *ca_cert_chain)
|
||||
{
|
||||
return lasso_provider_new_helper(role, metadata, public_key, ca_cert_chain,
|
||||
return _lasso_provider_new_helper(role, metadata, public_key, ca_cert_chain,
|
||||
lasso_provider_load_metadata);
|
||||
}
|
||||
|
||||
|
@ -955,7 +1147,7 @@ LassoProvider*
|
|||
lasso_provider_new_from_buffer(LassoProviderRole role, const char *metadata,
|
||||
const char *public_key, const char *ca_cert_chain)
|
||||
{
|
||||
return lasso_provider_new_helper(role, metadata, public_key, ca_cert_chain,
|
||||
return _lasso_provider_new_helper(role, metadata, public_key, ca_cert_chain,
|
||||
lasso_provider_load_metadata_from_buffer);
|
||||
}
|
||||
|
||||
|
@ -1321,7 +1513,7 @@ lasso_provider_verify_query_signature(LassoProvider *provider, const char *messa
|
|||
* Return value:(transfer full)(allow-none): a NameIDFormat URI or NULL, the returned value must be freed by the caller.
|
||||
*/
|
||||
gchar*
|
||||
lasso_provider_get_default_name_id_format(const LassoProvider *provider)
|
||||
lasso_provider_get_default_name_id_format(LassoProvider *provider)
|
||||
{
|
||||
return lasso_provider_get_metadata_one(provider, "NameIDFormat");
|
||||
}
|
||||
|
@ -1384,3 +1576,84 @@ lasso_provider_verify_single_node_signature (LassoProvider *provider, LassoNode
|
|||
}
|
||||
return lasso_verify_signature(xmlnode, NULL, id_attr_name, NULL, xmlseckey, NO_SINGLE_REFERENCE, NULL);
|
||||
}
|
||||
|
||||
struct AddForRoleHelper {
|
||||
GList *l;
|
||||
LassoProviderRole role;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
_add_for_role(gpointer key, G_GNUC_UNUSED gpointer data, struct AddForRoleHelper *helper)
|
||||
{
|
||||
char role_prefix[64];
|
||||
int l;
|
||||
|
||||
l = sprintf(role_prefix, "%s ", protocol_roles[helper->role]);
|
||||
|
||||
if (key && strncmp(key, role_prefix, l) == 0) {
|
||||
lasso_list_add_string(helper->l, ((char*)key) + l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_provider_get_metadata_keys_for_role:
|
||||
* @provider: a #LassoProvider object
|
||||
* @role: a #LassoProviderRole value
|
||||
*
|
||||
* Returns the list of metadata keys existing for the given provider.
|
||||
*
|
||||
* Return value:(element-type utf8)(transfer full): a newly allocated list of strings
|
||||
*/
|
||||
GList*
|
||||
lasso_provider_get_metadata_keys_for_role(LassoProvider *provider, LassoProviderRole role)
|
||||
{
|
||||
struct AddForRoleHelper helper = { NULL, role };
|
||||
|
||||
lasso_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL);
|
||||
lasso_return_val_if_fail(provider->private_data != NULL, NULL);
|
||||
lasso_return_val_if_fail(role > LASSO_PROVIDER_ROLE_NONE && role < LASSO_PROVIDER_ROLE_LAST, NULL);
|
||||
|
||||
g_hash_table_foreach(provider->private_data->Descriptors, (GHFunc)_add_for_role, &helper);
|
||||
|
||||
return helper.l;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_provider_get_roles:
|
||||
* @provider: a #LassoProvider object
|
||||
*
|
||||
* Return the bitmask of the supported roles.
|
||||
*
|
||||
* Return value: a #LassoProviderRole enumeration value.
|
||||
*/
|
||||
LassoProviderRole
|
||||
lasso_provider_get_roles(LassoProvider *provider)
|
||||
{
|
||||
lasso_return_val_if_fail(LASSO_IS_PROVIDER(provider) && provider->private_data, LASSO_PROVIDER_ROLE_NONE);
|
||||
|
||||
return provider->private_data->roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_provider_match_conformance:
|
||||
* @provider: a #LassoProvider object
|
||||
* @another_provider: a #LassoProvider object
|
||||
*
|
||||
* Return whether the two provider support a same protocol.
|
||||
* See also #LassoProtocolConformance.
|
||||
*
|
||||
* Return value: TRUE or FALSE.
|
||||
*/
|
||||
gboolean
|
||||
lasso_provider_match_conformance(LassoProvider *provider, LassoProvider *another_provider)
|
||||
{
|
||||
lasso_return_val_if_fail(LASSO_IS_PROVIDER(provider)
|
||||
&& LASSO_IS_PROVIDER(another_provider),
|
||||
FALSE);
|
||||
|
||||
int conformance1 = lasso_provider_get_protocol_conformance(provider);
|
||||
int conformance2 = lasso_provider_get_protocol_conformance(another_provider);
|
||||
|
||||
return (conformance1 & conformance2) != 0;
|
||||
}
|
||||
|
|
|
@ -118,10 +118,12 @@ typedef enum {
|
|||
* assertion providing authorization about a principal acessing a resource,
|
||||
* @LASSO_PROVIDER_ROLE_ATTRIBUTE_AUTHORITY: an attribute authority, i.e. an endpoint able to return
|
||||
* attributes aboute a principal,
|
||||
* @LASSO_PROVIDER_ROLE_LAST: all value in the enumeration are garanteed to be < to
|
||||
* @LASSO_PROVIDER_ROLE_LAST: all values in the enumeration are guaranteed to be < to
|
||||
* @LASSO_PROVIDER_ROLE_LAST.
|
||||
*
|
||||
* #LassoProviderRole is an enumeration allowing to precise the roles handled by a provider.
|
||||
* #LassoProviderRole is an enumeration allowing to enumerate the roles handled by a provider, it
|
||||
* can be used in a bitmask as each value is a power of 2 (except #LASSO_PROVIDER_ROLE_ANY which is
|
||||
* the full bitmask and LASSO_PROVIDER_ROLE_NONE).
|
||||
**/
|
||||
typedef enum {
|
||||
LASSO_PROVIDER_ROLE_ANY = -1,
|
||||
|
@ -169,6 +171,22 @@ typedef enum {
|
|||
} LassoEncryptionMode;
|
||||
|
||||
|
||||
/**
|
||||
* LassoProvider:
|
||||
* @ProviderID: the identifier URI of this provider
|
||||
* @role: the role prescribed when this #LassoProvider was built
|
||||
* @metadata_filename: file path or content of the metadata description for this provider.
|
||||
* @public_key: file path or content of the public key file for this provider.
|
||||
* @ca_cert_chain: file path or content of the CA cert chain used to validate signature of this
|
||||
* provider (can be used instead of a public key to limit the need for metadata updates).
|
||||
*
|
||||
* <para>Any kind of provider, identity provider, service provider, attribute authority, authorization
|
||||
* authority will be represented by a #LassoProvider object. This object will holds public keys,
|
||||
* certificate chains and metadata informations. The ID-FF 1.2 and SAML 2.0 metadata files are
|
||||
* flattened inside a key-value map that you can access using the functions
|
||||
* lasso_provider_get_metadata_one_for_role(), lasso_provider_get_metadata_list_for_role(),
|
||||
* lasso_provider_get_metadata_keys_for_role().</para>
|
||||
*/
|
||||
struct _LassoProvider {
|
||||
LassoNode parent;
|
||||
|
||||
|
@ -193,21 +211,21 @@ LASSO_EXPORT LassoProvider* lasso_provider_new(LassoProviderRole role, const cha
|
|||
const char *public_key, const char *ca_cert_chain);
|
||||
LASSO_EXPORT LassoProvider* lasso_provider_new_from_buffer(LassoProviderRole role,
|
||||
const char *metadata, const char *public_key, const char *ca_cert_chain);
|
||||
LASSO_EXPORT gchar* lasso_provider_get_assertion_consumer_service_url(const LassoProvider *provider,
|
||||
LASSO_EXPORT gchar* lasso_provider_get_assertion_consumer_service_url(LassoProvider *provider,
|
||||
const char *service_id);
|
||||
LASSO_EXPORT gchar* lasso_provider_get_metadata_one(const LassoProvider *provider, const char *name);
|
||||
LASSO_EXPORT const GList* lasso_provider_get_metadata_list(const LassoProvider *provider, const char *name);
|
||||
LASSO_EXPORT gchar* lasso_provider_get_metadata_one(LassoProvider *provider, const char *name);
|
||||
LASSO_EXPORT GList* lasso_provider_get_metadata_list(LassoProvider *provider, const char *name);
|
||||
|
||||
LASSO_EXPORT LassoProvider* lasso_provider_new_from_dump(const gchar *dump);
|
||||
|
||||
LASSO_EXPORT LassoHttpMethod lasso_provider_get_first_http_method(LassoProvider *provider,
|
||||
const LassoProvider *remote_provider, LassoMdProtocolType protocol_type);
|
||||
LassoProvider *remote_provider, LassoMdProtocolType protocol_type);
|
||||
|
||||
LASSO_EXPORT gboolean lasso_provider_accept_http_method(LassoProvider *provider,
|
||||
const LassoProvider *remote_provider, LassoMdProtocolType protocol_type,
|
||||
LassoProvider *remote_provider, LassoMdProtocolType protocol_type,
|
||||
LassoHttpMethod http_method, gboolean initiate_profile);
|
||||
|
||||
LASSO_EXPORT gboolean lasso_provider_has_protocol_profile(const LassoProvider *provider,
|
||||
LASSO_EXPORT gboolean lasso_provider_has_protocol_profile(LassoProvider *provider,
|
||||
LassoMdProtocolType protocol_type, const char *protocol_profile);
|
||||
|
||||
LASSO_EXPORT gchar* lasso_provider_get_base64_succinct_id(const LassoProvider *provider);
|
||||
|
@ -225,13 +243,32 @@ LASSO_EXPORT LassoEncryptionMode lasso_provider_get_encryption_mode(LassoProvide
|
|||
LASSO_EXPORT void lasso_provider_set_encryption_sym_key_type(LassoProvider *provider,
|
||||
LassoEncryptionSymKeyType encryption_sym_key_type);
|
||||
|
||||
LASSO_EXPORT gchar* lasso_provider_get_default_name_id_format(const LassoProvider *provider);
|
||||
LASSO_EXPORT gchar* lasso_provider_get_default_name_id_format(LassoProvider *provider);
|
||||
|
||||
LASSO_EXPORT const char* lasso_provider_get_sp_name_qualifier(LassoProvider *provider);
|
||||
|
||||
LASSO_EXPORT int lasso_provider_verify_single_node_signature (LassoProvider *provider,
|
||||
LassoNode *node, const char *id_attr_name);
|
||||
|
||||
LASSO_EXPORT GList* lasso_provider_get_idp_supported_attributes(LassoProvider *provider);
|
||||
|
||||
LASSO_EXPORT char* lasso_provider_get_valid_until(LassoProvider *provider);
|
||||
|
||||
LASSO_EXPORT char* lasso_provider_get_cache_duration(LassoProvider *provider);
|
||||
|
||||
LASSO_EXPORT char* lasso_provider_get_metadata_one_for_role(LassoProvider *provider,
|
||||
LassoProviderRole role, const char *name);
|
||||
|
||||
LASSO_EXPORT GList* lasso_provider_get_metadata_list_for_role(const LassoProvider *provider,
|
||||
LassoProviderRole role, const char *name);
|
||||
|
||||
LASSO_EXPORT GList *lasso_provider_get_metadata_keys_for_role(LassoProvider *provider,
|
||||
LassoProviderRole role);
|
||||
|
||||
LASSO_EXPORT LassoProviderRole lasso_provider_get_roles(LassoProvider *provider);
|
||||
|
||||
LASSO_EXPORT gboolean lasso_provider_match_conformance(LassoProvider *provider, LassoProvider *another_provider);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -46,6 +46,7 @@ struct _LassoProviderPrivate
|
|||
{
|
||||
gboolean dispose_has_run;
|
||||
|
||||
LassoProviderRole roles;
|
||||
LassoProtocolConformance conformance;
|
||||
GHashTable *Descriptors;
|
||||
GList *attributes; /* of LassoSaml2Attribute */
|
||||
|
@ -62,6 +63,8 @@ struct _LassoProviderPrivate
|
|||
xmlSecKey *encryption_public_key;
|
||||
LassoEncryptionMode encryption_mode;
|
||||
LassoEncryptionSymKeyType encryption_sym_key_type;
|
||||
char *valid_until;
|
||||
char *cache_duration;
|
||||
};
|
||||
|
||||
|
||||
|
@ -76,6 +79,9 @@ xmlSecKey* lasso_provider_get_encryption_public_key(const LassoProvider *provide
|
|||
LassoEncryptionSymKeyType lasso_provider_get_encryption_sym_key_type(const LassoProvider* provider);
|
||||
int lasso_provider_verify_saml_signature(LassoProvider *provider, xmlNode *signed_node, xmlDoc *doc);
|
||||
int lasso_provider_verify_query_signature(LassoProvider *provider, const char *message);
|
||||
void _lasso_provider_load_key_descriptor(LassoProvider *provider, xmlNode *key_descriptor);
|
||||
void _lasso_provider_add_metadata_value_for_role(LassoProvider *provider,
|
||||
LassoProviderRole role, const char *name, const char *value);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
#include "../id-ff/session.h"
|
||||
#include "../xml/private.h"
|
||||
#include "assertion_query.h"
|
||||
#include "providerprivate.h"
|
||||
#include "profileprivate.h"
|
||||
#include "./assertion_query.h"
|
||||
#include "./providerprivate.h"
|
||||
#include "./profileprivate.h"
|
||||
#include "../id-ff/providerprivate.h"
|
||||
#include "../id-ff/profileprivate.h"
|
||||
#include "../id-ff/identityprivate.h"
|
||||
|
@ -47,6 +47,23 @@ struct _LassoAssertionQueryPrivate
|
|||
LassoAssertionQueryRequestType query_request_type;
|
||||
};
|
||||
|
||||
LassoMdProtocolType
|
||||
_lasso_assertion_query_type_to_protocol_type(LassoAssertionQueryRequestType query_request_type) {
|
||||
|
||||
LassoMdProtocolType types[4] = {
|
||||
LASSO_MD_PROTOCOL_TYPE_ASSERTION_ID_REQUEST,
|
||||
LASSO_MD_PROTOCOL_TYPE_AUTHN_QUERY,
|
||||
LASSO_MD_PROTOCOL_TYPE_ATTRIBUTE,
|
||||
LASSO_MD_PROTOCOL_TYPE_AUTHZ, };
|
||||
|
||||
if (query_request_type < LASSO_ASSERTION_QUERY_REQUEST_TYPE_ASSERTION_ID &&
|
||||
query_request_type > LASSO_ASSERTION_QUERY_REQUEST_TYPE_AUTHZ_DECISION) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return types[query_request_type - LASSO_ASSERTION_QUERY_REQUEST_TYPE_ASSERTION_ID];
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* public methods */
|
||||
|
@ -74,24 +91,16 @@ lasso_assertion_query_init_request(LassoAssertionQuery *assertion_query,
|
|||
LassoAssertionQueryRequestType query_request_type)
|
||||
{
|
||||
LassoProfile *profile;
|
||||
LassoProvider *remote_provider;
|
||||
LassoFederation *federation;
|
||||
LassoSamlp2RequestAbstract *request;
|
||||
gint ret = 0;
|
||||
LassoNode *request;
|
||||
gint rc = 0;
|
||||
|
||||
g_return_val_if_fail(http_method == LASSO_HTTP_METHOD_ANY ||
|
||||
http_method == LASSO_HTTP_METHOD_SOAP,
|
||||
LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
g_return_val_if_fail(LASSO_IS_ASSERTION_QUERY(assertion_query),
|
||||
LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
|
||||
profile = LASSO_PROFILE(assertion_query);
|
||||
|
||||
/* verify the identity is set */
|
||||
if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
|
||||
return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* set the remote provider id */
|
||||
profile->remote_providerID = NULL;
|
||||
if (remote_provider_id) {
|
||||
|
@ -106,7 +115,7 @@ lasso_assertion_query_init_request(LassoAssertionQuery *assertion_query,
|
|||
role = LASSO_PROVIDER_ROLE_ATTRIBUTE_AUTHORITY;
|
||||
break;
|
||||
case LASSO_ASSERTION_QUERY_REQUEST_TYPE_AUTHZ_DECISION:
|
||||
role = LASSO_PROVIDER_ROLE_PDP;
|
||||
role = LASSO_PROVIDER_ROLE_AUTHZ_AUTHORITY;
|
||||
break;
|
||||
/* other request types should not happen or should not go there */
|
||||
default:
|
||||
|
@ -119,81 +128,40 @@ lasso_assertion_query_init_request(LassoAssertionQuery *assertion_query,
|
|||
g_return_val_if_fail(profile->remote_providerID != NULL,
|
||||
LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
|
||||
remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
|
||||
if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
|
||||
return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
assertion_query->private_data->query_request_type = query_request_type;
|
||||
switch (query_request_type) {
|
||||
case LASSO_ASSERTION_QUERY_REQUEST_TYPE_ASSERTION_ID:
|
||||
profile->request = lasso_samlp2_assertion_id_request_new();
|
||||
request = lasso_samlp2_assertion_id_request_new();
|
||||
break;
|
||||
case LASSO_ASSERTION_QUERY_REQUEST_TYPE_AUTHN:
|
||||
profile->request = lasso_samlp2_authn_query_new();
|
||||
request = lasso_samlp2_authn_query_new();
|
||||
break;
|
||||
case LASSO_ASSERTION_QUERY_REQUEST_TYPE_ATTRIBUTE:
|
||||
profile->request = lasso_samlp2_attribute_query_new();
|
||||
request = lasso_samlp2_attribute_query_new();
|
||||
break;
|
||||
case LASSO_ASSERTION_QUERY_REQUEST_TYPE_AUTHZ_DECISION:
|
||||
profile->request = lasso_samlp2_authz_decision_query_new();
|
||||
request = lasso_samlp2_authz_decision_query_new();
|
||||
break;
|
||||
default:
|
||||
return critical_error(LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
}
|
||||
|
||||
if (query_request_type != LASSO_ASSERTION_QUERY_REQUEST_TYPE_ASSERTION_ID) {
|
||||
LassoSaml2NameID *nameID = NULL;
|
||||
/* fill <Subject> */
|
||||
LassoSamlp2SubjectQueryAbstract *subject_query;
|
||||
|
||||
/* Get federation */
|
||||
if (profile->session) {
|
||||
GList *assertions;
|
||||
LassoSaml2Assertion *assertion = NULL;
|
||||
|
||||
assertions = lasso_session_get_assertions(profile->session,
|
||||
(gchar*)profile->remote_providerID);
|
||||
/* multiple assertions, take the first */
|
||||
if (assertions && LASSO_IS_SAML2_ASSERTION(assertions->data)) {
|
||||
assertion = (LassoSaml2Assertion*)assertions->data;
|
||||
}
|
||||
if (assertion && assertion->Subject) {
|
||||
nameID = assertion->Subject->NameID;
|
||||
}
|
||||
}
|
||||
if (nameID == NULL) {
|
||||
federation = g_hash_table_lookup(profile->identity->federations,
|
||||
profile->remote_providerID);
|
||||
if (LASSO_IS_FEDERATION(federation) == FALSE) {
|
||||
return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
|
||||
} /* XXX: should support looking up transient id */
|
||||
nameID = LASSO_SAML2_NAME_ID(lasso_profile_get_nameIdentifier(profile));
|
||||
}
|
||||
subject_query = LASSO_SAMLP2_SUBJECT_QUERY_ABSTRACT(profile->request);
|
||||
subject_query->Subject = LASSO_SAML2_SUBJECT(lasso_saml2_subject_new());
|
||||
subject_query->Subject->NameID = g_object_ref(nameID);
|
||||
}
|
||||
/* Setup usual request attributes */
|
||||
request = LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request);
|
||||
request->ID = lasso_build_unique_id(32);
|
||||
request->Version = g_strdup("2.0");
|
||||
request->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string(
|
||||
LASSO_PROVIDER(profile->server)->ProviderID));
|
||||
request->IssueInstant = lasso_get_current_time();
|
||||
if (LASSO_IS_SAMLP2_SUBJECT_QUERY_ABSTRACT(request)) {
|
||||
LassoSamlp2SubjectQueryAbstract *sqa;
|
||||
|
||||
request->sign_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
|
||||
if (profile->server->certificate) {
|
||||
request->sign_type = LASSO_SIGNATURE_TYPE_WITHX509;
|
||||
} else {
|
||||
request->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE;
|
||||
sqa = (LassoSamlp2SubjectQueryAbstract*)request;
|
||||
sqa->Subject = (LassoSaml2Subject*)lasso_saml2_subject_new();
|
||||
}
|
||||
request->private_key_file = g_strdup(profile->server->private_key);
|
||||
request->certificate_file = g_strdup(profile->server->certificate);
|
||||
|
||||
profile->http_request_method = http_method;
|
||||
|
||||
return ret;
|
||||
lasso_check_good_rc(lasso_saml20_profile_init_request(profile,
|
||||
profile->remote_providerID,
|
||||
TRUE,
|
||||
(LassoSamlp2RequestAbstract*)request,
|
||||
http_method,
|
||||
_lasso_assertion_query_type_to_protocol_type(query_request_type)));
|
||||
cleanup:
|
||||
lasso_release_gobject(request);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -210,6 +178,7 @@ lasso_assertion_query_build_request_msg(LassoAssertionQuery *assertion_query)
|
|||
{
|
||||
LassoProfile *profile;
|
||||
LassoProvider *remote_provider;
|
||||
gint rc = 0;
|
||||
|
||||
g_return_val_if_fail(LASSO_IS_ASSERTION_QUERY(assertion_query),
|
||||
LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
|
@ -221,8 +190,31 @@ lasso_assertion_query_build_request_msg(LassoAssertionQuery *assertion_query)
|
|||
if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
|
||||
return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* fill and encrypt <Subject> if necessary */
|
||||
if (LASSO_IS_SAMLP2_SUBJECT_QUERY_ABSTRACT(profile->request)) do {
|
||||
LassoSaml2NameID *nameID = NULL;
|
||||
LassoSamlp2SubjectQueryAbstract *subject_query;
|
||||
|
||||
subject_query = (LassoSamlp2SubjectQueryAbstract*)profile->request;
|
||||
if (subject_query->Subject &&
|
||||
(subject_query->Subject->NameID ||
|
||||
subject_query->Subject->EncryptedID)) {
|
||||
|
||||
nameID = (LassoSaml2NameID*)lasso_profile_get_nameIdentifier(profile);
|
||||
if (! LASSO_IS_SAML2_NAME_ID(nameID))
|
||||
return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
|
||||
subject_query = LASSO_SAMLP2_SUBJECT_QUERY_ABSTRACT(profile->request);
|
||||
subject_query->Subject->NameID = g_object_ref(nameID);
|
||||
}
|
||||
if (! subject_query->Subject)
|
||||
return LASSO_PROFILE_ERROR_MISSING_SUBJECT;
|
||||
lasso_check_good_rc(lasso_saml20_profile_setup_subject(profile, subject_query->Subject));
|
||||
} while(FALSE);
|
||||
|
||||
if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) {
|
||||
LassoAssertionQueryRequestType type;
|
||||
const char *url;
|
||||
/* XXX: support only SOAP */
|
||||
static const gchar *servicepoints[LASSO_ASSERTION_QUERY_REQUEST_TYPE_LAST] = {
|
||||
"AssertionIDRequestService SOAP",
|
||||
|
@ -230,22 +222,31 @@ lasso_assertion_query_build_request_msg(LassoAssertionQuery *assertion_query)
|
|||
"AuthzService SOAP",
|
||||
"AttributeService SOAP"
|
||||
};
|
||||
static const LassoProviderRole roles[LASSO_ASSERTION_QUERY_REQUEST_TYPE_LAST] = {
|
||||
LASSO_PROVIDER_ROLE_ANY,
|
||||
LASSO_PROVIDER_ROLE_AUTHN_AUTHORITY,
|
||||
LASSO_PROVIDER_ROLE_AUTHZ_AUTHORITY,
|
||||
LASSO_PROVIDER_ROLE_ATTRIBUTE_AUTHORITY
|
||||
};
|
||||
|
||||
type = assertion_query->private_data->query_request_type;
|
||||
if (type <= LASSO_ASSERTION_QUERY_REQUEST_TYPE_ASSERTION_ID ||
|
||||
if (type == LASSO_ASSERTION_QUERY_REQUEST_TYPE_ASSERTION_ID) {
|
||||
return LASSO_ERROR_UNDEFINED;
|
||||
}
|
||||
if (type < LASSO_ASSERTION_QUERY_REQUEST_TYPE_ASSERTION_ID ||
|
||||
type >= LASSO_ASSERTION_QUERY_REQUEST_TYPE_AUTHZ_DECISION) {
|
||||
return LASSO_PARAM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
profile->msg_url = lasso_provider_get_metadata_one(remote_provider,
|
||||
servicepoints[type]);
|
||||
lasso_saml20_profile_setup_request_signing(profile);
|
||||
profile->msg_body = lasso_node_export_to_soap(profile->request);
|
||||
return 0;
|
||||
url = lasso_provider_get_metadata_one_for_role(remote_provider, roles[type], servicepoints[type]);
|
||||
|
||||
return lasso_saml20_profile_build_request_msg(&assertion_query->parent,
|
||||
NULL,
|
||||
LASSO_HTTP_METHOD_SOAP, url);
|
||||
}
|
||||
|
||||
return critical_error(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD);
|
||||
cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lasso_assertion_query_process_request_msg:
|
||||
* @assertion_query: a #LassoAssertionQuery
|
||||
|
@ -302,63 +303,22 @@ lasso_assertion_query_validate_request(LassoAssertionQuery *assertion_query)
|
|||
{
|
||||
LassoProfile *profile;
|
||||
LassoProvider *remote_provider;
|
||||
LassoFederation *federation;
|
||||
LassoSamlp2StatusResponse *response;
|
||||
int rc;
|
||||
|
||||
g_return_val_if_fail(LASSO_IS_ASSERTION_QUERY(assertion_query),
|
||||
LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
profile = LASSO_PROFILE(assertion_query);
|
||||
|
||||
if (profile->remote_providerID) {
|
||||
g_free(profile->remote_providerID);
|
||||
}
|
||||
response = (LassoSamlp2StatusResponse*) lasso_samlp2_response_new();
|
||||
lasso_check_good_rc(lasso_saml20_profile_validate_request(profile,
|
||||
FALSE,
|
||||
response,
|
||||
&remote_provider));
|
||||
|
||||
profile->remote_providerID = g_strdup(
|
||||
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content);
|
||||
|
||||
/* get the provider */
|
||||
remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
|
||||
if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
|
||||
return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
federation = g_hash_table_lookup(profile->identity->federations,
|
||||
profile->remote_providerID);
|
||||
if (LASSO_IS_FEDERATION(federation) == FALSE) {
|
||||
return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (profile->response) {
|
||||
lasso_node_destroy(profile->response);
|
||||
}
|
||||
|
||||
profile->response = lasso_samlp2_response_new();
|
||||
response = LASSO_SAMLP2_STATUS_RESPONSE(profile->response);
|
||||
response->ID = lasso_build_unique_id(32);
|
||||
response->Version = g_strdup("2.0");
|
||||
response->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string(
|
||||
LASSO_PROVIDER(profile->server)->ProviderID));
|
||||
response->IssueInstant = lasso_get_current_time();
|
||||
response->InResponseTo = g_strdup(LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID);
|
||||
lasso_saml20_profile_set_response_status(profile, LASSO_SAML2_STATUS_CODE_SUCCESS, NULL);
|
||||
|
||||
response->sign_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
|
||||
if (profile->server->certificate) {
|
||||
response->sign_type = LASSO_SIGNATURE_TYPE_WITHX509;
|
||||
} else {
|
||||
response->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE;
|
||||
}
|
||||
response->private_key_file = g_strdup(profile->server->private_key);
|
||||
response->certificate_file = g_strdup(profile->server->certificate);
|
||||
|
||||
/* verify signature status */
|
||||
if (profile->signature_status != 0) {
|
||||
lasso_saml20_profile_set_response_status_requester(profile,
|
||||
LASSO_LIB_STATUS_CODE_INVALID_SIGNATURE);
|
||||
return profile->signature_status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
lasso_release_gobject(response);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -375,6 +335,7 @@ lasso_assertion_query_build_response_msg(LassoAssertionQuery *assertion_query)
|
|||
{
|
||||
LassoProfile *profile;
|
||||
LassoSamlp2StatusResponse *response;
|
||||
int rc;
|
||||
|
||||
g_return_val_if_fail(LASSO_IS_ASSERTION_QUERY(assertion_query),
|
||||
LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
|
@ -383,44 +344,23 @@ lasso_assertion_query_build_response_msg(LassoAssertionQuery *assertion_query)
|
|||
|
||||
if (profile->response == NULL) {
|
||||
/* no response set here means request denied */
|
||||
profile->response = lasso_samlp2_response_new();
|
||||
response = LASSO_SAMLP2_STATUS_RESPONSE(profile->response);
|
||||
response->ID = lasso_build_unique_id(32);
|
||||
response->Version = g_strdup("2.0");
|
||||
response->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string(
|
||||
LASSO_PROVIDER(profile->server)->ProviderID));
|
||||
response->IssueInstant = lasso_get_current_time();
|
||||
response->InResponseTo = g_strdup(
|
||||
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID);
|
||||
lasso_saml20_profile_set_response_status_responder(profile,
|
||||
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
|
||||
response = (LassoSamlp2StatusResponse*) lasso_samlp2_response_new();
|
||||
|
||||
response->sign_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
|
||||
if (profile->server->certificate) {
|
||||
response->sign_type = LASSO_SIGNATURE_TYPE_WITHX509;
|
||||
} else {
|
||||
response->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE;
|
||||
}
|
||||
response->private_key_file = g_strdup(profile->server->private_key);
|
||||
response->certificate_file = g_strdup(profile->server->certificate);
|
||||
lasso_check_good_rc(lasso_saml20_profile_init_response(
|
||||
profile,
|
||||
response,
|
||||
LASSO_SAML2_STATUS_CODE_RESPONDER,
|
||||
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (profile->remote_providerID == NULL || profile->response == NULL) {
|
||||
/* no remote provider id set or no response set, this means
|
||||
* this function got called before validate_request, probably
|
||||
* because there were no identity or federation */
|
||||
return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* build logout response message */
|
||||
if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) {
|
||||
profile->msg_url = NULL;
|
||||
profile->msg_body = lasso_node_export_to_soap(profile->response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return LASSO_PROFILE_ERROR_MISSING_REQUEST;
|
||||
rc = lasso_saml20_profile_build_response_msg(profile,
|
||||
NULL,
|
||||
profile->http_request_method,
|
||||
NULL);
|
||||
cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -446,9 +386,10 @@ lasso_assertion_query_process_response_msg(
|
|||
profile = &assertion_query->parent;
|
||||
response = (LassoSamlp2StatusResponse*)lasso_samlp2_response_new();
|
||||
|
||||
rc = lasso_saml20_profile_process_any_response(profile, response, NULL, response_msg);
|
||||
lasso_check_good_rc(lasso_saml20_profile_process_any_response(profile,
|
||||
response, NULL, response_msg));
|
||||
|
||||
/* cleanup: */
|
||||
cleanup:
|
||||
lasso_release_gobject(response);
|
||||
return rc;
|
||||
}
|
||||
|
@ -486,12 +427,6 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
|||
/* overridden parent class methods */
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
dispose(GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS(parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize(GObject *object)
|
||||
{
|
||||
|
@ -501,8 +436,6 @@ finalize(GObject *object)
|
|||
G_OBJECT_CLASS(parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* instance and class init functions */
|
||||
/*****************************************************************************/
|
||||
|
@ -525,12 +458,9 @@ class_init(LassoAssertionQueryClass *klass)
|
|||
lasso_node_class_set_nodename(nclass, "AssertionQuery");
|
||||
lasso_node_class_add_snippets(nclass, schema_snippets);
|
||||
|
||||
G_OBJECT_CLASS(klass)->dispose = dispose;
|
||||
G_OBJECT_CLASS(klass)->finalize = finalize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GType
|
||||
lasso_assertion_query_get_type()
|
||||
{
|
||||
|
@ -571,8 +501,7 @@ lasso_assertion_query_new(LassoServer *server)
|
|||
g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
|
||||
|
||||
assertion_query = g_object_new(LASSO_TYPE_ASSERTION_QUERY, NULL);
|
||||
LASSO_PROFILE(assertion_query)->server = g_object_ref(server);
|
||||
|
||||
LASSO_PROFILE(assertion_query)->server = lasso_ref(server);
|
||||
return assertion_query;
|
||||
}
|
||||
|
||||
|
@ -585,5 +514,5 @@ lasso_assertion_query_new(LassoServer *server)
|
|||
void
|
||||
lasso_assertion_query_destroy(LassoAssertionQuery *assertion_query)
|
||||
{
|
||||
lasso_node_destroy(LASSO_NODE(assertion_query));
|
||||
lasso_release_gobject(assertion_query);
|
||||
}
|
||||
|
|
|
@ -340,6 +340,8 @@ lasso_saml20_profile_process_artifact_resolve(LassoProfile *profile, const char
|
|||
LassoProvider *remote_provider;
|
||||
int rc;
|
||||
|
||||
/* FIXME: parse only one time the message, reuse the parsed document for signature
|
||||
* validation */
|
||||
lasso_assign_new_gobject(profile->request, lasso_node_new_from_soap(msg));
|
||||
if (profile->request == NULL) {
|
||||
return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG);
|
||||
|
@ -644,7 +646,6 @@ cleanup:
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lasso_saml20_profile_process_soap_request(LassoProfile *profile,
|
||||
const char *request_msg)
|
||||
|
@ -1165,7 +1166,7 @@ lasso_saml20_profile_build_response_msg(LassoProfile *profile, char *service,
|
|||
}
|
||||
|
||||
/* if not explicitely given, automatically determine an URI from the metadatas */
|
||||
if (url == NULL && service) {
|
||||
if (url == NULL && service && method != LASSO_HTTP_METHOD_SOAP) {
|
||||
made_url = url = get_response_url(provider, service, http_method_to_binding(method));
|
||||
}
|
||||
|
||||
|
@ -1484,6 +1485,29 @@ lasso_profile_saml20_setup_message_signature(LassoProfile *profile, LassoNode *r
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_saml20_profile_setup_subject:
|
||||
* @profile: a #LassoProfile object
|
||||
* @subject: a #LassoSaml2Subject object
|
||||
*
|
||||
* Encrypt subject if necessary.
|
||||
*/
|
||||
int
|
||||
lasso_saml20_profile_setup_subject(LassoProfile *profile,
|
||||
LassoSaml2Subject *subject)
|
||||
{
|
||||
LassoProvider *remote_provider;
|
||||
|
||||
remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
|
||||
g_return_val_if_fail (LASSO_IS_PROVIDER(remote_provider), LASSO_ERROR_CAST_FAILED);
|
||||
if (! (lasso_provider_get_encryption_mode(remote_provider) & LASSO_ENCRYPTION_MODE_NAMEID)) {
|
||||
return 0;
|
||||
}
|
||||
return lasso_saml20_profile_setup_encrypted_node(remote_provider,
|
||||
(LassoNode**)subject->NameID,
|
||||
(LassoNode**)subject->EncryptedID);
|
||||
}
|
||||
|
||||
gint
|
||||
lasso_saml20_profile_setup_encrypted_node(LassoProvider *provider,
|
||||
LassoNode **node_to_encrypt, LassoNode **node_destination)
|
||||
|
|
|
@ -34,6 +34,7 @@ extern "C" {
|
|||
#include "../xml/saml-2.0/saml2_encrypted_element.h"
|
||||
#include "../xml/saml-2.0/samlp2_status_response.h"
|
||||
#include "../xml/saml-2.0/samlp2_request_abstract.h"
|
||||
#include "../xml/saml-2.0/saml2_subject.h"
|
||||
#include "../id-ff/provider.h"
|
||||
|
||||
int lasso_saml20_profile_init_request(LassoProfile *profile, const char *remote_provider_id,
|
||||
|
@ -77,6 +78,7 @@ gint lasso_profile_saml20_setup_message_signature(LassoProfile *profile,
|
|||
LassoNode *request_or_response);
|
||||
gint lasso_saml20_profile_setup_encrypted_node(LassoProvider *provider,
|
||||
LassoNode **node_to_encrypt, LassoNode **node_destination);
|
||||
int lasso_saml20_profile_setup_subject(LassoProfile *profile, LassoSaml2Subject *subject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -22,14 +22,18 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define _POSIX_SOURCE
|
||||
|
||||
#include "../xml/private.h"
|
||||
#include <xmlsec/base64.h>
|
||||
#include <xmlsec/xmltree.h>
|
||||
|
||||
#include "providerprivate.h"
|
||||
#include "../id-ff/providerprivate.h"
|
||||
#include "../utils.h"
|
||||
#include "./provider.h"
|
||||
#include "../xml/saml-2.0/saml2_attribute.h"
|
||||
#include "../xml/saml-2.0/saml2_xsd.h"
|
||||
|
||||
const char *profile_names[LASSO_MD_PROTOCOL_TYPE_LAST] = {
|
||||
"", /* No fedterm in SAML 2.0 */
|
||||
|
@ -50,122 +54,179 @@ const char *profile_names[LASSO_MD_PROTOCOL_TYPE_LAST] = {
|
|||
|
||||
static void add_assertion_consumer_url_to_list(gchar *key, G_GNUC_UNUSED gpointer value, GList **list);
|
||||
|
||||
static void
|
||||
load_descriptor(xmlNode *xmlnode, GHashTable *descriptor, LassoProvider *provider)
|
||||
static const char*
|
||||
binding_uri_to_identifier(const char *uri)
|
||||
{
|
||||
char *descriptor_attrs[] = {"AuthnRequestsSigned", "WantAuthnRequestsSigned", NULL};
|
||||
if (strcmp(uri, LASSO_SAML2_METADATA_BINDING_SOAP) == 0) {
|
||||
return "SOAP";
|
||||
} else if (strcmp(uri, LASSO_SAML2_METADATA_BINDING_REDIRECT) == 0) {
|
||||
return "HTTP-Redirect";
|
||||
} else if (strcmp(uri, LASSO_SAML2_METADATA_BINDING_POST) == 0) {
|
||||
return "HTTP-POST";
|
||||
} else if (strcmp(uri, LASSO_SAML2_METADATA_BINDING_ARTIFACT) == 0) {
|
||||
return "HTTP-Artifact";
|
||||
} else if (strcmp(uri, LASSO_SAML2_METADATA_BINDING_PAOS) == 0) {
|
||||
return "PAOS";
|
||||
} else if (strcmp(uri, LASSO_SAML2_METADATA_BINDING_URI) == 0) {
|
||||
return "URI";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
checkSaml2MdNode(xmlNode *t, char *name)
|
||||
{
|
||||
return xmlSecCheckNodeName(t,
|
||||
BAD_CAST name,
|
||||
BAD_CAST LASSO_SAML2_METADATA_HREF);
|
||||
}
|
||||
|
||||
static xmlChar*
|
||||
getSaml2MdProp(xmlNode *t, char *name) {
|
||||
return xmlGetProp(t, BAD_CAST name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
hasSaml2MdProp(xmlNode *t, char *name) {
|
||||
return xmlHasProp(t, BAD_CAST name) != NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xsdIsTrue(xmlChar *value)
|
||||
{
|
||||
if (value && strcmp((char*)value, "true") == 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
load_endpoint_type(xmlNode *xmlnode, LassoProvider *provider, LassoProviderRole role)
|
||||
{
|
||||
xmlChar *binding = xmlGetProp(xmlnode, BAD_CAST "Binding");
|
||||
char *name = NULL;
|
||||
char *response_name = NULL;
|
||||
LassoProviderPrivate *private_data = provider->private_data;
|
||||
const char *binding_s = NULL;
|
||||
xmlChar *value = NULL;
|
||||
xmlChar *response_value = NULL;
|
||||
|
||||
|
||||
binding_s = binding_uri_to_identifier((char*)binding);
|
||||
if (! binding_s) {
|
||||
message(G_LOG_LEVEL_CRITICAL, "XXX: unknown binding: %s", binding);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* get endpoint location */
|
||||
value = getSaml2MdProp(xmlnode, LASSO_SAML2_METADATA_ATTRIBUTE_LOCATION);
|
||||
|
||||
if (value == NULL) {
|
||||
message(G_LOG_LEVEL_CRITICAL, "XXX: missing location for element %s", xmlnode->name);
|
||||
goto cleanup;
|
||||
}
|
||||
/* special case of AssertionConsumerService */
|
||||
if (checkSaml2MdNode(xmlnode, LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE)) {
|
||||
xmlChar *index = getSaml2MdProp(xmlnode, LASSO_SAML2_METADATA_ATTRIBUTE_INDEX);
|
||||
xmlChar *is_default = getSaml2MdProp(xmlnode, LASSO_SAML2_METADATA_ATTRIBUTE_ISDEFAULT);
|
||||
|
||||
if (xsdIsTrue(is_default)) {
|
||||
lasso_assign_string(private_data->default_assertion_consumer, (char*)index);
|
||||
}
|
||||
name = g_strdup_printf(LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE
|
||||
" %s %s",
|
||||
binding_s,
|
||||
index);
|
||||
lasso_release_xml_string(index);
|
||||
lasso_release_xml_string(is_default);
|
||||
} else {
|
||||
name = g_strdup_printf("%s %s", xmlnode->name, binding_s);
|
||||
}
|
||||
lasso_release_xml_string(binding);
|
||||
|
||||
/* Response endpoint ? */
|
||||
response_value = getSaml2MdProp(xmlnode, LASSO_SAML2_METADATA_ATTRIBUTE_RESPONSE_LOCATION);
|
||||
if (response_value) {
|
||||
response_name = g_strdup_printf("%s "
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_RESPONSE_LOCATION,
|
||||
name);
|
||||
_lasso_provider_add_metadata_value_for_role(provider, role, response_name,
|
||||
(char*)response_value);
|
||||
}
|
||||
_lasso_provider_add_metadata_value_for_role(provider, role, name, (char*)value);
|
||||
|
||||
cleanup:
|
||||
lasso_release_xml_string(value);
|
||||
lasso_release_xml_string(response_value);
|
||||
lasso_release_string(name);
|
||||
lasso_release_string(response_name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_descriptor(xmlNode *xmlnode, LassoProvider *provider, LassoProviderRole role)
|
||||
{
|
||||
static char * const descriptor_attrs[] = {
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_VALID_UNTIL,
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_CACHE_DURATION,
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_AUTHN_REQUEST_SIGNED,
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_WANT_AUTHN_REQUEST_SIGNED,
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_ERROR_URL
|
||||
};
|
||||
int i;
|
||||
xmlNode *t;
|
||||
GList *elements;
|
||||
char *name, *binding, *response_name;
|
||||
xmlChar *value;
|
||||
xmlChar *response_value;
|
||||
xmlChar *use;
|
||||
LassoProviderPrivate *pdata = provider->private_data;
|
||||
char *token, *saveptr;
|
||||
|
||||
/* check protocol support enumeration */
|
||||
value = getSaml2MdProp(xmlnode,
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_PROTOCOL_SUPPORT_ENUMERATION);
|
||||
token = strtok_r((char*) value, " ", &saveptr);
|
||||
while (token) {
|
||||
if (strcmp(token, LASSO_SAML2_PROTOCOL_HREF) == 0)
|
||||
break;
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
}
|
||||
if (g_strcmp0(token, LASSO_SAML2_PROTOCOL_HREF) != 0) {
|
||||
lasso_release_xml_string(value);
|
||||
message(G_LOG_LEVEL_WARNING, "%s descriptor does not support SAML 2.0 protocol", xmlnode->name);
|
||||
return FALSE;
|
||||
}
|
||||
lasso_release_xml_string(value);
|
||||
|
||||
t = xmlnode->children;
|
||||
/* add role to supported roles for the provider */
|
||||
pdata->roles |= role;
|
||||
t = xmlSecGetNextElementNode(xmlnode->children);
|
||||
while (t) {
|
||||
if (t->type != XML_ELEMENT_NODE) {
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
if (strcmp((char*)t->name, "KeyDescriptor") == 0) {
|
||||
use = xmlGetProp(t, (xmlChar*)"use");
|
||||
if (use == NULL || strcmp((char*)use, "signing") == 0) {
|
||||
provider->private_data->signing_key_descriptor = xmlCopyNode(t, 1);
|
||||
}
|
||||
if (use == NULL || strcmp((char*)use, "encryption") == 0) {
|
||||
provider->private_data->encryption_key_descriptor =
|
||||
xmlCopyNode(t, 1);
|
||||
}
|
||||
if (use) {
|
||||
xmlFree(use);
|
||||
}
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
if (strcmp((char*)t->name, "Attribute") == 0) {
|
||||
if (checkSaml2MdNode(t,
|
||||
LASSO_SAML2_METADATA_ELEMENT_KEY_DESCRIPTOR)) {
|
||||
_lasso_provider_load_key_descriptor(provider, t);
|
||||
} else if (checkSaml2MdNode(t,
|
||||
LASSO_SAML2_ASSERTION_ELEMENT_ATTRIBUTE) && role == LASSO_PROVIDER_ROLE_IDP) {
|
||||
LassoSaml2Attribute *attribute;
|
||||
attribute = LASSO_SAML2_ATTRIBUTE(lasso_node_new_from_xmlNode(t));
|
||||
if (attribute) {
|
||||
provider->private_data->attributes =
|
||||
g_list_append(provider->private_data->attributes, attribute);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
binding = (char*)xmlGetProp(t, (xmlChar*)"Binding");
|
||||
if (binding) {
|
||||
/* Endpoint type */
|
||||
char *binding_s = NULL;
|
||||
if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_SOAP) == 0) {
|
||||
binding_s = "SOAP";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_REDIRECT) == 0) {
|
||||
binding_s = "HTTP-Redirect";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_POST) == 0) {
|
||||
binding_s = "HTTP-POST";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_ARTIFACT) == 0) {
|
||||
binding_s = "HTTP-Artifact";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_PAOS) == 0) {
|
||||
binding_s = "PAOS";
|
||||
} else {
|
||||
message(G_LOG_LEVEL_CRITICAL, "XXX: unknown binding: %s", binding);
|
||||
xmlFree(binding);
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
value = xmlGetProp(t, (xmlChar*)"Location");
|
||||
if (value == NULL) {
|
||||
message(G_LOG_LEVEL_CRITICAL, "XXX: missing location");
|
||||
xmlFree(binding);
|
||||
t = t->next;
|
||||
continue;
|
||||
}
|
||||
if (strcmp((char*)t->name, "AssertionConsumerService") == 0) {
|
||||
char *index = (char*)xmlGetProp(t, (xmlChar*)"index");
|
||||
char *is_default = (char*)xmlGetProp(t, (xmlChar*)"isDefault");
|
||||
if (is_default && strcmp(is_default, "true") == 0) {
|
||||
provider->private_data->default_assertion_consumer =
|
||||
g_strdup(index);
|
||||
}
|
||||
name = g_strdup_printf("%s %s %s", t->name, binding_s, index);
|
||||
xmlFree(index);
|
||||
xmlFree(is_default);
|
||||
}
|
||||
else {
|
||||
name = g_strdup_printf("%s %s", t->name, binding_s);
|
||||
}
|
||||
xmlFree(binding);
|
||||
|
||||
response_value = xmlGetProp(t, (xmlChar*)"ResponseLocation");
|
||||
if (response_value) {
|
||||
response_name = g_strdup_printf("%s ResponseLocation", name);
|
||||
elements = g_hash_table_lookup(descriptor, response_name);
|
||||
elements = g_list_append(elements, g_strdup((char*)response_value));
|
||||
g_hash_table_insert(descriptor, response_name, elements);
|
||||
xmlFree(response_value);
|
||||
}
|
||||
attribute = (LassoSaml2Attribute*) lasso_node_new_from_xmlNode(t);
|
||||
lasso_list_add_new_gobject(pdata->attributes,
|
||||
attribute);
|
||||
} else if (hasSaml2MdProp(t, LASSO_SAML2_METADATA_ATTRIBUTE_BINDING)) {
|
||||
load_endpoint_type(t, provider, role);
|
||||
} else {
|
||||
name = g_strdup((char*)t->name);
|
||||
value = xmlNodeGetContent(t);
|
||||
_lasso_provider_add_metadata_value_for_role(provider, role, (char*)t->name,
|
||||
(char*)value);
|
||||
lasso_release_xml_string(value);
|
||||
}
|
||||
elements = g_hash_table_lookup(descriptor, name);
|
||||
elements = g_list_append(elements, g_strdup((char*)value));
|
||||
xmlFree(value);
|
||||
g_hash_table_insert(descriptor, name, elements);
|
||||
t = t->next;
|
||||
t = xmlSecGetNextElementNode(t->next);
|
||||
}
|
||||
|
||||
for (i = 0; descriptor_attrs[i]; i++) {
|
||||
value = xmlGetProp(xmlnode, (xmlChar*)descriptor_attrs[i]);
|
||||
value = getSaml2MdProp(xmlnode, descriptor_attrs[i]);
|
||||
if (value == NULL) {
|
||||
continue;
|
||||
}
|
||||
name = g_strdup(descriptor_attrs[i]);
|
||||
elements = g_hash_table_lookup(descriptor, name);
|
||||
elements = g_list_append(elements, g_strdup((char*)value));
|
||||
xmlFree(value);
|
||||
g_hash_table_insert(descriptor, name, elements);
|
||||
_lasso_provider_add_metadata_value_for_role(provider, role, descriptor_attrs[i],
|
||||
(char*)value);
|
||||
lasso_release_xml_string(value);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -173,103 +234,104 @@ lasso_saml20_provider_load_metadata(LassoProvider *provider, xmlNode *root_node)
|
|||
{
|
||||
xmlNode *node, *descriptor_node;
|
||||
xmlChar *providerID;
|
||||
LassoProviderPrivate *pdata = provider->private_data;
|
||||
static const struct {
|
||||
char *name;
|
||||
LassoProviderRole role;
|
||||
} descriptors[] = {
|
||||
{ LASSO_SAML2_METADATA_ELEMENT_IDP_SSO_DESCRIPTOR,
|
||||
LASSO_PROVIDER_ROLE_IDP },
|
||||
{ LASSO_SAML2_METADATA_ELEMENT_SP_SSO_DESCRIPTOR,
|
||||
LASSO_PROVIDER_ROLE_SP },
|
||||
{ LASSO_SAML2_METADATA_ELEMENT_ATTRIBUTE_AUTHORITY_DESCRIPTOR,
|
||||
LASSO_PROVIDER_ROLE_ATTRIBUTE_AUTHORITY },
|
||||
{ LASSO_SAML2_METADATA_ELEMENT_PDP_DESCRIPTOR,
|
||||
LASSO_PROVIDER_ROLE_AUTHZ_AUTHORITY },
|
||||
{ LASSO_SAML2_METADATA_ELEMENT_AUTHN_DESCRIPTOR,
|
||||
LASSO_PROVIDER_ROLE_AUTHN_AUTHORITY },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
if (strcmp((char*)root_node->name, "EntityDescriptor") == 0) {
|
||||
/* find a root node for the metadata file */
|
||||
if (xmlSecCheckNodeName(root_node,
|
||||
BAD_CAST LASSO_SAML2_METADATA_ELEMENT_ENTITY_DESCRIPTOR,
|
||||
BAD_CAST LASSO_SAML2_METADATA_HREF)) {
|
||||
node = root_node;
|
||||
} else if (strcmp((char*)root_node->name, "EntitiesDescriptor") == 0) {
|
||||
/* XXX: take the first entity; would it be possible to have an
|
||||
* optional argument to take another one ? */
|
||||
node = root_node->children;
|
||||
while (node && strcmp((char*)node->name, "EntityDescriptor") != 0) {
|
||||
node = node->next;
|
||||
}
|
||||
if (node == NULL) {
|
||||
message (G_LOG_LEVEL_CRITICAL, "lasso_saml20_provider_load_metadata_from_doc: no EntityDescriptor");
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
message (G_LOG_LEVEL_CRITICAL, "lasso_saml20_provider_load_metadata_from_doc: no EntityDescriptor");
|
||||
/* what? */
|
||||
return FALSE;
|
||||
} else if (xmlSecCheckNodeName(root_node,
|
||||
BAD_CAST LASSO_SAML2_METADATA_ELEMENT_ENTITIES_DESCRIPTOR,
|
||||
BAD_CAST LASSO_SAML2_METADATA_HREF)) {
|
||||
node = xmlSecFindChild(root_node,
|
||||
BAD_CAST LASSO_SAML2_METADATA_ELEMENT_ENTITY_DESCRIPTOR,
|
||||
BAD_CAST LASSO_SAML2_METADATA_HREF);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (node, FALSE);
|
||||
providerID = xmlGetProp(node, (xmlChar*)"entityID");
|
||||
g_return_val_if_fail(providerID, FALSE);
|
||||
lasso_assign_string(provider->ProviderID, (char*)providerID);
|
||||
lasso_release_xml_string(providerID);
|
||||
if (provider->ProviderID == NULL) {
|
||||
message (G_LOG_LEVEL_CRITICAL, "lasso_saml20_provider_load_metadata_from_doc: no entityID attribute");
|
||||
return FALSE;
|
||||
/* initialize roles */
|
||||
pdata->roles = LASSO_PROVIDER_ROLE_NONE;
|
||||
lasso_set_string_from_prop(&pdata->valid_until, node,
|
||||
BAD_CAST LASSO_SAML2_METADATA_ATTRIBUTE_VALID_UNTIL,
|
||||
BAD_CAST LASSO_SAML2_METADATA_HREF);
|
||||
lasso_set_string_from_prop(&pdata->cache_duration, node,
|
||||
BAD_CAST LASSO_SAML2_METADATA_ATTRIBUTE_CACHE_DURATION,
|
||||
BAD_CAST LASSO_SAML2_METADATA_HREF);
|
||||
|
||||
descriptor_node = xmlSecGetNextElementNode(node->children);
|
||||
while (descriptor_node) {
|
||||
int i = 0;
|
||||
|
||||
while (descriptors[i].name) {
|
||||
char *name = descriptors[i].name;
|
||||
LassoProviderRole role = descriptors[i].role;
|
||||
|
||||
if (checkSaml2MdNode(descriptor_node, name)) {
|
||||
load_descriptor(descriptor_node,
|
||||
provider,
|
||||
role);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (checkSaml2MdNode(descriptor_node,
|
||||
LASSO_SAML2_METADATA_ELEMENT_ORGANIZATION)) {
|
||||
lasso_assign_xml_node(pdata->organization, descriptor_node); }
|
||||
descriptor_node = xmlSecGetNextElementNode(descriptor_node->next);
|
||||
}
|
||||
|
||||
for (descriptor_node = node->children; descriptor_node != NULL;
|
||||
descriptor_node = descriptor_node->next) {
|
||||
if (descriptor_node->type != XML_ELEMENT_NODE)
|
||||
continue;
|
||||
|
||||
if (strcmp((char*)descriptor_node->name, "IDPSSODescriptor") == 0) {
|
||||
load_descriptor(descriptor_node,
|
||||
provider->private_data->Descriptors, provider);
|
||||
provider->role = LASSO_PROVIDER_ROLE_IDP;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp((char*)descriptor_node->name, "SPSSODescriptor") == 0) {
|
||||
load_descriptor(descriptor_node,
|
||||
provider->private_data->Descriptors, provider);
|
||||
provider->role = LASSO_PROVIDER_ROLE_SP;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp((char*)descriptor_node->name, "AttributeAuthorityDescriptor") == 0) {
|
||||
load_descriptor(descriptor_node,
|
||||
provider->private_data->Descriptors, provider);
|
||||
provider->role = LASSO_PROVIDER_ROLE_ATTRIBUTE_AUTHORITY;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp((char*)descriptor_node->name, "PDPDescriptor") == 0) {
|
||||
load_descriptor(descriptor_node,
|
||||
provider->private_data->Descriptors, provider);
|
||||
provider->role = LASSO_PROVIDER_ROLE_PDP;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp((char*)descriptor_node->name, "AuthnAuthorityDescriptor") == 0) {
|
||||
load_descriptor(descriptor_node,
|
||||
provider->private_data->Descriptors, provider);
|
||||
provider->role = LASSO_PROVIDER_ROLE_AUTHN_AUTHORITY;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp((char*)descriptor_node->name, "Organization") == 0) {
|
||||
provider->private_data->organization = xmlCopyNode(
|
||||
descriptor_node, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LassoHttpMethod
|
||||
lasso_saml20_provider_get_first_http_method(LassoProvider *provider,
|
||||
const LassoProvider *remote_provider, LassoMdProtocolType protocol_type)
|
||||
LassoProvider *remote_provider, LassoMdProtocolType protocol_type)
|
||||
{
|
||||
LassoHttpMethod method = LASSO_HTTP_METHOD_NONE;
|
||||
int i;
|
||||
const char *possible_bindings[] = {
|
||||
"HTTP-Redirect", "HTTP-Post", "SOAP", "HTTP-Artifact", NULL
|
||||
"HTTP-POST",
|
||||
"HTTP-Redirect",
|
||||
"HTTP-Artifact",
|
||||
"SOAP",
|
||||
"PAOS",
|
||||
NULL
|
||||
};
|
||||
LassoHttpMethod method_bindings[] = {
|
||||
LASSO_HTTP_METHOD_SOAP, LASSO_HTTP_METHOD_REDIRECT, LASSO_HTTP_METHOD_POST
|
||||
LASSO_HTTP_METHOD_POST,
|
||||
LASSO_HTTP_METHOD_REDIRECT,
|
||||
LASSO_HTTP_METHOD_ARTIFACT_GET,
|
||||
LASSO_HTTP_METHOD_SOAP,
|
||||
LASSO_HTTP_METHOD_PAOS
|
||||
};
|
||||
for (i=0; possible_bindings[i] && method == LASSO_HTTP_METHOD_NONE; i++) {
|
||||
char *s;
|
||||
const GList *l1, *l2;
|
||||
|
||||
s = g_strdup_printf("%s %s", profile_names[protocol_type], possible_bindings[i]);
|
||||
s = g_strdup_printf("%s %s",
|
||||
profile_names[protocol_type],
|
||||
possible_bindings[i]);
|
||||
l1 = lasso_provider_get_metadata_list(provider, s);
|
||||
l2 = lasso_provider_get_metadata_list(remote_provider, s);
|
||||
if (l1 && l2) {
|
||||
|
@ -286,37 +348,29 @@ lasso_saml20_provider_check_assertion_consumer_service_url(LassoProvider *provid
|
|||
GHashTable *descriptor;
|
||||
GList *l = NULL, *r = NULL, *candidate = NULL;
|
||||
char *name;
|
||||
char *binding_s = NULL;
|
||||
const char *binding_s = NULL;
|
||||
int lname;
|
||||
|
||||
descriptor = provider->private_data->SPDescriptor;
|
||||
descriptor = provider->private_data->Descriptors;
|
||||
if (descriptor == NULL || url == NULL || binding == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_SOAP) == 0) {
|
||||
binding_s = "SOAP";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_REDIRECT) == 0) {
|
||||
binding_s = "HTTP-Redirect";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_POST) == 0) {
|
||||
binding_s = "HTTP-POST";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_ARTIFACT) == 0) {
|
||||
binding_s = "HTTP-Artifact";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_PAOS) == 0) {
|
||||
binding_s = "PAOS";
|
||||
}
|
||||
|
||||
binding_s = binding_uri_to_identifier(binding);
|
||||
if (binding_s == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_foreach(descriptor, (GHFunc)add_assertion_consumer_url_to_list, &r);
|
||||
g_hash_table_foreach(descriptor,
|
||||
(GHFunc)add_assertion_consumer_url_to_list,
|
||||
&r);
|
||||
|
||||
name = g_strdup_printf("AssertionConsumerService %s ", binding_s);
|
||||
name = g_strdup_printf(LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE
|
||||
" %s ", binding_s);
|
||||
lname = strlen(name);
|
||||
for (l = r; l; l = g_list_next(l)) {
|
||||
char *b = l->data;
|
||||
if (strncmp(name, b, lname) == 0) {
|
||||
candidate = g_hash_table_lookup(descriptor, b);
|
||||
candidate = lasso_provider_get_metadata_list_for_role(provider, LASSO_PROVIDER_ROLE_SP, b);
|
||||
if (candidate && candidate->data && strcmp(candidate->data, url) == 0)
|
||||
break;
|
||||
else
|
||||
|
@ -333,15 +387,17 @@ lasso_saml20_provider_check_assertion_consumer_service_url(LassoProvider *provid
|
|||
}
|
||||
|
||||
gchar*
|
||||
lasso_saml20_provider_get_assertion_consumer_service_url(const LassoProvider *provider,
|
||||
lasso_saml20_provider_get_assertion_consumer_service_url(LassoProvider *provider,
|
||||
int service_id)
|
||||
{
|
||||
GHashTable *descriptor;
|
||||
GList *l = NULL;
|
||||
char *sid;
|
||||
char *name;
|
||||
const char *possible_bindings[] = {
|
||||
"HTTP-Artifact", "HTTP-Post", "HTTP-POST", "HTTP-Redirect", "SOAP", NULL
|
||||
"HTTP-Artifact",
|
||||
"HTTP-POST",
|
||||
"HTTP-Redirect",
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
|
@ -351,19 +407,18 @@ lasso_saml20_provider_get_assertion_consumer_service_url(const LassoProvider *pr
|
|||
sid = g_strdup_printf("%d", service_id);
|
||||
}
|
||||
|
||||
descriptor = provider->private_data->Descriptors;
|
||||
if (descriptor == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i=0; possible_bindings[i]; i++) {
|
||||
name = g_strdup_printf("AssertionConsumerService %s %s",
|
||||
name = g_strdup_printf(LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE
|
||||
" %s %s",
|
||||
possible_bindings[i], sid);
|
||||
l = g_hash_table_lookup(descriptor, name);
|
||||
g_free(name);
|
||||
l = lasso_provider_get_metadata_list_for_role(provider,
|
||||
LASSO_PROVIDER_ROLE_SP,
|
||||
name);
|
||||
lasso_release_string(name);
|
||||
if (l != NULL)
|
||||
break;
|
||||
}
|
||||
g_free(sid);
|
||||
lasso_release_string(sid);
|
||||
if (l)
|
||||
return g_strdup(l->data);
|
||||
return NULL;
|
||||
|
@ -372,45 +427,37 @@ lasso_saml20_provider_get_assertion_consumer_service_url(const LassoProvider *pr
|
|||
static void
|
||||
add_assertion_consumer_url_to_list(gchar *key, G_GNUC_UNUSED gpointer value, GList **list)
|
||||
{
|
||||
if (strncmp(key, "AssertionConsumerService", 24) == 0) {
|
||||
*list = g_list_append(*list, key);
|
||||
if (strncmp(key, "sp AssertionConsumerService", 24) == 0) {
|
||||
lasso_list_add_new_string(*list, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gchar*
|
||||
lasso_saml20_provider_get_assertion_consumer_service_url_by_binding(const LassoProvider *provider,
|
||||
gchar *binding)
|
||||
lasso_saml20_provider_get_assertion_consumer_service_url_by_binding(LassoProvider *provider,
|
||||
const gchar *binding)
|
||||
{
|
||||
GHashTable *descriptor;
|
||||
GList *l = NULL, *r = NULL;
|
||||
char *name;
|
||||
char *binding_s = NULL;
|
||||
const char *binding_s = NULL;
|
||||
int lname;
|
||||
|
||||
descriptor = provider->private_data->Descriptors;
|
||||
if (descriptor == NULL)
|
||||
return NULL;
|
||||
|
||||
if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_SOAP) == 0) {
|
||||
binding_s = "SOAP";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_REDIRECT) == 0) {
|
||||
binding_s = "HTTP-Redirect";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_POST) == 0) {
|
||||
binding_s = "HTTP-POST";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_ARTIFACT) == 0) {
|
||||
binding_s = "HTTP-Artifact";
|
||||
} else if (strcmp(binding, LASSO_SAML2_METADATA_BINDING_PAOS) == 0) {
|
||||
binding_s = "PAOS";
|
||||
}
|
||||
|
||||
binding_s = binding_uri_to_identifier(binding);
|
||||
if (binding_s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_hash_table_foreach(descriptor, (GHFunc)add_assertion_consumer_url_to_list, &r);
|
||||
g_hash_table_foreach(descriptor,
|
||||
(GHFunc)add_assertion_consumer_url_to_list,
|
||||
&r);
|
||||
|
||||
name = g_strdup_printf("AssertionConsumerService %s ", binding_s);
|
||||
name = g_strdup_printf("sp "
|
||||
LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE
|
||||
" %s ", binding_s);
|
||||
lname = strlen(name);
|
||||
for (l = r; l; l = g_list_next(l)) {
|
||||
char *b = l->data;
|
||||
|
@ -419,8 +466,8 @@ lasso_saml20_provider_get_assertion_consumer_service_url_by_binding(const LassoP
|
|||
break;
|
||||
}
|
||||
}
|
||||
g_free(name);
|
||||
g_list_free(r);
|
||||
lasso_release_string(name);
|
||||
lasso_release_list(r);
|
||||
|
||||
if (l) {
|
||||
return g_strdup(l->data);
|
||||
|
@ -429,10 +476,8 @@ lasso_saml20_provider_get_assertion_consumer_service_url_by_binding(const LassoP
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gchar*
|
||||
lasso_saml20_provider_get_assertion_consumer_service_binding(const LassoProvider *provider,
|
||||
lasso_saml20_provider_get_assertion_consumer_service_binding(LassoProvider *provider,
|
||||
int service_id)
|
||||
{
|
||||
GHashTable *descriptor;
|
||||
|
@ -441,7 +486,11 @@ lasso_saml20_provider_get_assertion_consumer_service_binding(const LassoProvider
|
|||
char *name;
|
||||
char *binding = NULL;
|
||||
const char *possible_bindings[] = {
|
||||
"HTTP-Artifact", "HTTP-Post", "HTTP-POST", "HTTP-Redirect", "SOAP", NULL
|
||||
"HTTP-POST",
|
||||
"HTTP-Redirect",
|
||||
"HTTP-Artifact",
|
||||
"SOAP",
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
|
@ -450,32 +499,32 @@ lasso_saml20_provider_get_assertion_consumer_service_binding(const LassoProvider
|
|||
} else {
|
||||
sid = g_strdup_printf("%d", service_id);
|
||||
}
|
||||
|
||||
descriptor = provider->private_data->Descriptors;
|
||||
if (descriptor == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i=0; possible_bindings[i]; i++) {
|
||||
name = g_strdup_printf("AssertionConsumerService %s %s",
|
||||
name = g_strdup_printf(LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE
|
||||
" %s %s",
|
||||
possible_bindings[i], sid);
|
||||
l = g_hash_table_lookup(descriptor, name);
|
||||
g_free(name);
|
||||
l = lasso_provider_get_metadata_list_for_role(provider, LASSO_PROVIDER_ROLE_SP, name);
|
||||
lasso_release_string(name);
|
||||
if (l != NULL) {
|
||||
binding = g_strdup(possible_bindings[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free(sid);
|
||||
lasso_release_string(sid);
|
||||
return binding;
|
||||
}
|
||||
|
||||
gboolean
|
||||
lasso_saml20_provider_accept_http_method(LassoProvider *provider, const LassoProvider *remote_provider,
|
||||
lasso_saml20_provider_accept_http_method(LassoProvider *provider, LassoProvider *remote_provider,
|
||||
LassoMdProtocolType protocol_type, LassoHttpMethod http_method,
|
||||
gboolean initiate_profile)
|
||||
{
|
||||
char *protocol_profile;
|
||||
const static char *http_methods[] = {
|
||||
static const char *http_methods[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
@ -488,7 +537,7 @@ lasso_saml20_provider_accept_http_method(LassoProvider *provider, const LassoPro
|
|||
NULL
|
||||
};
|
||||
gboolean rc = FALSE;
|
||||
|
||||
LassoProviderRole initiating_role;
|
||||
|
||||
initiating_role = remote_provider->role;
|
||||
if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) {
|
||||
|
@ -511,7 +560,7 @@ lasso_saml20_provider_accept_http_method(LassoProvider *provider, const LassoPro
|
|||
/* special hack for single sign on */
|
||||
if (protocol_type == LASSO_MD_PROTOCOL_TYPE_SINGLE_SIGN_ON) {
|
||||
/* no need to check for the response, it uses another canal
|
||||
* (AssertionConsumingService) */
|
||||
* (AssertionConsumerService) */
|
||||
rc = (lasso_provider_get_metadata_list(remote_provider, protocol_profile) != NULL);
|
||||
|
||||
} else {
|
||||
|
|
|
@ -35,20 +35,20 @@ extern "C" {
|
|||
gboolean lasso_saml20_provider_load_metadata(LassoProvider *provider, xmlNode *root_node);
|
||||
|
||||
LassoHttpMethod lasso_saml20_provider_get_first_http_method(LassoProvider *provider,
|
||||
const LassoProvider *remote_provider, LassoMdProtocolType protocol_type);
|
||||
LassoProvider *remote_provider, LassoMdProtocolType protocol_type);
|
||||
|
||||
gboolean lasso_saml20_provider_accept_http_method(LassoProvider *provider,
|
||||
const LassoProvider *remote_provider, LassoMdProtocolType protocol_type,
|
||||
LassoProvider *remote_provider, LassoMdProtocolType protocol_type,
|
||||
LassoHttpMethod http_method, gboolean initiate_profile);
|
||||
|
||||
char* lasso_saml20_provider_build_artifact(const LassoProvider *provider);
|
||||
char* lasso_saml20_provider_build_artifact(LassoProvider *provider);
|
||||
|
||||
gchar* lasso_saml20_provider_get_assertion_consumer_service_url(const LassoProvider *provider,
|
||||
gchar* lasso_saml20_provider_get_assertion_consumer_service_url(LassoProvider *provider,
|
||||
int service_id);
|
||||
gchar* lasso_saml20_provider_get_assertion_consumer_service_binding(const LassoProvider *provider,
|
||||
gchar* lasso_saml20_provider_get_assertion_consumer_service_binding(LassoProvider *provider,
|
||||
int service_id);
|
||||
gchar* lasso_saml20_provider_get_assertion_consumer_service_url_by_binding(const LassoProvider *provider,
|
||||
gchar *binding);
|
||||
gchar* lasso_saml20_provider_get_assertion_consumer_service_url_by_binding(LassoProvider *provider,
|
||||
const gchar *binding);
|
||||
gboolean lasso_saml20_provider_check_assertion_consumer_service_url(LassoProvider *provider, const gchar *url, const gchar *binding);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -116,6 +116,13 @@
|
|||
*/
|
||||
#define LASSO_SAML2_METADATA_BINDING_PAOS "urn:oasis:names:tc:SAML:2.0:bindings:PAOS"
|
||||
|
||||
/**
|
||||
* LASSO_SAML2_METADATA_BINDING_URI:
|
||||
*
|
||||
* URI for the URI special binding.
|
||||
*/
|
||||
#define LASSO_SAML2_METADATA_BINDING_URI "urn:oasis:names:tc:SAML:2.0:bindings:URI"
|
||||
|
||||
/**
|
||||
* LASSO_SAML2_DEFLATE_ENCODING:
|
||||
*
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#define LASSO_SAML2_METADATA_ELEMENT_SP_SSO_DESCRIPTOR "SPSSODescriptor"
|
||||
#define LASSO_SAML2_METADATA_ELEMENT_ATTRIBUTE_AUTHORITY_DESCRIPTOR "AttributeAuthorityDescriptor"
|
||||
#define LASSO_SAML2_METADATA_ELEMENT_PDP_DESCRIPTOR "PDPDescriptor"
|
||||
#define LASSO_SAML2_METADATA_ELEMENT_AUTHN_DESCRIPTOR "AuthnAuhtorityDescriptor"
|
||||
#define LASSO_SAML2_METADATA_ELEMENT_AUTHN_DESCRIPTOR "AuthnAuthorityDescriptor"
|
||||
#define LASSO_SAML2_METADATA_ELEMENT_ORGANIZATION "Organization"
|
||||
#define LASSO_SAML2_METADATA_ELEMENT_KEY_DESCRIPTOR "KeyDescriptor"
|
||||
#define LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE "AssertionConsumerService"
|
||||
|
|
|
@ -20,7 +20,7 @@ INCLUDES = \
|
|||
$(CHECK_CFLAGS)
|
||||
|
||||
|
||||
tests_SOURCES = tests.c login_tests.c basic_tests.c random_tests.c metadata_tests.c login_tests_saml2.c $(WSF_TESTS)
|
||||
tests_SOURCES = tests.c login_tests.c basic_tests.c random_tests.c metadata_tests.c login_tests_saml2.c assertion_query_saml2.c $(WSF_TESTS)
|
||||
|
||||
tests_LDADD = \
|
||||
$(top_builddir)/lasso/liblasso.la \
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Lasso library C unit tests
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <check.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "../lasso/lasso.h"
|
||||
#include "../lasso/utils.h"
|
||||
#include "../lasso/backward_comp.h"
|
||||
#include "../lasso/xml/saml-2.0/saml2_xsd.h"
|
||||
|
||||
#include "./tests.h"
|
||||
|
||||
inline static char*
|
||||
generateIdentityProviderContextDump()
|
||||
{
|
||||
LassoServer *serverContext;
|
||||
GList *providers;
|
||||
char *ret;
|
||||
|
||||
serverContext = lasso_server_new(
|
||||
TESTSDATADIR "/idp6-saml2/metadata.xml",
|
||||
TESTSDATADIR "/idp6-saml2/private-key.pem",
|
||||
NULL, /* Secret key to unlock private key */
|
||||
NULL);
|
||||
lasso_server_add_provider(
|
||||
serverContext,
|
||||
LASSO_PROVIDER_ROLE_SP,
|
||||
TESTSDATADIR "/sp5-saml2/metadata.xml",
|
||||
NULL,
|
||||
NULL);
|
||||
providers = g_hash_table_get_values(serverContext->providers);
|
||||
lasso_provider_set_encryption_mode(LASSO_PROVIDER(providers->data), LASSO_ENCRYPTION_MODE_ASSERTION | LASSO_ENCRYPTION_MODE_NAMEID);
|
||||
ret = lasso_server_dump(serverContext);
|
||||
|
||||
g_object_unref(serverContext);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static char*
|
||||
generateServiceProviderContextDump()
|
||||
{
|
||||
LassoServer *serverContext;
|
||||
char *ret;
|
||||
|
||||
serverContext = lasso_server_new(
|
||||
TESTSDATADIR "/sp5-saml2/metadata.xml",
|
||||
TESTSDATADIR "/sp5-saml2/private-key.pem",
|
||||
NULL, /* Secret key to unlock private key */
|
||||
NULL);
|
||||
lasso_server_add_provider(
|
||||
serverContext,
|
||||
LASSO_PROVIDER_ROLE_IDP,
|
||||
TESTSDATADIR "/idp6-saml2/metadata.xml",
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
ret = lasso_server_dump(serverContext);
|
||||
g_object_unref(serverContext);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Suite*
|
||||
assertion_query_suite()
|
||||
{
|
||||
Suite *s = suite_create("Assertion Query");
|
||||
TCase *tc_metadata_access = tcase_create("Extended metadata access");
|
||||
suite_add_tcase(s, tc_metadata_access);
|
||||
|
||||
return s;
|
||||
}
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
#include <../lasso/lasso.h>
|
||||
#include <../lasso/id-ff/provider.h>
|
||||
#include "../lasso/utils.h"
|
||||
#include "./tests.h"
|
||||
#include "../lasso/xml/saml-2.0/saml2_xsd.h"
|
||||
|
||||
START_TEST(test01_metadata_load_der_certificate_from_x509_cert)
|
||||
{
|
||||
|
@ -83,6 +86,29 @@ START_TEST(test06_metadata_load_public_key_from_rsa_keyvalue)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test07_metadata_role_descriptors)
|
||||
{
|
||||
LassoProvider *provider = (LassoProvider*)lasso_provider_new(LASSO_PROVIDER_ROLE_IDP, TESTSDATADIR "/idp6-saml2/metadata.xml",
|
||||
NULL, NULL);
|
||||
GList *l, *q;
|
||||
int i = 0;
|
||||
|
||||
check_not_null(provider);
|
||||
for (i = LASSO_PROVIDER_ROLE_ANY+1; i < LASSO_PROVIDER_ROLE_LAST; i++) {
|
||||
l = lasso_provider_get_metadata_keys_for_role(provider, i);
|
||||
lasso_foreach(q, l) {
|
||||
printf("%i %s\n", i, (char*)q->data);
|
||||
}
|
||||
}
|
||||
l = lasso_provider_get_metadata_list_for_role(provider, LASSO_PROVIDER_ROLE_IDP,
|
||||
LASSO_SAML2_METADATA_ATTRIBUTE_WANT_AUTHN_REQUEST_SIGNED);
|
||||
check_not_null(l);
|
||||
check_null(l->next);
|
||||
check_str_equals(l->data, "true");
|
||||
lasso_release_gobject(provider);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite*
|
||||
metadata_suite()
|
||||
{
|
||||
|
@ -99,12 +125,16 @@ metadata_suite()
|
|||
tcase_create("Load DER public key from <ds:X509Certificate>");
|
||||
TCase *tc_metadata_load_public_key_from_rsa_keyvalue =
|
||||
tcase_create("Load RSAKeyValue public key");
|
||||
TCase *tc_metadata_role_descriptors =
|
||||
tcase_create("Lookup different role descriptors datas");
|
||||
|
||||
suite_add_tcase(s, tc_metadata_load_der_certificate_from_x509_cert);
|
||||
suite_add_tcase(s, tc_metadata_load_pem_certificate_from_x509_cert);
|
||||
suite_add_tcase(s, tc_metadata_load_der_public_key_from_keyvalue);
|
||||
suite_add_tcase(s, tc_metadata_load_pem_public_key_from_keyvalue);
|
||||
suite_add_tcase(s, tc_metadata_load_public_key_from_x509_cert);
|
||||
suite_add_tcase(s, tc_metadata_load_public_key_from_rsa_keyvalue);
|
||||
suite_add_tcase(s, tc_metadata_role_descriptors);
|
||||
tcase_add_test(tc_metadata_load_der_certificate_from_x509_cert,
|
||||
test01_metadata_load_der_certificate_from_x509_cert);
|
||||
tcase_add_test(tc_metadata_load_pem_certificate_from_x509_cert,
|
||||
|
@ -117,5 +147,7 @@ metadata_suite()
|
|||
test05_metadata_load_public_key_from_x509_cert);
|
||||
tcase_add_test(tc_metadata_load_public_key_from_rsa_keyvalue,
|
||||
test06_metadata_load_public_key_from_rsa_keyvalue);
|
||||
tcase_add_test(tc_metadata_role_descriptors,
|
||||
test07_metadata_role_descriptors);
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ extern Suite* login_suite();
|
|||
extern Suite* login_saml2_suite();
|
||||
extern Suite* random_suite();
|
||||
extern Suite* metadata_suite();
|
||||
extern Suite* assertion_query_suite();
|
||||
#ifdef LASSO_WSF_ENABLED
|
||||
extern Suite* idwsf2_suite();
|
||||
#endif
|
||||
|
@ -46,6 +47,7 @@ SuiteFunction suites[] = {
|
|||
login_saml2_suite,
|
||||
random_suite,
|
||||
metadata_suite,
|
||||
assertion_query_suite,
|
||||
#ifdef LASSO_WSF_ENABLED
|
||||
idwsf2_suite,
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue