diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2017-05-08 06:43:28 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-05-10 10:45:55 +0200 |
commit | fe3453be9032e94940e1b9cfb1ece35d0d822d06 (patch) | |
tree | 1dd8cfb59d7f39f036ddb54b9ec7ad517c0b2562 /lib/x509/verify-high.c | |
parent | 379223a5a1c418f0542a55e79acd9120e1e6a803 (diff) | |
download | gnutls-fe3453be9032e94940e1b9cfb1ece35d0d822d06.tar.gz |
gnutls_x509_trust_list_verify_crt2: treat signers with insecure algorithms as unknown
The reason is that many servers utilize a legacy chain to improve compatibility
with old clients and that chain often contains insecure algorithm. In that case
try to construct alternative paths. To maintain compatibility with previous
versions, we ensure that the same error code (verification status) is returned
in these cases as before by sending the cached error if the alternative path fails
too.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Diffstat (limited to 'lib/x509/verify-high.c')
-rw-r--r-- | lib/x509/verify-high.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c index 9d9d0956cd..d78a2d4b7b 100644 --- a/lib/x509/verify-high.c +++ b/lib/x509/verify-high.c @@ -52,7 +52,6 @@ struct node_st { /* The trusted CRLs */ gnutls_x509_crl_t *crls; unsigned int crl_size; - }; struct gnutls_x509_trust_list_iter { @@ -1175,6 +1174,15 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list, NULL, 0, flags, voutput, func); } +#define LAST_DN cert_list[cert_list_size-1]->raw_dn +#define LAST_IDN cert_list[cert_list_size-1]->raw_issuer_dn +/* This macro is introduced to detect a verification output + * which indicates an unknown signer, or a signer which uses + * an insecure algorithm (e.g., sha1), something that indicates + * a superceded signer */ +#define SIGNER_OLD_OR_UNKNOWN(output) ((output & GNUTLS_CERT_SIGNER_NOT_FOUND) || (output & GNUTLS_CERT_INSECURE_ALGORITHM)) +#define SIGNER_WAS_KNOWN(output) (!(output & GNUTLS_CERT_SIGNER_NOT_FOUND)) + /** * gnutls_x509_trust_list_verify_crt2: * @list: The list @@ -1238,6 +1246,7 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list, const char *hostname = NULL, *purpose = NULL, *email = NULL; unsigned hostname_size = 0; unsigned have_set_name = 0; + unsigned saved_output; gnutls_datum_t ip = {NULL, 0}; if (cert_list == NULL || cert_list_size < 1) @@ -1313,11 +1322,9 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list, list-> node[hash].trusted_ca_size, flags, purpose, func); + saved_output = *voutput; -#define LAST_DN cert_list[cert_list_size-1]->raw_dn -#define LAST_IDN cert_list[cert_list_size-1]->raw_issuer_dn - - if ((*voutput) & GNUTLS_CERT_SIGNER_NOT_FOUND && + if (SIGNER_OLD_OR_UNKNOWN(*voutput) && (LAST_DN.size != LAST_IDN.size || memcmp(LAST_DN.data, LAST_IDN.data, LAST_IDN.size) != 0)) { @@ -1329,16 +1336,25 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list, data, cert_list[cert_list_size - 1]->raw_dn.size); hash %= list->size; + _gnutls_debug_log("issuer in verification was not found or insecure; trying against trust list\n"); + *voutput = _gnutls_verify_crt_status(cert_list, cert_list_size, list->node[hash].trusted_cas, list-> node[hash].trusted_ca_size, flags, purpose, func); + if (*voutput != 0) { + if (SIGNER_WAS_KNOWN(saved_output)) + *voutput = saved_output; + gnutls_assert(); + } } + saved_output = *voutput; + #ifdef ENABLE_PKCS11 - if ((*voutput & GNUTLS_CERT_SIGNER_NOT_FOUND) && list->pkcs11_token) { + if (SIGNER_OLD_OR_UNKNOWN(*voutput) && list->pkcs11_token) { /* use the token for verification */ *voutput = _gnutls_pkcs11_verify_crt_status(list->pkcs11_token, @@ -1346,6 +1362,8 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list, purpose, flags, func); if (*voutput != 0) { + if (SIGNER_WAS_KNOWN(saved_output)) + *voutput = saved_output; gnutls_assert(); } } |