summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2010-03-27 16:52:04 +0000
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2010-03-27 16:52:04 +0000
commitc07cd3898cfc00ab6dbfc4c48b31e7d4858808ec (patch)
treead57ebe2fc8dd266a1c5218725d9b801e8f2eafa
parent16d4b4df24f0bdd341756d3be20bbbc30c3414e5 (diff)
downloadlasso-c07cd3898cfc00ab6dbfc4c48b31e7d4858808ec.tar.gz
lasso-c07cd3898cfc00ab6dbfc4c48b31e7d4858808ec.tar.xz
lasso-c07cd3898cfc00ab6dbfc4c48b31e7d4858808ec.zip
SAML 2.0&ID-FF 1.2: simplify and complete metadata loading for multi-role support
-rw-r--r--docs/reference/lasso/lasso-sections.txt7
-rw-r--r--lasso/id-ff/profile.h3
-rw-r--r--lasso/id-ff/provider.c491
-rw-r--r--lasso/id-ff/provider.h55
-rw-r--r--lasso/id-ff/providerprivate.h6
-rw-r--r--lasso/saml-2.0/assertion_query.c293
-rw-r--r--lasso/saml-2.0/profile.c28
-rw-r--r--lasso/saml-2.0/profileprivate.h2
-rw-r--r--lasso/saml-2.0/provider.c511
-rw-r--r--lasso/saml-2.0/providerprivate.h14
-rw-r--r--lasso/xml/saml-2.0/saml2_strings.h7
-rw-r--r--lasso/xml/saml-2.0/saml2_xsd.h2
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/assertion_query_saml2.c95
-rw-r--r--tests/metadata_tests.c32
-rw-r--r--tests/tests.c2
16 files changed, 1007 insertions, 543 deletions
diff --git a/docs/reference/lasso/lasso-sections.txt b/docs/reference/lasso/lasso-sections.txt
index a73bc9ee..9c91d374 100644
--- a/docs/reference/lasso/lasso-sections.txt
+++ b/docs/reference/lasso/lasso-sections.txt
@@ -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
diff --git a/lasso/id-ff/profile.h b/lasso/id-ff/profile.h
index 5dc5be2f..270a3034 100644
--- a/lasso/id-ff/profile.h
+++ b/lasso/id-ff/profile.h
@@ -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
}
diff --git a/lasso/id-ff/provider.c b/lasso/id-ff/provider.c
index 0dcd9d5e..5e874100 100644
--- a/lasso/id-ff/provider.c
+++ b/lasso/id-ff/provider.c
@@ -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,58 +112,132 @@ 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)
{
- GHashTable *descriptor;
- GList *l;
- char *sid = (char*)service_id;
- char *name;
+ char *name = NULL;
+ char *assertion_consumer_service_url = NULL;
- g_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL);
- if (sid == NULL)
- sid = provider->private_data->default_assertion_consumer;
+ 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);
- descriptor = provider->private_data->Descriptors;
- if (descriptor == NULL)
- return NULL;
+ return assertion_consumer_service_url;
+}
- name = g_strdup_printf("AssertionConsumerServiceURL %s", sid);
- l = g_hash_table_lookup(descriptor, name);
- g_free(name);
- if (l == NULL)
- return NULL;
+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;
+ }
+}
- return g_strdup(l->data);
+void
+_lasso_provider_add_metadata_value_for_role(LassoProvider *provider, LassoProviderRole role, const char *name, const char *value)
+{
+ GList *l;
+ GHashTable *descriptor;
+ char *symbol;
+ LassoProviderRoleIndex role_index;
+
+ 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);
}
/**
- * lasso_provider_get_metadata_one:
+ * lasso_provider_get_metadata_list_for_role:
* @provider: a #LassoProvider
+ * @role: a #LassoProviderRole value
* @name: the element name
*
- * Extracts the element @name from the provider metadata descriptor.
+ * Extracts zero to many elements from the @provider descriptor for the given @role.
*
- * Return value:(transfer full)(allow-none): the element value, NULL if the element was not found. This
- * string must be freed by the caller.
+ * 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.
**/
-gchar*
-lasso_provider_get_metadata_one(const LassoProvider *provider, const char *name)
+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), NULL);
+ 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;
- l = g_hash_table_lookup(descriptor, name);
+
+ symbol = g_strdup_printf("%s %s", protocol_roles[role_index], name);
+ l = g_hash_table_lookup(descriptor, symbol);
+ g_free(symbol);
+
+ 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;
}
+/**
+ * lasso_provider_get_metadata_one:
+ * @provider: a #LassoProvider
+ * @name: the element name
+ *
+ * Extracts the element @name from the provider metadata descriptor.
+ *
+ * Return value:(transfer full)(allow-none): the element value, NULL if the element was not found. This
+ * string must be freed by the caller.
+ **/
+gchar*
+lasso_provider_get_metadata_one(LassoProvider *provider, const char *name)
+{
+ return lasso_provider_get_metadata_one_for_role(provider, provider->role, name);
+}
/**
* lasso_provider_get_metadata_list:
@@ -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;
+}
diff --git a/lasso/id-ff/provider.h b/lasso/id-ff/provider.h
index be30426f..f3124f2f 100644
--- a/lasso/id-ff/provider.h
+++ b/lasso/id-ff/provider.h
@@ -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 */
diff --git a/lasso/id-ff/providerprivate.h b/lasso/id-ff/providerprivate.h
index 2382cf69..de3bc963 100644
--- a/lasso/id-ff/providerprivate.h
+++ b/lasso/id-ff/providerprivate.h
@@ -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
diff --git a/lasso/saml-2.0/assertion_query.c b/lasso/saml-2.0/assertion_query.c
index de7ae6bc..ddf8ad7e 100644
--- a/lasso/saml-2.0/assertion_query.c
+++ b/lasso/saml-2.0/assertion_query.c
@@ -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();
-
- 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;
- }
- request->private_key_file = g_strdup(profile->server->private_key);
- request->certificate_file = g_strdup(profile->server->certificate);
-
- profile->http_request_method = http_method;
+ if (LASSO_IS_SAMLP2_SUBJECT_QUERY_ABSTRACT(request)) {
+ LassoSamlp2SubjectQueryAbstract *sqa;
- return ret;
+ sqa = (LassoSamlp2SubjectQueryAbstract*)request;
+ sqa->Subject = (LassoSaml2Subject*)lasso_saml2_subject_new();
+ }
+ 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 critical_error(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD);
+ return lasso_saml20_profile_build_request_msg(&assertion_query->parent,
+ NULL,
+ LASSO_HTTP_METHOD_SOAP, url);
+ }
+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);
- }
-
- 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);
- }
+ response = (LassoSamlp2StatusResponse*) lasso_samlp2_response_new();
+ lasso_check_good_rc(lasso_saml20_profile_validate_request(profile,
+ FALSE,
+ response,
+ &remote_provider));
- 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->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);
- 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);
- }
+ response = (LassoSamlp2StatusResponse*) lasso_samlp2_response_new();
- /* 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);
+ lasso_check_good_rc(lasso_saml20_profile_init_response(
+ profile,
+ response,
+ LASSO_SAML2_STATUS_CODE_RESPONDER,
+ LASSO_SAML2_STATUS_CODE_REQUEST_DENIED));
return 0;
}
- return LASSO_PROFILE_ERROR_MISSING_REQUEST;
+ /* build logout response message */
+ 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;
}
@@ -487,12 +428,6 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode)
/*****************************************************************************/
static void
-dispose(GObject *object)
-{
- G_OBJECT_CLASS(parent_class)->dispose(object);
-}
-
-static void
finalize(GObject *object)
{
LassoAssertionQuery *profile = LASSO_ASSERTION_QUERY(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);
}
diff --git a/lasso/saml-2.0/profile.c b/lasso/saml-2.0/profile.c
index 7be10686..a27966bc 100644
--- a/lasso/saml-2.0/profile.c
+++ b/lasso/saml-2.0/profile.c
@@ -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)
diff --git a/lasso/saml-2.0/profileprivate.h b/lasso/saml-2.0/profileprivate.h
index 04677633..c3968aa3 100644
--- a/lasso/saml-2.0/profileprivate.h
+++ b/lasso/saml-2.0/profileprivate.h
@@ -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
}
diff --git a/lasso/saml-2.0/provider.c b/lasso/saml-2.0/provider.c
index 5e7f1082..a30250c4 100644
--- a/lasso/saml-2.0/provider.c
+++ b/lasso/saml-2.0/provider.c
@@ -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 const char*
+binding_uri_to_identifier(const char *uri)
+{
+ 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_descriptor(xmlNode *xmlnode, GHashTable *descriptor, LassoProvider *provider)
+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)
{
- char *descriptor_attrs[] = {"AuthnRequestsSigned", "WantAuthnRequestsSigned", NULL};
+ 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;
- }
-
- 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;
+ /* 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 (strcmp((char*)descriptor_node->name, "Organization") == 0) {
- provider->private_data->organization = xmlCopyNode(
- descriptor_node, 1);
- continue;
- }
+ if (checkSaml2MdNode(descriptor_node,
+ LASSO_SAML2_METADATA_ELEMENT_ORGANIZATION)) {
+ lasso_assign_xml_node(pdata->organization, descriptor_node); }
+ descriptor_node = xmlSecGetNextElementNode(descriptor_node->next);
}
-
-
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 {
diff --git a/lasso/saml-2.0/providerprivate.h b/lasso/saml-2.0/providerprivate.h
index 5c08fe5c..2c217ab5 100644
--- a/lasso/saml-2.0/providerprivate.h
+++ b/lasso/saml-2.0/providerprivate.h
@@ -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
}
diff --git a/lasso/xml/saml-2.0/saml2_strings.h b/lasso/xml/saml-2.0/saml2_strings.h
index f4f0470d..00443d62 100644
--- a/lasso/xml/saml-2.0/saml2_strings.h
+++ b/lasso/xml/saml-2.0/saml2_strings.h
@@ -117,6 +117,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:
*
* URI for URL-Encoding of kind DEFLATE (compress message content before encoding in the URI).
diff --git a/lasso/xml/saml-2.0/saml2_xsd.h b/lasso/xml/saml-2.0/saml2_xsd.h
index 365a4955..d9b9b7cc 100644
--- a/lasso/xml/saml-2.0/saml2_xsd.h
+++ b/lasso/xml/saml-2.0/saml2_xsd.h
@@ -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"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 62ee098c..2d1f6f4a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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 \
diff --git a/tests/assertion_query_saml2.c b/tests/assertion_query_saml2.c
new file mode 100644
index 00000000..12e4b345
--- /dev/null
+++ b/tests/assertion_query_saml2.c
@@ -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;
+}
diff --git a/tests/metadata_tests.c b/tests/metadata_tests.c
index 6daf31f0..c6653121 100644
--- a/tests/metadata_tests.c
+++ b/tests/metadata_tests.c
@@ -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;
}
diff --git a/tests/tests.c b/tests/tests.c
index 806a6097..5217bbb8 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -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