diff options
| author | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2011-04-04 11:50:45 +0200 |
|---|---|---|
| committer | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2011-04-04 18:34:06 +0200 |
| commit | cad3d305a90870abd9e48d8bd8370632fdc89941 (patch) | |
| tree | f28aa4729d8c59930bb236bc0d8d5bc412919f1c | |
| parent | 31a623aeeeee3174590aa984903abf46644bcc79 (diff) | |
| download | lasso-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.c | 2 | ||||
| -rw-r--r-- | lasso/errors.h | 9 | ||||
| -rw-r--r-- | lasso/id-ff/server.c | 3 | ||||
| -rw-r--r-- | lasso/saml-2.0/server.c | 130 | ||||
| -rw-r--r-- | lasso/saml-2.0/serverprivate.h | 2 |
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 |
