[core] multiple decryption keys support
This commit complements the support for multiple signing certificate support in the metadata files. The use-case is still key roll-over. The structure LassoServerPrivateData was changed to accomodate multiple decryption keys, and so: xmlSecKey *encryption_private_key became: GList *encryption_private_keys All uses of this key were replaced by a loop over this list, terminating with the first key to be able to decrypt the content. The private key passed to lasso_server_new() or lasso_server_new_from_buffers() is first added to the list of decryption keys. Any other call to lasso_server_set_encryption_private_key_with_password() or lasso_server_set_encryption_private_key() will add a new key to the list.
This commit is contained in:
parent
055b405387
commit
5192cdf7a0
|
@ -384,12 +384,13 @@ lasso_login_build_assertion(LassoLogin *login,
|
|||
/* Encrypt NameID */
|
||||
provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
|
||||
ss = LASSO_SAML_SUBJECT_STATEMENT_ABSTRACT(as);
|
||||
if (provider && provider->private_data->encryption_mode & LASSO_ENCRYPTION_MODE_NAMEID
|
||||
&& lasso_provider_get_encryption_public_key(provider) != NULL) {
|
||||
if (provider
|
||||
&& (lasso_provider_get_encryption_mode(provider) & LASSO_ENCRYPTION_MODE_NAMEID)) {
|
||||
encrypted_element = LASSO_SAML2_ENCRYPTED_ELEMENT(lasso_node_encrypt(
|
||||
LASSO_NODE(ss->Subject->NameIdentifier),
|
||||
lasso_provider_get_encryption_public_key(provider),
|
||||
provider->private_data->encryption_sym_key_type, provider->ProviderID));
|
||||
LASSO_NODE(ss->Subject->NameIdentifier),
|
||||
lasso_provider_get_encryption_public_key(provider),
|
||||
lasso_provider_get_encryption_sym_key_type(provider),
|
||||
provider->ProviderID));
|
||||
if (encrypted_element != NULL) {
|
||||
lasso_assign_new_gobject(ss->Subject->EncryptedNameIdentifier, encrypted_element);
|
||||
lasso_release_gobject(ss->Subject->NameIdentifier);
|
||||
|
|
|
@ -548,16 +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;
|
||||
GList *keys;
|
||||
|
||||
if (provider->private_data->encryption_public_keys) {
|
||||
return provider->private_data->encryption_public_keys->data;
|
||||
keys = provider->private_data->encryption_public_keys;
|
||||
/* encrypt using the first given key, multiple encryption key in the metadata is generally
|
||||
* useless. roll-over of the encryption key is done mainly at the receiving side, by trying
|
||||
* to decipher using the two private keys, the old and the new. */
|
||||
if (keys && keys->data) {
|
||||
return (xmlSecKey*)keys->data;
|
||||
}
|
||||
public_keys = lasso_provider_get_public_keys(provider);
|
||||
if (! public_keys) {
|
||||
return NULL;
|
||||
}
|
||||
return (xmlSecKey*)public_keys->data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -859,9 +859,7 @@ dispose(GObject *object)
|
|||
provider->private_data->encryption_public_key_str = NULL;
|
||||
}
|
||||
|
||||
if (provider->private_data->encryption_public_keys) {
|
||||
lasso_release_list_of_sec_key(provider->private_data->encryption_public_keys);
|
||||
}
|
||||
lasso_release_list_of_sec_key(provider->private_data->encryption_public_keys);
|
||||
|
||||
lasso_release(provider->private_data->affiliation_id);
|
||||
provider->private_data->affiliation_id = NULL;
|
||||
|
@ -1289,8 +1287,8 @@ lasso_provider_load_public_key(LassoProvider *provider, LassoPublicKeyType publi
|
|||
list_of_sec_key);
|
||||
break;
|
||||
case LASSO_PUBLIC_KEY_ENCRYPTION:
|
||||
lasso_transfer_full(provider->private_data->encryption_public_keys,
|
||||
keys, list_of_sec_key);
|
||||
lasso_transfer_full(provider->private_data->encryption_public_keys, keys,
|
||||
list_of_sec_key);
|
||||
break;
|
||||
default:
|
||||
lasso_release_list_of_sec_key(keys);
|
||||
|
|
|
@ -182,10 +182,7 @@ lasso_server_set_encryption_private_key_with_password(LassoServer *server,
|
|||
if (! key || ! (xmlSecKeyGetType(key) & xmlSecKeyDataTypePrivate)) {
|
||||
return LASSO_SERVER_ERROR_SET_ENCRYPTION_PRIVATE_KEY_FAILED;
|
||||
}
|
||||
lasso_release_sec_key(server->private_data->encryption_private_key);
|
||||
server->private_data->encryption_private_key = key;
|
||||
} else {
|
||||
lasso_release_sec_key(server->private_data->encryption_private_key);
|
||||
lasso_list_add_new_sec_key(server->private_data->encryption_private_keys, key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -289,8 +286,8 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
|||
rc = parent_class->init_from_xml(node, xmlnode);
|
||||
|
||||
if (server->private_key) {
|
||||
server->private_data->encryption_private_key =
|
||||
lasso_xmlsec_load_private_key(server->private_key, server->private_key_password);
|
||||
lasso_server_set_encryption_private_key_with_password(server, server->private_key,
|
||||
server->private_key_password);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -481,7 +478,7 @@ dispose(GObject *object)
|
|||
}
|
||||
server->private_data->dispose_has_run = TRUE;
|
||||
|
||||
lasso_release_sec_key(server->private_data->encryption_private_key);
|
||||
lasso_release_list_of_sec_key(server->private_data->encryption_private_keys);
|
||||
|
||||
lasso_release_list_of_gobjects(server->private_data->svc_metadatas);
|
||||
|
||||
|
@ -523,7 +520,7 @@ instance_init(LassoServer *server)
|
|||
{
|
||||
server->private_data = g_new0(LassoServerPrivate, 1);
|
||||
server->private_data->dispose_has_run = FALSE;
|
||||
server->private_data->encryption_private_key = NULL;
|
||||
server->private_data->encryption_private_keys = NULL;
|
||||
server->private_data->svc_metadatas = NULL;
|
||||
|
||||
server->providers = g_hash_table_new_full(
|
||||
|
@ -610,7 +607,7 @@ lasso_server_new(const gchar *metadata,
|
|||
if (lasso_provider_load_metadata(LASSO_PROVIDER(server), metadata) == FALSE) {
|
||||
message(G_LOG_LEVEL_CRITICAL,
|
||||
"Failed to load metadata from %s.", metadata);
|
||||
lasso_node_destroy(LASSO_NODE(server));
|
||||
lasso_release_gobject(server);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -619,11 +616,11 @@ lasso_server_new(const gchar *metadata,
|
|||
if (private_key) {
|
||||
lasso_assign_string(server->private_key, private_key);
|
||||
lasso_assign_string(server->private_key_password, private_key_password);
|
||||
server->private_data->encryption_private_key = lasso_xmlsec_load_private_key(private_key,
|
||||
private_key_password);
|
||||
if (! server->private_data->encryption_private_key) {
|
||||
if (lasso_server_set_encryption_private_key_with_password(server, private_key,
|
||||
private_key_password) != 0) {
|
||||
message(G_LOG_LEVEL_WARNING, "Cannot load the private key");
|
||||
lasso_release_gobject(server);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
lasso_provider_load_public_key(&server->parent, LASSO_PUBLIC_KEY_SIGNING);
|
||||
|
@ -657,7 +654,7 @@ lasso_server_new_from_buffers(const char *metadata, const char *private_key_cont
|
|||
if (lasso_provider_load_metadata_from_buffer(LASSO_PROVIDER(server), metadata) == FALSE) {
|
||||
message(G_LOG_LEVEL_CRITICAL,
|
||||
"Failed to load metadata from preloaded buffer");
|
||||
lasso_node_destroy(LASSO_NODE(server));
|
||||
lasso_release_gobject(server);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -665,12 +662,12 @@ lasso_server_new_from_buffers(const char *metadata, const char *private_key_cont
|
|||
if (private_key_content) {
|
||||
lasso_assign_string(server->private_key, private_key_content);
|
||||
lasso_assign_string(server->private_key_password, private_key_password);
|
||||
server->private_data->encryption_private_key =
|
||||
lasso_xmlsec_load_private_key_from_buffer(private_key_content,
|
||||
strlen(private_key_content), private_key_password);
|
||||
if (! server->private_data->encryption_private_key) {
|
||||
|
||||
if (lasso_server_set_encryption_private_key_with_password(server, private_key_content,
|
||||
private_key_password) != 0) {
|
||||
message(G_LOG_LEVEL_WARNING, "Cannot load the private key");
|
||||
lasso_release_gobject(server);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
lasso_provider_load_public_key(&server->parent, LASSO_PUBLIC_KEY_SIGNING);
|
||||
|
@ -731,14 +728,14 @@ lasso_server_get_private_key(LassoServer *server)
|
|||
}
|
||||
|
||||
/**
|
||||
* lasso_server_get_encryption_private_key:
|
||||
* lasso_server_get_encryption_private_keys:
|
||||
* @server: a #LassoServer object
|
||||
*
|
||||
* Return:(transfer none): a xmlSecKey object, it is owned by the #LassoServer object, so do not
|
||||
* Return:(transfer none)(element-type xmlSecKeyPtr): a GList of xmlSecKey object, it is owned by the #LassoServer object, so do not
|
||||
* free it.
|
||||
*/
|
||||
xmlSecKey*
|
||||
lasso_server_get_encryption_private_key(LassoServer *server)
|
||||
GList*
|
||||
lasso_server_get_encryption_private_keys(LassoServer *server)
|
||||
{
|
||||
if (! LASSO_IS_SERVER(server))
|
||||
return NULL;
|
||||
|
@ -746,7 +743,7 @@ lasso_server_get_encryption_private_key(LassoServer *server)
|
|||
if (! server->private_data)
|
||||
return NULL;
|
||||
|
||||
return server->private_data->encryption_private_key;
|
||||
return server->private_data->encryption_private_keys;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,7 +32,7 @@ extern "C" {
|
|||
struct _LassoServerPrivate
|
||||
{
|
||||
gboolean dispose_has_run;
|
||||
xmlSecKey *encryption_private_key;
|
||||
GList *encryption_private_keys;
|
||||
GList *svc_metadatas;
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,7 @@ gchar* lasso_server_get_first_providerID(LassoServer *server);
|
|||
gchar* lasso_server_get_first_providerID_by_role(const LassoServer *server, LassoProviderRole role);
|
||||
gchar* lasso_server_get_providerID_from_hash(LassoServer *server, gchar *b64_hash);
|
||||
xmlSecKey* lasso_server_get_private_key(LassoServer *server);
|
||||
xmlSecKey* lasso_server_get_encryption_private_key(LassoServer *server);
|
||||
GList* lasso_server_get_encryption_private_keys(LassoServer *server);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1160,16 +1160,16 @@ _lasso_check_assertion_issuer(LassoSaml2Assertion *assertion, const gchar *provi
|
|||
static gint
|
||||
_lasso_saml20_login_decrypt_assertion(LassoLogin *login, LassoSamlp2Response *samlp2_response)
|
||||
{
|
||||
xmlSecKey *encryption_private_key;
|
||||
GList *it;
|
||||
GList *encryption_private_keys = NULL;
|
||||
GList *it = NULL;
|
||||
gboolean at_least_one_decryption_failture = FALSE;
|
||||
gboolean at_least_one_malformed_element = FALSE;
|
||||
|
||||
if (! samlp2_response->EncryptedAssertion)
|
||||
return 0; /* nothing to do */
|
||||
|
||||
encryption_private_key = lasso_server_get_encryption_private_key(login->parent.server);
|
||||
if (! encryption_private_key) {
|
||||
encryption_private_keys = lasso_server_get_encryption_private_keys(login->parent.server);
|
||||
if (! encryption_private_keys) {
|
||||
message(G_LOG_LEVEL_WARNING, "Missing private encryption key, cannot decrypt assertions.");
|
||||
return LASSO_DS_ERROR_DECRYPTION_FAILED_MISSING_PRIVATE_KEY;
|
||||
}
|
||||
|
@ -1185,7 +1185,14 @@ _lasso_saml20_login_decrypt_assertion(LassoLogin *login, LassoSamlp2Response *sa
|
|||
continue;
|
||||
}
|
||||
encrypted_assertion = (LassoSaml2EncryptedElement*)it->data;
|
||||
rc1 = lasso_saml2_encrypted_element_decrypt(encrypted_assertion, encryption_private_key, (LassoNode**)&assertion);
|
||||
lasso_foreach_full_begin(xmlSecKey*, encryption_private_key, it,
|
||||
encryption_private_keys)
|
||||
{
|
||||
rc1 = lasso_saml2_encrypted_element_decrypt(encrypted_assertion, encryption_private_key, (LassoNode**)&assertion);
|
||||
if (rc1 == 0)
|
||||
break;
|
||||
}
|
||||
lasso_foreach_full_end();
|
||||
|
||||
if (rc1) {
|
||||
message(G_LOG_LEVEL_WARNING, "Could not decrypt an assertion: %s", lasso_strerror(rc1));
|
||||
|
|
|
@ -506,10 +506,23 @@ lasso_saml20_profile_set_session_from_dump_decrypt(
|
|||
assertion->Subject->EncryptedID->original_data);
|
||||
lasso_release_gobject(assertion->Subject->EncryptedID);
|
||||
} else { /* decrypt */
|
||||
int rc = 0;
|
||||
rc = lasso_saml2_encrypted_element_decrypt(assertion->Subject->EncryptedID,
|
||||
lasso_server_get_encryption_private_key(profile->server),
|
||||
(LassoNode**) &assertion->Subject->NameID);
|
||||
int rc;
|
||||
GList *encryption_private_keys =
|
||||
lasso_server_get_encryption_private_keys(profile->server);
|
||||
|
||||
rc = LASSO_PROFILE_ERROR_MISSING_ENCRYPTION_PRIVATE_KEY;
|
||||
lasso_foreach_full_begin(xmlSecKey*, encryption_private_key, it,
|
||||
encryption_private_keys);
|
||||
{
|
||||
rc = lasso_saml2_encrypted_element_decrypt(
|
||||
assertion->Subject->EncryptedID,
|
||||
encryption_private_key,
|
||||
(LassoNode**)&assertion->Subject->NameID);
|
||||
if (rc == 0)
|
||||
break;
|
||||
}
|
||||
lasso_foreach_full_end();
|
||||
|
||||
if (rc == 0) {
|
||||
lasso_release_gobject(assertion->Subject->EncryptedID);
|
||||
} else {
|
||||
|
@ -560,7 +573,6 @@ lasso_saml20_profile_process_name_identifier_decryption(LassoProfile *profile,
|
|||
LassoSaml2NameID **name_id,
|
||||
LassoSaml2EncryptedElement **encrypted_id)
|
||||
{
|
||||
xmlSecKey *encryption_private_key = NULL;
|
||||
int rc = 0;
|
||||
|
||||
lasso_bad_param(PROFILE, profile);
|
||||
|
@ -568,15 +580,20 @@ lasso_saml20_profile_process_name_identifier_decryption(LassoProfile *profile,
|
|||
lasso_null_param(encrypted_id);
|
||||
|
||||
if (*name_id == NULL && *encrypted_id != NULL) {
|
||||
encryption_private_key = profile->server->private_data->encryption_private_key;
|
||||
if (! LASSO_IS_SAML2_ENCRYPTED_ELEMENT(*encrypted_id)) {
|
||||
return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
|
||||
}
|
||||
if (encrypted_id != NULL && encryption_private_key == NULL) {
|
||||
return LASSO_PROFILE_ERROR_MISSING_ENCRYPTION_PRIVATE_KEY;
|
||||
rc = LASSO_PROFILE_ERROR_MISSING_ENCRYPTION_PRIVATE_KEY;
|
||||
lasso_foreach_full_begin(xmlSecKey*, encryption_private_key, it,
|
||||
lasso_server_get_encryption_private_keys(profile->server));
|
||||
{
|
||||
rc = lasso_saml2_encrypted_element_decrypt(*encrypted_id, encryption_private_key,
|
||||
&profile->nameIdentifier);
|
||||
if (rc == 0)
|
||||
break;
|
||||
}
|
||||
rc = lasso_saml2_encrypted_element_decrypt(*encrypted_id, encryption_private_key,
|
||||
&profile->nameIdentifier);
|
||||
lasso_foreach_full_end();
|
||||
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
if (! LASSO_IS_SAML2_NAME_ID(profile->nameIdentifier)) {
|
||||
|
|
|
@ -776,8 +776,22 @@ int
|
|||
lasso_saml2_encrypted_element_server_decrypt(LassoSaml2EncryptedElement* encrypted_element, LassoServer *server, LassoNode** decrypted_node)
|
||||
{
|
||||
lasso_bad_param(SERVER, server);
|
||||
int rc = 0;
|
||||
GList *encryption_private_keys;
|
||||
|
||||
return lasso_saml2_encrypted_element_decrypt(encrypted_element, lasso_server_get_encryption_private_key(server), decrypted_node);
|
||||
encryption_private_keys = lasso_server_get_encryption_private_keys(server);
|
||||
if (! encryption_private_keys) {
|
||||
return LASSO_PROFILE_ERROR_MISSING_ENCRYPTION_PRIVATE_KEY;
|
||||
}
|
||||
lasso_foreach_full_begin(xmlSecKey*, encryption_private_key, it, encryption_private_keys)
|
||||
{
|
||||
rc = lasso_saml2_encrypted_element_decrypt(encrypted_element,
|
||||
encryption_private_key, decrypted_node);
|
||||
if (rc == 0)
|
||||
break;
|
||||
}
|
||||
lasso_foreach_full_end();
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue