diff options
| author | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2011-05-17 11:04:05 +0200 |
|---|---|---|
| committer | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2011-05-19 17:54:16 +0200 |
| commit | e67f2bb6587770d024f740d92356c827a40120bb (patch) | |
| tree | 366f9562f4d31b4121128217e9c80382d0a3aaf7 /lasso | |
| parent | e14652e7a41332f954b72dd2fbc6f9962970e8c3 (diff) | |
| download | lasso-e67f2bb6587770d024f740d92356c827a40120bb.tar.gz lasso-e67f2bb6587770d024f740d92356c827a40120bb.tar.xz lasso-e67f2bb6587770d024f740d92356c827a40120bb.zip | |
[core] first try at multiple signing keys support
The idea was to replace every use of an xmlSecKey* by a loop over a
GList* of xmlSecKey*.
- In the structure LassoProviderPrivate changed
xmlSecKey*public_key -> GList* signing_public_keys
xmlNode*signing_key_descriptor -> GList* signing_key_descriptors.
- Renamed lasso_provider_try_loading_public_key to
lasso_provider_try_loading_public_keys and chaned its signature
accordingly
- Renamed lasso_provider_get_public_key to
lasso_provider_get_public_keys and changed the signature accordingly.
- Changed lasso_provider_get_encryption_public_key to return the first
signing key from the list as a temporary work around. Multiple
encryption keys will be supported later.
- Changed lasso_provider_load_public_key to load keys from the passed
file on the LassoProvider constructor, from every key descriptors
found for signing and eventually from the key descriptor marked for
encryption.
- Every failure to load from a file or an XML KeyInfo descriptor are
noew reported as warning.
- Query signature checking was completely moved to
lasso_provider_verify_query_signature and
lasso_provider_verify_signature now calls it.
- lasso_provider_verify_signature is now using lasso_verify_signature
from the xml/tools.o module.
- lasso_provider_verify_single_signature was modified to support
multiple signing keys.
Diffstat (limited to 'lasso')
| -rw-r--r-- | lasso/id-ff/provider.c | 253 | ||||
| -rw-r--r-- | lasso/id-ff/providerprivate.h | 6 |
2 files changed, 143 insertions, 116 deletions
diff --git a/lasso/id-ff/provider.c b/lasso/id-ff/provider.c index 163d73bc..28c9e1d2 100644 --- a/lasso/id-ff/provider.c +++ b/lasso/id-ff/provider.c @@ -97,15 +97,15 @@ void _lasso_provider_add_metadata_value_for_role(LassoProvider *provider, typedef int LassoProviderRoleIndex; static int -lasso_provider_try_loading_public_key(LassoProvider *provider, xmlSecKeyPtr *public_key, gboolean mandatory) { - if (provider->public_key || provider->private_data->signing_key_descriptor) { - *public_key = lasso_provider_get_public_key(provider); - if (*public_key == NULL) +lasso_provider_try_loading_public_keys(LassoProvider *provider, GList **public_keys, gboolean mandatory) { + if (provider->public_key || provider->private_data->signing_key_descriptors) { + *public_keys = lasso_provider_get_public_keys(provider); + if (*public_keys == NULL) return LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED; } else { - *public_key = NULL; + *public_keys = NULL; } - if (*public_key == NULL && mandatory) + if (*public_keys == NULL && mandatory) return LASSO_PROVIDER_ERROR_MISSING_PUBLIC_KEY; return 0; } @@ -521,18 +521,18 @@ static struct XmlSnippet schema_snippets[] = { static LassoNodeClass *parent_class = NULL; /** - * lasso_provider_get_public_key: + * lasso_provider_get_public_keys: * @provider: a #LassoProvider object * - * Return the public key associated with this provider. + * Return the public keys associated with this provider. * * Return value: an #xmlSecKey object. */ -xmlSecKey* -lasso_provider_get_public_key(const LassoProvider *provider) +GList* +lasso_provider_get_public_keys(const LassoProvider *provider) { g_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL); - return provider->private_data->public_key; + return provider->private_data->signing_public_keys; } /** @@ -548,11 +548,16 @@ xmlSecKey* lasso_provider_get_encryption_public_key(const LassoProvider *provider) { g_return_val_if_fail(LASSO_IS_PROVIDER(provider), NULL); + GList *public_keys; if (provider->private_data->encryption_public_key) { return provider->private_data->encryption_public_key; } - return lasso_provider_get_public_key(provider); + public_keys = lasso_provider_get_public_keys(provider); + if (! public_keys) { + return NULL; + } + return (xmlSecKey*)public_keys->data; } static void @@ -647,7 +652,8 @@ _lasso_provider_load_key_descriptor(LassoProvider *provider, xmlNode *key_descri private_data = provider->private_data; use = xmlGetProp(key_descriptor, (xmlChar*)"use"); if (use == NULL || lasso_strisequal((char *)use,"signing")) { - lasso_assign_xml_node(private_data->signing_key_descriptor, key_descriptor); + lasso_list_add_xml_node(private_data->signing_key_descriptors, + key_descriptor); } if (use == NULL || strcmp((char*)use, "encryption") == 0) { lasso_assign_xml_node(private_data->encryption_key_descriptor, key_descriptor); @@ -835,14 +841,12 @@ dispose(GObject *object) provider->private_data->default_assertion_consumer = NULL; } - if (provider->private_data->public_key) { - xmlSecKeyDestroy(provider->private_data->public_key); - provider->private_data->public_key = NULL; + if (provider->private_data->signing_public_keys) { + lasso_release_list_of_sec_key(provider->private_data->signing_public_keys); } - if (provider->private_data->signing_key_descriptor) { - xmlFreeNode(provider->private_data->signing_key_descriptor); - provider->private_data->signing_key_descriptor = NULL; + if (provider->private_data->signing_key_descriptors) { + lasso_release_list_of_xml_node(provider->private_data->signing_key_descriptors); } if (provider->private_data->encryption_key_descriptor) { @@ -898,8 +902,8 @@ instance_init(LassoProvider *provider) provider->private_data->affiliation_id = NULL; provider->private_data->affiliation_owner_id = NULL; provider->private_data->organization = NULL; - provider->private_data->public_key = NULL; - provider->private_data->signing_key_descriptor = NULL; + provider->private_data->signing_public_keys = NULL; + provider->private_data->signing_key_descriptors = NULL; provider->private_data->encryption_key_descriptor = NULL; provider->private_data->encryption_public_key_str = NULL; provider->private_data->encryption_public_key = NULL; @@ -1230,44 +1234,72 @@ gboolean lasso_provider_load_public_key(LassoProvider *provider, LassoPublicKeyType public_key_type) { gchar *public_key = NULL; + GList *keys_descriptors = NULL; xmlNode *key_descriptor = NULL; - xmlSecKey *pub_key = NULL; + GList *keys = NULL; g_return_val_if_fail(LASSO_IS_PROVIDER(provider), FALSE); if (public_key_type == LASSO_PUBLIC_KEY_SIGNING) { public_key = provider->public_key; - key_descriptor = provider->private_data->signing_key_descriptor; + keys_descriptors = provider->private_data->signing_key_descriptors; } else { key_descriptor = provider->private_data->encryption_key_descriptor; } - if (public_key == NULL && key_descriptor == NULL) { + if (public_key == NULL && keys_descriptors == NULL && key_descriptor == NULL) { return TRUE; } - if (public_key == NULL) { - pub_key = lasso_xmlsec_load_key_info(key_descriptor); - if (! pub_key) { + if (public_key != NULL) { + xmlSecKey *key = lasso_xmlsec_load_private_key(public_key, NULL); + if (key) { + lasso_list_add_new_sec_key(keys, key); + } else { + message(G_LOG_LEVEL_WARNING, "Could not read public key from file %s", public_key); + } + } + if (key_descriptor) { + xmlSecKey *key = lasso_xmlsec_load_key_info(key_descriptor); + if (key) { + lasso_list_add_new_sec_key(keys, key); + } else { message(G_LOG_LEVEL_WARNING, "Could not read KeyInfo from %s KeyDescriptor", public_key_type == LASSO_PUBLIC_KEY_SIGNING ? "signing" : "encryption"); } - } else { - pub_key = lasso_xmlsec_load_private_key(public_key, NULL); } - if (pub_key) { + if (keys_descriptors) { + lasso_foreach_full_begin(xmlNode*, key_descriptor, it, keys_descriptors); + { + xmlSecKey *key = lasso_xmlsec_load_key_info(key_descriptor); + if (key) { + lasso_list_add_new_sec_key(keys, key); + } else { + message(G_LOG_LEVEL_WARNING, "Could not read KeyInfo from %s " + "KeyDescriptor", + public_key_type == LASSO_PUBLIC_KEY_SIGNING ? "signing" : + "encryption"); + } + } + lasso_foreach_full_end(); + } + + if (keys) { switch (public_key_type) { case LASSO_PUBLIC_KEY_SIGNING: - lasso_assign_new_sec_key(provider->private_data->public_key, pub_key); + lasso_transfer_full(provider->private_data->signing_public_keys, keys, + list_of_sec_key); break; case LASSO_PUBLIC_KEY_ENCRYPTION: - lasso_assign_new_sec_key(provider->private_data->encryption_public_key, pub_key); + lasso_assign_new_sec_key(provider->private_data->encryption_public_key, + (xmlSecKey*)keys->data); break; default: - xmlSecKeyDestroy(pub_key); + lasso_release_list_of_sec_key(keys); } + return TRUE; + } else { + return FALSE; } - - return (pub_key != NULL); } @@ -1297,9 +1329,10 @@ lasso_provider_verify_saml_signature(LassoProvider *provider, { const char *id_attribute_name = NULL; const xmlChar *node_ns = NULL; - xmlSecKey *public_key = NULL; + GList *public_keys = NULL; xmlSecKeysMngr *keys_manager = NULL; int rc = 0; + int signature_rc = 0; lasso_bad_param(PROVIDER, provider); lasso_null_param(signed_node); @@ -1320,9 +1353,17 @@ lasso_provider_verify_saml_signature(LassoProvider *provider, goto_cleanup_if_fail_with_rc(id_attribute_name, LASSO_PARAM_ERROR_INVALID_VALUE); /* Get provider credentials */ lasso_check_good_rc(lasso_provider_try_loading_ca_cert_chain(provider, &keys_manager)); - lasso_check_good_rc(lasso_provider_try_loading_public_key(provider, &public_key, keys_manager == NULL)); - rc = lasso_verify_signature(signed_node, doc, id_attribute_name, keys_manager, public_key, - NO_OPTION, NULL); + lasso_check_good_rc(lasso_provider_try_loading_public_keys(provider, &public_keys, keys_manager == NULL)); + lasso_foreach_full_begin(xmlSecKey*, public_key, it, public_keys); + { + signature_rc = lasso_verify_signature(signed_node, doc, id_attribute_name, keys_manager, public_key, + NO_OPTION, NULL); + if (signature_rc == 0) { + break; + } + } + lasso_foreach_full_end(); + rc = signature_rc; cleanup: lasso_release_key_manager(keys_manager); return rc; @@ -1336,45 +1377,35 @@ lasso_provider_verify_signature(LassoProvider *provider, * reflection about code reuse is under way... */ xmlDoc *doc = NULL; - xmlNode *xmlnode = NULL, *sign = NULL, *x509data = NULL; + xmlNode *xmlnode = NULL; xmlSecKeysMngr *keys_mngr = NULL; - xmlSecDSigCtx *dsigCtx = NULL; int rc = 0; + int signature_rc = 0; xmlXPathContext *xpathCtx = NULL; xmlXPathObject *xpathObj = NULL; - xmlSecKey *public_key = NULL; + GList *public_keys = NULL; g_return_val_if_fail(LASSO_IS_PROVIDER(provider), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); if (lasso_flag_verify_signature == FALSE) return 0; - if (message == NULL) return LASSO_PROFILE_ERROR_INVALID_MSG; if (format == LASSO_MESSAGE_FORMAT_ERROR) return LASSO_PROFILE_ERROR_INVALID_MSG; + if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) return LASSO_PROFILE_ERROR_INVALID_MSG; if (format == LASSO_MESSAGE_FORMAT_QUERY) { - lasso_check_good_rc(lasso_provider_try_loading_public_key(provider, &public_key, TRUE)); - - switch (lasso_provider_get_protocol_conformance(provider)) { - case LASSO_PROTOCOL_LIBERTY_1_0: - case LASSO_PROTOCOL_LIBERTY_1_1: - case LASSO_PROTOCOL_LIBERTY_1_2: - return lasso_query_verify_signature(message, public_key); - case LASSO_PROTOCOL_SAML_2_0: - return lasso_saml2_query_verify_signature(message, public_key); - default: - return LASSO_PROFILE_ERROR_CANNOT_VERIFY_SIGNATURE; - } + return lasso_provider_verify_query_signature(provider, message); } lasso_check_good_rc(lasso_provider_try_loading_ca_cert_chain(provider, &keys_mngr)); /* public key is mandatory if no keys manager is present */ - lasso_check_good_rc(lasso_provider_try_loading_public_key(provider, &public_key, keys_mngr == NULL)); + lasso_check_good_rc(lasso_provider_try_loading_public_keys(provider, &public_keys, + keys_mngr == NULL)); if (format == LASSO_MESSAGE_FORMAT_BASE64) { int len; @@ -1402,64 +1433,20 @@ lasso_provider_verify_signature(LassoProvider *provider, } - sign = NULL; - for (sign = xmlnode->children; sign; sign = sign->next) { - if (strcmp((char*)sign->name, "Signature") == 0) + lasso_foreach_full_begin(xmlSecKeyPtr, public_key, it, public_keys); + { + signature_rc = lasso_verify_signature(xmlnode, doc, id_attr_name, + keys_mngr, public_key, NO_OPTION, NULL); + if (signature_rc == 0) { break; - } - - /* If no signature was found, look for one in assertion */ - if (sign == NULL) { - for (sign = xmlnode->children; sign; sign = sign->next) { - if (strcmp((char*)sign->name, "Assertion") == 0) - break; - } - if (sign != NULL) { - xmlnode = sign; - for (sign = xmlnode->children; sign; sign = sign->next) { - if (strcmp((char*)sign->name, "Signature") == 0) - break; - } } } - - goto_cleanup_if_fail_with_rc (sign != NULL, LASSO_DS_ERROR_SIGNATURE_NOT_FOUND); - - if (id_attr_name) { - xmlChar *id_value = xmlGetProp(xmlnode, (xmlChar*)id_attr_name); - xmlAttr *id_attr = xmlHasProp(xmlnode, (xmlChar*)id_attr_name); - if (id_value != NULL) { - xmlAddID(NULL, doc, id_value, id_attr); - xmlFree(id_value); - } - } - - x509data = xmlSecFindNode(xmlnode, xmlSecNodeX509Data, xmlSecDSigNs); - if (x509data == NULL) { /* no need for a keys mngr if there is no X509 data */ - lasso_release_key_manager(keys_mngr); - } - - dsigCtx = xmlSecDSigCtxCreate(keys_mngr); - if (public_key) { - dsigCtx->signKey = xmlSecKeyDuplicate(public_key); - } - - goto_cleanup_if_fail_with_rc (xmlSecDSigCtxVerify(dsigCtx, sign) >= 0, - LASSO_DS_ERROR_SIGNATURE_VERIFICATION_FAILED); - - if (dsigCtx->status != xmlSecDSigStatusSucceeded) { - rc = LASSO_DS_ERROR_INVALID_SIGNATURE; - goto cleanup; - } + lasso_foreach_full_end(); + rc = signature_rc; cleanup: lasso_release_key_manager(keys_mngr); - lasso_release_signature_context(dsigCtx); - if (xpathCtx) - xmlXPathFreeContext(xpathCtx); - if (xpathObj) - xmlXPathFreeObject(xpathObj); - lasso_release_doc(doc); + lasso_release_xpath_job(xpathObj, xpathCtx, doc); return rc; } @@ -1543,7 +1530,40 @@ lasso_provider_get_encryption_sym_key_type(const LassoProvider *provider) int lasso_provider_verify_query_signature(LassoProvider *provider, const char *message) { - return lasso_provider_verify_signature(provider, message, "", LASSO_MESSAGE_FORMAT_QUERY); + int (*check)(const char *, const xmlSecKey *) = NULL; + int rc = 0; + int signature_rc = 0; + GList *public_keys = NULL; + + lasso_bad_param(PROVIDER, provider); + lasso_null_param(message); + + lasso_check_good_rc(lasso_provider_try_loading_public_keys(provider, &public_keys, TRUE)); + + switch (lasso_provider_get_protocol_conformance(provider)) { + case LASSO_PROTOCOL_LIBERTY_1_0: + case LASSO_PROTOCOL_LIBERTY_1_1: + case LASSO_PROTOCOL_LIBERTY_1_2: + check = lasso_query_verify_signature; + break; + case LASSO_PROTOCOL_SAML_2_0: + check = lasso_saml2_query_verify_signature; + break; + default: + return LASSO_PROFILE_ERROR_CANNOT_VERIFY_SIGNATURE; + } + /* Check with all known signing keys... */ + lasso_foreach_full_begin(xmlSecKeyPtr, public_key, it, public_keys); + { + signature_rc = check(message, public_key); + if (signature_rc == 0) { + break; + } + } + lasso_foreach_full_end(); + rc = signature_rc; +cleanup: + return rc; } /** @@ -1606,7 +1626,7 @@ int lasso_provider_verify_single_node_signature (LassoProvider *provider, LassoNode *node, const char *id_attr_name) { xmlNode *xmlnode = NULL; - xmlSecKey *public_key = NULL; + GList *public_keys = NULL; xmlSecKeysMngr *keys_mngr = NULL; int rc = 0; @@ -1615,10 +1635,17 @@ lasso_provider_verify_single_node_signature (LassoProvider *provider, LassoNode return LASSO_DS_ERROR_SIGNATURE_VERIFICATION_FAILED; } lasso_check_good_rc(lasso_provider_try_loading_ca_cert_chain(provider, &keys_mngr)); - lasso_check_good_rc(lasso_provider_try_loading_public_key(provider, &public_key, + lasso_check_good_rc(lasso_provider_try_loading_public_keys(provider, &public_keys, keys_mngr == NULL)); - rc = lasso_verify_signature(xmlnode, NULL, id_attr_name, keys_mngr, public_key, - NO_SINGLE_REFERENCE, NULL); + + lasso_foreach_full_begin(xmlSecKey*, public_key, it, public_keys); + { + rc = lasso_verify_signature(xmlnode, NULL, id_attr_name, keys_mngr, public_key, + NO_SINGLE_REFERENCE, NULL); + if (rc == 0) + break; + } + lasso_foreach_full_end(); cleanup: return rc; } diff --git a/lasso/id-ff/providerprivate.h b/lasso/id-ff/providerprivate.h index 2c8d7139..bd9c46cc 100644 --- a/lasso/id-ff/providerprivate.h +++ b/lasso/id-ff/providerprivate.h @@ -68,8 +68,8 @@ struct _LassoProviderPrivate char *affiliation_owner_id; char *affiliation_id; - xmlSecKey *public_key; - xmlNode *signing_key_descriptor; + GList *signing_public_keys; + GList *signing_key_descriptors; xmlNode *encryption_key_descriptor; char *encryption_public_key_str; xmlSecKey *encryption_public_key; @@ -86,7 +86,7 @@ int lasso_provider_verify_signature(LassoProvider *provider, const char *message, const char *id_attr_name, LassoMessageFormat format); gboolean lasso_provider_load_public_key(LassoProvider *provider, LassoPublicKeyType public_key_type); -xmlSecKey* lasso_provider_get_public_key(const LassoProvider *provider); +GList* lasso_provider_get_public_keys(const LassoProvider *provider); xmlSecKey* lasso_provider_get_encryption_public_key(const LassoProvider *provider); LassoEncryptionSymKeyType lasso_provider_get_encryption_sym_key_type(const LassoProvider* provider); int lasso_provider_verify_saml_signature(LassoProvider *provider, xmlNode *signed_node, xmlDoc *doc); |
