summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2011-04-04 11:50:45 +0200
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2011-04-04 18:34:06 +0200
commitcad3d305a90870abd9e48d8bd8370632fdc89941 (patch)
treef28aa4729d8c59930bb236bc0d8d5bc412919f1c
parent31a623aeeeee3174590aa984903abf46644bcc79 (diff)
downloadlasso-cad3d305a90870abd9e48d8bd8370632fdc89941.tar.gz
lasso-cad3d305a90870abd9e48d8bd8370632fdc89941.tar.xz
lasso-cad3d305a90870abd9e48d8bd8370632fdc89941.zip
[core] make lasso_server_load_metadata load any metadata file
The new code can load metadata file with a EntityDescriptor root node, and with nested EntitiesDescriptor. Idea and prototype by Olav Morken.
-rw-r--r--lasso/errors.c2
-rw-r--r--lasso/errors.h9
-rw-r--r--lasso/id-ff/server.c3
-rw-r--r--lasso/saml-2.0/server.c130
-rw-r--r--lasso/saml-2.0/serverprivate.h2
5 files changed, 110 insertions, 36 deletions
diff --git a/lasso/errors.c b/lasso/errors.c
index f3e829e0..69556c10 100644
--- a/lasso/errors.c
+++ b/lasso/errors.c
@@ -301,6 +301,8 @@ lasso_strerror(int error_code)
return "Failed to add new provider (protocol mismatch). It means that you tried to add a provider supporting a protocol imcompatible with the protocol declared for your #LassoServer, for example metadata for ID-FF 1.2 with metadata for SAML 2.0.";
case LASSO_SERVER_ERROR_INVALID_XML:
return "Parsed XML is invalid.";
+ case LASSO_SERVER_ERROR_NO_PROVIDER_LOADED:
+ return "When loading a metadata file it indicates that no provider could be loaded. It could be because the file is not well formed, or because there is no provider for the role sought.";
case LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND:
return "The identifier of a provider is unknown to #LassoServer. To register a provider in a #LassoServer object, you must use the methods lasso_server_add_provider() or lasso_server_add_provider_from_buffer().";
case LASSO_SERVER_ERROR_SET_ENCRYPTION_PRIVATE_KEY_FAILED:
diff --git a/lasso/errors.h b/lasso/errors.h
index 6dd2b461..1e4b24fa 100644
--- a/lasso/errors.h
+++ b/lasso/errors.h
@@ -263,6 +263,15 @@ LASSO_EXPORT const char* lasso_strerror(int error_code);
* Parsed XML is invalid.
*/
#define LASSO_SERVER_ERROR_INVALID_XML -205
+/**
+ * LASSO_SERVER_ERROR_NO_PROVIDER_LOADED
+ *
+ * When loading a metadata file it indicates that no provider could be loaded.
+ * It could be because the file is not well formed, or because there is no provider for the
+ * role sought.
+ *
+ */
+#define LASSO_SERVER_ERROR_NO_PROVIDER_LOADED 206
/* Single Logout */
/**
diff --git a/lasso/id-ff/server.c b/lasso/id-ff/server.c
index b3ced080..b84d5abe 100644
--- a/lasso/id-ff/server.c
+++ b/lasso/id-ff/server.c
@@ -803,7 +803,8 @@ lasso_server_load_metadata(LassoServer *server, LassoProviderRole role, const gc
EMPTY_URI, &uri_references));
}
if (lasso_strisequal((char*)root->ns->href, LASSO_SAML2_METADATA_HREF)) {
- lasso_check_good_rc(lasso_saml20_server_load_federation(server, role, root, blacklisted_entity_ids, loaded_entity_ids));
+ lasso_check_good_rc(lasso_saml20_server_load_metadata(server, role, root,
+ blacklisted_entity_ids, loaded_entity_ids));
} else {
goto_cleanup_with_rc(LASSO_ERROR_UNIMPLEMENTED);
}
diff --git a/lasso/saml-2.0/server.c b/lasso/saml-2.0/server.c
index cf105b89..ad54e6d6 100644
--- a/lasso/saml-2.0/server.c
+++ b/lasso/saml-2.0/server.c
@@ -102,51 +102,113 @@ _lasso_test_idp_descriptor(xmlNode *node) {
BAD_CAST LASSO_SAML2_METADATA_HREF) != NULL;
}
-lasso_error_t
-lasso_saml20_server_load_federation(LassoServer *server, LassoProviderRole role, xmlNode *root_node, GList *blacklisted_entity_ids, GList **loaded_entity_ids)
+static lasso_error_t
+lasso_saml20_server_load_metadata_entity(LassoServer *server, LassoProviderRole role,
+ xmlNode *entity, GList *blacklisted_entity_ids, GList **loaded_end)
{
- xmlNode *child;
- lasso_error_t rc = 0;
- GList loaded = { .data = NULL, .next = NULL };
- GList *loaded_end = &loaded;
+ LassoProvider *provider = NULL;
- child = xmlSecGetNextElementNode(root_node->children);
- /* first parse the providers... */
- while (child) {
- LassoProvider *provider = NULL;
+ if (role == LASSO_PROVIDER_ROLE_IDP && ! _lasso_test_idp_descriptor(entity)) {
+ return 0;
+ }
+ if (role == LASSO_PROVIDER_ROLE_SP && ! _lasso_test_sp_descriptor(entity)) {
+ return 0;
+ }
- if (! xmlSecCheckNodeName(child,
- BAD_CAST LASSO_SAML2_METADATA_ELEMENT_ENTITY_DESCRIPTOR,
- BAD_CAST LASSO_SAML2_METADATA_HREF)) {
- goto next;
- }
- if (role == LASSO_PROVIDER_ROLE_IDP && ! _lasso_test_idp_descriptor(child)) {
- goto next;
+ provider = lasso_provider_new_from_xmlnode(role, entity);
+ if (provider) {
+ char *name = g_strdup(provider->ProviderID);
+
+ if (g_list_find_custom(blacklisted_entity_ids, name,
+ (GCompareFunc) g_strcmp0)) {
+ lasso_release_gobject(provider);
+ return LASSO_SERVER_ERROR_NO_PROVIDER_LOADED;
}
- if (role == LASSO_PROVIDER_ROLE_SP && ! _lasso_test_sp_descriptor(child)) {
- goto next;
+ if (*loaded_end) {
+ GList *l = *loaded_end;
+ l->next = g_new0(GList, 1);
+ l->next->data = g_strdup(name);
+ *loaded_end = l->next;
}
+ g_hash_table_insert(server->providers, name, provider);
+ return 0;
+ } else {
+ return LASSO_SERVER_ERROR_NO_PROVIDER_LOADED;
+ }
+}
- provider = lasso_provider_new_from_xmlnode(role, child);
- if (provider) {
- char *name = g_strdup(provider->ProviderID);
+static lasso_error_t lasso_saml20_server_load_metadata_child(LassoServer *server,
+ LassoProviderRole role, xmlNode *child, GList *blacklisted_entity_ids,
+ GList **loaded_end);
- if (g_list_find_custom(blacklisted_entity_ids, name,
- (GCompareFunc) g_strcmp0)) {
- lasso_release_gobject(provider);
- goto next;
- }
- if (loaded_entity_ids) {
- loaded_end->next = g_new0(GList, 1);
- loaded_end->next->data = g_strdup(name);
- loaded_end = loaded_end->next;
- }
- g_hash_table_insert(server->providers, name, provider);
+static lasso_error_t
+lasso_saml20_server_load_metadata_entities(LassoServer *server, LassoProviderRole role, xmlNode *entities,
+ GList *blacklisted_entity_ids, GList **loaded_end)
+{
+ xmlNode *child;
+ gboolean at_least_one = FALSE;
+
+ child = xmlSecGetNextElementNode(entities->children);
+ while (child) {
+ lasso_error_t rc = 0;
+
+ rc = lasso_saml20_server_load_metadata_child(server, role, child,
+ blacklisted_entity_ids, loaded_end);
+ if (rc == 0) {
+ at_least_one = TRUE;
}
-next:
child = xmlSecGetNextElementNode(child->next);
}
+ return at_least_one ? 0 : LASSO_SERVER_ERROR_NO_PROVIDER_LOADED;
+}
+
+static lasso_error_t
+lasso_saml20_server_load_metadata_child(LassoServer *server, LassoProviderRole role, xmlNode *child,
+ GList *blacklisted_entity_ids, GList **loaded_end)
+{
+ if (xmlSecCheckNodeName(child,
+ BAD_CAST LASSO_SAML2_METADATA_ELEMENT_ENTITY_DESCRIPTOR,
+ BAD_CAST LASSO_SAML2_METADATA_HREF)) {
+ return lasso_saml20_server_load_metadata_entity(server, role, child,
+ blacklisted_entity_ids, loaded_end);
+ } else if (xmlSecCheckNodeName(child,
+ BAD_CAST LASSO_SAML2_METADATA_ELEMENT_ENTITIES_DESCRIPTOR,
+ BAD_CAST LASSO_SAML2_METADATA_HREF)) {
+ return lasso_saml20_server_load_metadata_entities(server, role, child,
+ blacklisted_entity_ids, loaded_end);
+ }
+ return LASSO_SERVER_ERROR_INVALID_XML;
+}
+
+/**
+ * lasso_saml20_server_load_metadata:
+ * @server: a #LassoServer object
+ * @role: the role of providers to load
+ * @root_node: the root node a SAML 2.0 metadata file
+ * @blacklisted_entity_ids: a list of entity IDs of provider to skip
+ * @loaded_entity_ids: an out parameter to return the list of the loaded providers entity IDs
+ *
+ * Load the SAML 2.0 providers present in the given metadata as pointed to by the @root_node
+ * parameter. If at least one provider is loaded the call is deemed successful.
+ *
+ * Return value: 0 if at least one provider has been loaded, LASSO_SERVER_ERROR_NO_PROVIDER_LOADED
+ * otherwise.
+ */
+lasso_error_t
+lasso_saml20_server_load_metadata(LassoServer *server, LassoProviderRole role, xmlNode *root_node,
+ GList *blacklisted_entity_ids, GList **loaded_entity_ids)
+{
+ lasso_error_t rc = 0;
+ GList loaded = { .data = NULL, .next = NULL };
+ GList *loaded_end = NULL;
+
+ if (loaded_entity_ids) {
+ loaded_end = &loaded;
+ }
+ rc = lasso_saml20_server_load_metadata_child(server, role,
+ root_node, blacklisted_entity_ids, &loaded_end);
if (loaded_entity_ids) {
+ lasso_release_list_of_strings(*loaded_entity_ids);
*loaded_entity_ids = loaded.next;
}
return rc;
diff --git a/lasso/saml-2.0/serverprivate.h b/lasso/saml-2.0/serverprivate.h
index 674ef6b5..08fea735 100644
--- a/lasso/saml-2.0/serverprivate.h
+++ b/lasso/saml-2.0/serverprivate.h
@@ -33,7 +33,7 @@ extern "C" {
#include "../id-ff/server.h"
int lasso_saml20_server_load_affiliation(LassoServer *server, xmlNode *node);
-lasso_error_t lasso_saml20_server_load_federation(LassoServer *server, LassoProviderRole role,
+lasso_error_t lasso_saml20_server_load_metadata(LassoServer *server, LassoProviderRole role,
xmlNode *root_node, GList *blacklisted_entity_ids, GList **loaded_entity_ids);
#ifdef __cplusplus