More work on signature validation for SAML 2.0

* lasso/saml-2.0/profile.c:
   in lasso_saml20_profile_process_any_request and
   lasso_saml20_profile_process_any_response do not make signature
   validation failure as call failure, just store the result in
   profile->signature_status and let the upper level functions handle
   what to do with it. also add documentation about those two functions.

 * lasso/saml-2.0/logout.c:
 * lasso/saml-2.0/name_id_management.c:
   handle new signature_status semantic.

 * lasso/saml-2.0/login.c:
   add internal documentation for
   lasso_saml20_login_process_authn_response_msg.
This commit is contained in:
Benjamin Dauvergne 2009-04-27 15:48:53 +00:00
parent cbd9ade936
commit 2a75e87543
4 changed files with 56 additions and 7 deletions

View File

@ -1088,11 +1088,23 @@ lasso_saml20_login_process_paos_response_msg(LassoLogin *login, gchar *msg)
return rc2;
}
/**
* lasso_saml20_login_process_authn_response_msg:
* @login: a #LassoLogin profile object
* @authn_response_msg: a string containg a response msg to an #LassoSaml2AuthnRequest
*
* Parse a response made using binding HTTP-Redirect, HTTP-Post or HTTP-SOAP. If a signature is
* missing on the message object, it accepts signatures coming from the first assertion as a
* sufficient proof. But if the signature verification failed on the message for any other reason
* than a missing Signature node, an error code is returned.
*
* Return value: 0 if succesfull, an error code otherwise.
*/
gint
lasso_saml20_login_process_authn_response_msg(LassoLogin *login, gchar *authn_response_msg)
{
LassoProfile *profile = NULL;
int rc1, rc2;
int rc1, rc2, message_signature_status;
lasso_bad_param(LOGIN, login);
lasso_null_param(authn_response_msg);
@ -1103,9 +1115,14 @@ lasso_saml20_login_process_authn_response_msg(LassoLogin *login, gchar *authn_re
(LassoSamlp2StatusResponse*)lasso_samlp2_response_new(),
authn_response_msg);
message_signature_status = profile->signature_status;
rc2 = lasso_saml20_login_process_response_status_and_assertion(login);
/** The more important signature errors */
if (message_signature_status) {
message(G_LOG_LEVEL_WARNING, "Validation of the AuthnResponse message signature failed: %s", lasso_strerror(message_signature_status));
}
if (profile->signature_status) {
return profile->signature_status;
}

View File

@ -243,6 +243,10 @@ lasso_saml20_logout_process_request_msg(LassoLogout *logout, char *request_msg)
&logout_request->NameID,
&logout_request->EncryptedID);
if (profile->signature_status) {
return profile->signature_status;
}
if (rc1) {
return rc1;
}

View File

@ -146,6 +146,9 @@ lasso_name_id_management_process_request_msg(LassoNameIdManagement *name_id_mana
rc2 = lasso_saml20_profile_process_name_identifier_decryption(profile,
&request->NameID, &request->EncryptedID);
if (profile->signature_status) {
return profile->signature_status;
}
if (rc1)
return rc1;
if (rc2)
@ -291,6 +294,9 @@ lasso_name_id_management_process_response_msg(
if (rc)
goto cleanup;
/* Stop here if signature validation failed. */
goto_cleanup_if_fail_with_rc(profile->signature_status == 0, profile->signature_status);
if (LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->Terminate) {
lasso_identity_remove_federation(profile->identity, profile->remote_providerID);
} else {

View File

@ -489,6 +489,23 @@ cleanup:
return rc;
}
/**
* lasso_saml20_profile_process_any_request:
* @profile: a #LassoProfile object
* @request_node: a #LassoNode object which will be initialized with the content of @request_msg
* @request_msg: a string containing the request message as a SOAP XML message, a query string of
* the content of SAMLRequest POST field.
*
* Parse a request message, initialize the given node object with it, try to extract basic SAML
* profile information like the remote_provider_id or the name_id and validate the signature.
*
* Signature validation status is accessible in profile->signature_status, beware that if signature
* validation fails no error code will be returned, you must explicitely verify the
* profile->signature_status code.
*
* Return value: 0 if parsing is successfull (even if signature validation fails), and error code
* otherwise.
*/
int
lasso_saml20_profile_process_any_request(LassoProfile *profile,
LassoNode *request_node,
@ -549,13 +566,13 @@ lasso_saml20_profile_process_any_request(LassoProfile *profile,
/* verify the signature at the request level */
if (content && doc && format != LASSO_MESSAGE_FORMAT_QUERY) {
rc = profile->signature_status =
profile->signature_status =
lasso_provider_verify_saml_signature(remote_provider, content, doc);
} else if (format == LASSO_MESSAGE_FORMAT_QUERY) {
rc = profile->signature_status =
profile->signature_status =
lasso_provider_verify_query_signature(remote_provider, request_msg);
} else {
rc = LASSO_PROFILE_ERROR_CANNOT_VERIFY_SIGNATURE;
profile->signature_status = LASSO_PROFILE_ERROR_CANNOT_VERIFY_SIGNATURE;
}
cleanup:
@ -1157,6 +1174,11 @@ cleanup:
*
* Generic method for SAML 2.0 protocol message handling.
*
* It tries to validate a signature on the response msg, the result of this operation is kept inside
* profile->signature_status. Use it afterward in your specific profile. Beware that it does not
* return an error code if signature validation failed. It let's specific profile accept unsigned
* messages.
*
* Return value: 0 if successful, an error code otherwise.
*/
int
@ -1206,13 +1228,13 @@ lasso_saml20_profile_process_any_response(LassoProfile *profile,
/* verify the signature at the request level */
if (content && doc && format != LASSO_MESSAGE_FORMAT_QUERY) {
rc = profile->signature_status =
profile->signature_status =
lasso_provider_verify_saml_signature(remote_provider, content, doc);
} else if (format == LASSO_MESSAGE_FORMAT_QUERY) {
rc = profile->signature_status =
profile->signature_status =
lasso_provider_verify_query_signature(remote_provider, response_msg);
} else {
rc = LASSO_PROFILE_ERROR_CANNOT_VERIFY_SIGNATURE;
profile->signature_status = LASSO_PROFILE_ERROR_CANNOT_VERIFY_SIGNATURE;
}
/* verify status code */