[core] refactor lasso_query_verify_signature and lasso_saml2_query_verify_signature
This commit introduces lasso_query_verify_helper which factorize cryptographic operations.
This commit is contained in:
parent
42ca33315d
commit
6c7114d5ce
|
@ -474,14 +474,14 @@ lasso_query_sign(char *query, LassoSignatureContext context)
|
||||||
RSA *rsa = NULL;
|
RSA *rsa = NULL;
|
||||||
DSA *dsa = NULL;
|
DSA *dsa = NULL;
|
||||||
unsigned char *sigret = NULL;
|
unsigned char *sigret = NULL;
|
||||||
unsigned int siglen;
|
unsigned int siglen = 0;
|
||||||
xmlChar *b64_sigret = NULL, *e_b64_sigret = NULL;
|
xmlChar *b64_sigret = NULL, *e_b64_sigret = NULL;
|
||||||
char *new_query = NULL, *s_new_query = NULL;
|
char *new_query = NULL, *s_new_query = NULL;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
const xmlChar *algo_href = NULL;
|
const xmlChar *algo_href = NULL;
|
||||||
xmlSecKey *key;
|
xmlSecKey *key;
|
||||||
xmlSecKeyData *key_data;
|
xmlSecKeyData *key_data;
|
||||||
int sigret_size;
|
unsigned int sigret_size = 0;
|
||||||
LassoSignatureMethod sign_method;
|
LassoSignatureMethod sign_method;
|
||||||
|
|
||||||
g_return_val_if_fail(query != NULL, NULL);
|
g_return_val_if_fail(query != NULL, NULL);
|
||||||
|
@ -551,12 +551,14 @@ lasso_query_sign(char *query, LassoSignatureContext context)
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_assert(siglen == sigret_size);
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base64 encode the signature value */
|
/* Base64 encode the signature value */
|
||||||
b64_sigret = xmlSecBase64Encode(sigret, siglen, 0);
|
b64_sigret = xmlSecBase64Encode(sigret, sigret_size, 0);
|
||||||
/* escape b64_sigret */
|
/* escape b64_sigret */
|
||||||
e_b64_sigret = xmlURIEscapeStr((xmlChar*)b64_sigret, NULL);
|
e_b64_sigret = xmlURIEscapeStr((xmlChar*)b64_sigret, NULL);
|
||||||
|
|
||||||
|
@ -602,6 +604,78 @@ lasso_assertion_encrypt(LassoSaml2Assertion *assertion, char *recipient)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static lasso_error_t
|
||||||
|
lasso_query_verify_helper(const char *signed_content, const char *b64_signature, const char *algorithm,
|
||||||
|
const xmlSecKey *key)
|
||||||
|
{
|
||||||
|
RSA *rsa = NULL;
|
||||||
|
DSA *dsa = NULL;
|
||||||
|
char *digest = NULL;
|
||||||
|
xmlSecByte *signature = NULL;
|
||||||
|
int key_size = 0;
|
||||||
|
lasso_error_t rc = 0;
|
||||||
|
LassoSignatureMethod method = LASSO_SIGNATURE_METHOD_NONE;
|
||||||
|
|
||||||
|
if (lasso_strisequal(algorithm, (char*)xmlSecHrefRsaSha1)) {
|
||||||
|
goto_cleanup_if_fail_with_rc(key->value->id == xmlSecOpenSSLKeyDataRsaId,
|
||||||
|
LASSO_DS_ERROR_INVALID_SIGALG)
|
||||||
|
rsa = xmlSecOpenSSLKeyDataRsaGetRsa(key->value);
|
||||||
|
key_size = RSA_size(rsa);
|
||||||
|
method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
|
||||||
|
} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefDsaSha1)) {
|
||||||
|
goto_cleanup_if_fail_with_rc(key->value->id == xmlSecOpenSSLKeyDataDsaId, LASSO_DS_ERROR_INVALID_SIGALG);
|
||||||
|
dsa = xmlSecOpenSSLKeyDataDsaGetDsa(key->value);
|
||||||
|
key_size = DSA_size(dsa);
|
||||||
|
method = LASSO_SIGNATURE_METHOD_DSA_SHA1;
|
||||||
|
} else {
|
||||||
|
goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGALG);
|
||||||
|
}
|
||||||
|
/* decode signature */
|
||||||
|
signature = g_malloc(key_size+1);
|
||||||
|
goto_cleanup_if_fail_with_rc(
|
||||||
|
xmlSecBase64Decode((xmlChar*)b64_signature, signature, key_size+1) != 0,
|
||||||
|
LASSO_DS_ERROR_INVALID_SIGNATURE);
|
||||||
|
/* digest */
|
||||||
|
switch (method) {
|
||||||
|
case LASSO_SIGNATURE_METHOD_RSA_SHA1:
|
||||||
|
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||||
|
digest = lasso_sha1(signed_content);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* verify signature */
|
||||||
|
switch (method) {
|
||||||
|
case LASSO_SIGNATURE_METHOD_RSA_SHA1:
|
||||||
|
goto_cleanup_if_fail_with_rc(
|
||||||
|
RSA_verify(
|
||||||
|
NID_sha1,
|
||||||
|
(unsigned char*)digest,
|
||||||
|
20,
|
||||||
|
signature,
|
||||||
|
key_size, rsa) == 1,
|
||||||
|
LASSO_DS_ERROR_INVALID_SIGNATURE);
|
||||||
|
break;
|
||||||
|
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||||
|
goto_cleanup_if_fail_with_rc(
|
||||||
|
DSA_verify(NID_sha1,
|
||||||
|
(unsigned char*)digest,
|
||||||
|
20,
|
||||||
|
signature,
|
||||||
|
key_size, dsa) == 1,
|
||||||
|
LASSO_DS_ERROR_INVALID_SIGNATURE);
|
||||||
|
break;
|
||||||
|
case LASSO_SIGNATURE_METHOD_NONE:
|
||||||
|
case LASSO_SIGNATURE_METHOD_LAST:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
lasso_release_string(digest);
|
||||||
|
lasso_release_string(signature);
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lasso_query_verify_signature:
|
* lasso_query_verify_signature:
|
||||||
* @query: a query (an url-encoded message)
|
* @query: a query (an url-encoded message)
|
||||||
|
@ -613,16 +687,14 @@ lasso_assertion_encrypt(LassoSaml2Assertion *assertion, char *recipient)
|
||||||
* a positive value if signature was not found or is invalid
|
* a positive value if signature was not found or is invalid
|
||||||
* a negative value if an error occurs during verification
|
* a negative value if an error occurs during verification
|
||||||
**/
|
**/
|
||||||
int
|
lasso_error_t
|
||||||
lasso_query_verify_signature(const char *query, const xmlSecKey *sender_public_key)
|
lasso_query_verify_signature(const char *query, const xmlSecKey *sender_public_key)
|
||||||
{
|
{
|
||||||
RSA *rsa = NULL;
|
|
||||||
DSA *dsa = NULL;
|
|
||||||
gchar **str_split = NULL;
|
gchar **str_split = NULL;
|
||||||
char *digest = NULL, *b64_signature = NULL;
|
char *b64_signature = NULL;
|
||||||
xmlSecByte *signature = NULL;
|
char *sig_alg = NULL;
|
||||||
int key_size, status = 0, ret = 0;
|
char *usig_alg = NULL;
|
||||||
char *sig_alg, *usig_alg = NULL;
|
lasso_error_t rc = 0;
|
||||||
|
|
||||||
g_return_val_if_fail(query != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
|
g_return_val_if_fail(query != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||||
|
|
||||||
|
@ -638,89 +710,31 @@ lasso_query_verify_signature(const char *query, const xmlSecKey *sender_public_k
|
||||||
* covered by the signature */
|
* covered by the signature */
|
||||||
|
|
||||||
str_split = g_strsplit(query, "&Signature=", 0);
|
str_split = g_strsplit(query, "&Signature=", 0);
|
||||||
if (str_split[0] == NULL || str_split[1] == NULL) {
|
if (str_split[0] == NULL || str_split[1] == NULL)
|
||||||
g_strfreev(str_split);
|
goto_cleanup_with_rc(LASSO_DS_ERROR_SIGNATURE_NOT_FOUND);
|
||||||
return LASSO_DS_ERROR_SIGNATURE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sender_public_key->value->id == xmlSecOpenSSLKeyDataRsaId) {
|
|
||||||
} else {
|
|
||||||
/* no key; it will fail later */
|
|
||||||
}
|
|
||||||
|
|
||||||
sig_alg = strstr(str_split[0], "&SigAlg=");
|
sig_alg = strstr(str_split[0], "&SigAlg=");
|
||||||
if (sig_alg == NULL) {
|
if (sig_alg == NULL)
|
||||||
ret = critical_error(LASSO_DS_ERROR_INVALID_SIGALG);
|
goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGALG);
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
sig_alg = strchr(sig_alg, '=')+1;
|
sig_alg = strchr(sig_alg, '=')+1;
|
||||||
|
|
||||||
usig_alg = xmlURIUnescapeString(sig_alg, 0, NULL);
|
usig_alg = xmlURIUnescapeString(sig_alg, 0, NULL);
|
||||||
if (strcmp(usig_alg, (char*)xmlSecHrefRsaSha1) == 0) {
|
|
||||||
if (sender_public_key->value->id != xmlSecOpenSSLKeyDataRsaId) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
rsa = xmlSecOpenSSLKeyDataRsaGetRsa(sender_public_key->value);
|
|
||||||
if (rsa == NULL) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
key_size = RSA_size(rsa);
|
|
||||||
} else if (strcmp(usig_alg, (char*)xmlSecHrefDsaSha1) == 0) {
|
|
||||||
if (sender_public_key->value->id != xmlSecOpenSSLKeyDataDsaId) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
dsa = xmlSecOpenSSLKeyDataDsaGetDsa(sender_public_key->value);
|
|
||||||
if (dsa == NULL) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
key_size = DSA_size(dsa);
|
|
||||||
} else {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_INVALID_SIGALG);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* insure there is only the signature in str_split[1] */
|
/* insure there is only the signature in str_split[1] */
|
||||||
if (strchr(str_split[1], '&')) {
|
if (strchr(str_split[1], '&')) {
|
||||||
strchr(str_split[1], '&')[0] = 0;
|
strchr(str_split[1], '&')[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get signature (unescape + base64 decode) */
|
/* get signature (unescape + base64 decode) */
|
||||||
signature = xmlMalloc(key_size+1);
|
|
||||||
b64_signature = (char*)xmlURIUnescapeString(str_split[1], 0, NULL);
|
b64_signature = (char*)xmlURIUnescapeString(str_split[1], 0, NULL);
|
||||||
if (b64_signature == NULL || xmlSecBase64Decode((xmlChar*)b64_signature, signature, key_size+1) < 0) {
|
lasso_check_good_rc(lasso_query_verify_helper(str_split[0],
|
||||||
ret = LASSO_DS_ERROR_INVALID_SIGNATURE;
|
b64_signature, usig_alg, sender_public_key));
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute signature digest */
|
|
||||||
digest = lasso_sha1(str_split[0]);
|
|
||||||
if (digest == NULL) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_DIGEST_COMPUTE_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rsa) {
|
cleanup:
|
||||||
status = RSA_verify(NID_sha1, (unsigned char*)digest, 20, signature, key_size, rsa);
|
if (b64_signature)
|
||||||
} else if (dsa) {
|
xmlFree(b64_signature);
|
||||||
status = DSA_verify(NID_sha1, (unsigned char*)digest, 20, signature, key_size, dsa);
|
if (usig_alg)
|
||||||
}
|
xmlFree(usig_alg);
|
||||||
|
|
||||||
if (status != 1) {
|
|
||||||
ret = LASSO_DS_ERROR_INVALID_SIGNATURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
xmlFree(b64_signature);
|
|
||||||
xmlFree(signature);
|
|
||||||
lasso_release_string(digest);
|
|
||||||
xmlFree(usig_alg);
|
|
||||||
g_strfreev(str_split);
|
g_strfreev(str_split);
|
||||||
|
return rc;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -735,11 +749,7 @@ done:
|
||||||
int
|
int
|
||||||
lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key)
|
lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key)
|
||||||
{
|
{
|
||||||
RSA *rsa = NULL;
|
char *b64_signature = NULL;
|
||||||
DSA *dsa = NULL;
|
|
||||||
char *digest = NULL, *b64_signature = NULL;
|
|
||||||
xmlSecByte *signature = NULL;
|
|
||||||
int key_size, status = 0, ret = 0;
|
|
||||||
char *query_copy = NULL;
|
char *query_copy = NULL;
|
||||||
char *signed_query = NULL;
|
char *signed_query = NULL;
|
||||||
char *i = NULL;
|
char *i = NULL;
|
||||||
|
@ -748,6 +758,7 @@ lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_pu
|
||||||
char *saml_request_response = NULL;
|
char *saml_request_response = NULL;
|
||||||
char *relaystate = NULL;
|
char *relaystate = NULL;
|
||||||
char *sig_alg, *usig_alg = NULL;
|
char *sig_alg, *usig_alg = NULL;
|
||||||
|
lasso_error_t rc = 0;
|
||||||
|
|
||||||
lasso_return_val_if_fail(query != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
|
lasso_return_val_if_fail(query != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||||
lasso_return_val_if_fail(lasso_flag_verify_signature, 0);
|
lasso_return_val_if_fail(lasso_flag_verify_signature, 0);
|
||||||
|
@ -800,13 +811,11 @@ lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_pu
|
||||||
|
|
||||||
if (! saml_request_response) {
|
if (! saml_request_response) {
|
||||||
message(G_LOG_LEVEL_CRITICAL, "SAMLRequest or SAMLResponse missing in query");
|
message(G_LOG_LEVEL_CRITICAL, "SAMLRequest or SAMLResponse missing in query");
|
||||||
ret = LASSO_PROFILE_ERROR_INVALID_QUERY;
|
goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_QUERY);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! b64_signature) {
|
if (! b64_signature) {
|
||||||
ret = LASSO_DS_ERROR_SIGNATURE_NOT_FOUND;
|
goto_cleanup_with_rc(LASSO_DS_ERROR_SIGNATURE_NOT_FOUND);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
/* build the signed query */
|
/* build the signed query */
|
||||||
if (relaystate) {
|
if (relaystate) {
|
||||||
|
@ -817,74 +826,23 @@ lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_pu
|
||||||
|
|
||||||
sig_alg = strchr(sig_alg, '=')+1;
|
sig_alg = strchr(sig_alg, '=')+1;
|
||||||
if (! sig_alg) {
|
if (! sig_alg) {
|
||||||
ret = LASSO_DS_ERROR_INVALID_SIGALG;
|
goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGALG);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
usig_alg = xmlURIUnescapeString(sig_alg, 0, NULL);
|
usig_alg = xmlURIUnescapeString(sig_alg, 0, NULL);
|
||||||
if (lasso_strisequal(usig_alg,(char *)xmlSecHrefRsaSha1)) {
|
lasso_check_good_rc(lasso_query_verify_helper(signed_query, b64_signature, usig_alg,
|
||||||
if (sender_public_key->value->id != xmlSecOpenSSLKeyDataRsaId) {
|
sender_public_key));
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
rsa = xmlSecOpenSSLKeyDataRsaGetRsa(sender_public_key->value);
|
|
||||||
if (rsa == NULL) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
key_size = RSA_size(rsa);
|
|
||||||
} else if (lasso_strisequal(usig_alg,(char *)xmlSecHrefDsaSha1)) {
|
|
||||||
if (sender_public_key->value->id != xmlSecOpenSSLKeyDataDsaId) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
dsa = xmlSecOpenSSLKeyDataDsaGetDsa(sender_public_key->value);
|
|
||||||
if (dsa == NULL) {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
key_size = DSA_size(dsa);
|
|
||||||
} else {
|
|
||||||
ret = critical_error(LASSO_DS_ERROR_INVALID_SIGALG);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get signature (unescape + base64 decode) */
|
|
||||||
signature = xmlMalloc(key_size+1);
|
|
||||||
xmlSecErrorsDefaultCallbackEnableOutput(FALSE);
|
|
||||||
if (b64_signature == NULL || xmlSecBase64Decode((xmlChar*)b64_signature, signature, key_size+1) < 0) {
|
|
||||||
xmlSecErrorsDefaultCallbackEnableOutput(TRUE);
|
|
||||||
ret = LASSO_DS_ERROR_INVALID_SIGNATURE;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
xmlSecErrorsDefaultCallbackEnableOutput(TRUE);
|
|
||||||
|
|
||||||
/* compute signature digest */
|
cleanup:
|
||||||
digest = lasso_sha1(signed_query);
|
if (b64_signature)
|
||||||
if (digest == NULL) {
|
xmlFree(b64_signature);
|
||||||
ret = critical_error(LASSO_DS_ERROR_DIGEST_COMPUTE_FAILED);
|
if (usig_alg)
|
||||||
goto done;
|
xmlFree(usig_alg);
|
||||||
}
|
|
||||||
|
|
||||||
if (rsa) {
|
|
||||||
status = RSA_verify(NID_sha1, (unsigned char*)digest, 20, signature, key_size, rsa);
|
|
||||||
} else if (dsa) {
|
|
||||||
status = DSA_verify(NID_sha1, (unsigned char*)digest, 20, signature, key_size, dsa);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != 1) {
|
|
||||||
ret = LASSO_DS_ERROR_INVALID_SIGNATURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
xmlFree(b64_signature);
|
|
||||||
xmlFree(signature);
|
|
||||||
lasso_release_string(digest);
|
|
||||||
xmlFree(usig_alg);
|
|
||||||
lasso_release(components);
|
lasso_release(components);
|
||||||
lasso_release(query_copy);
|
lasso_release(query_copy);
|
||||||
lasso_release(signed_query);
|
lasso_release(signed_query);
|
||||||
|
|
||||||
return ret;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1206,6 +1164,7 @@ lasso_saml_constrain_dsigctxt(xmlSecDSigCtxPtr dsigCtx) {
|
||||||
if((xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) ||
|
if((xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) ||
|
||||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) ||
|
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) ||
|
||||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformSha1Id) < 0) ||
|
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformSha1Id) < 0) ||
|
||||||
|
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformDsaSha1Id) < 0) ||
|
||||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformRsaSha1Id) < 0)) {
|
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformRsaSha1Id) < 0)) {
|
||||||
|
|
||||||
message(G_LOG_LEVEL_CRITICAL, "Error: failed to limit allowed signature transforms");
|
message(G_LOG_LEVEL_CRITICAL, "Error: failed to limit allowed signature transforms");
|
||||||
|
|
Loading…
Reference in New Issue