diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-07-31 17:47:42 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-07-31 17:55:11 +0200 |
commit | 5c0711523df8f108ecc1707dcd0cc4134003343e (patch) | |
tree | 02fbce6b4c44b86544fe845aca128b1f2e6a8896 | |
parent | 7544a585429668e0b5b4eccc463a9cd3ac247bad (diff) | |
download | gnutls-5c0711523df8f108ecc1707dcd0cc4134003343e.tar.gz |
Added GNUTLS_E_CERTIFICATE_LIST_UNSORTED.
If a certificate list is loaded then verify
that it is sorted with order to starts with
the subject and finished with the trusted
root. That way we make sure we don't send
data that violate the TLS protocol.
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 2 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 67 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 1 |
4 files changed, 77 insertions, 0 deletions
@@ -8,6 +8,13 @@ See the end for copying conditions. ** libgnutls: gcrypt: replaced occurences of gcry_sexp_nth_mpi (..., 0) with gcry_sexp_nth_mpi (..., GCRYMPI_FMT_USG) to fix errors with 1.5.0. +** libgnutls: Verify that a certificate liste specified +using gnutls_certificate_set_x509_key*(), is sorted +according to TLS specification (from subject to issuer). + +** API and ABI modifications: +No changes since last version. + ** libgnutls: writev_emu: stop on the first incomplete write. Patch by Sjoerd Simons. diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 137a590cd9..37e5b1e4e4 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -321,6 +321,8 @@ static const gnutls_error_entry error_algorithms[] = { GNUTLS_E_PKCS11_TOKEN_ERROR, 1), ERROR_ENTRY (N_("PKCS #11 user error"), GNUTLS_E_PKCS11_USER_ERROR, 1), + ERROR_ENTRY (N_("The provided X.509 certificate list is not sorted (in subject to issuer order)"), + GNUTLS_E_CERTIFICATE_LIST_UNSORTED, 1), {NULL, NULL, 0, 0} }; diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index ee5872f096..3dbc763866 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -808,10 +808,77 @@ gnutls_certificate_set_x509_key_mem (gnutls_certificate_credentials_t res, return 0; } +static int check_if_sorted(gnutls_pcert_st * crt, int nr) +{ +gnutls_x509_crt_t x509; +char prev_dn[MAX_CN]; +char dn[MAX_CN]; +size_t prev_dn_size, dn_size; +int i, ret; + + /* check if the X.509 list is ordered */ + if (nr > 1 && crt[0].type == GNUTLS_CRT_X509) + { + + for (i=0;i<nr;i++) + { + ret = gnutls_x509_crt_init(&x509); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = gnutls_x509_crt_import(x509, &crt[i].cert, GNUTLS_X509_FMT_DER); + if (ret < 0) + { + ret = gnutls_assert_val(ret); + goto cleanup; + } + + if (i>0) + { + dn_size = sizeof(dn); + ret = gnutls_x509_crt_get_dn(x509, dn, &dn_size); + if (ret < 0) + { + ret = gnutls_assert_val(ret); + goto cleanup; + } + + if (dn_size != prev_dn_size || memcmp(dn, prev_dn, dn_size) != 0) + { + ret = gnutls_assert_val(GNUTLS_E_CERTIFICATE_LIST_UNSORTED); + goto cleanup; + } + } + + prev_dn_size = sizeof(prev_dn); + ret = gnutls_x509_crt_get_issuer_dn(x509, prev_dn, &prev_dn_size); + if (ret < 0) + { + ret = gnutls_assert_val(ret); + goto cleanup; + } + + gnutls_x509_crt_deinit(x509); + } + } + + return 0; + +cleanup: + gnutls_x509_crt_deinit(x509); + return ret; +} + int certificate_credential_append_crt_list (gnutls_certificate_credentials_t res, gnutls_cert * crt, int nr) { +int ret; + + ret = check_if_sorted(crt, nr); + if (ret < 0) + return gnutls_assert_val(ret); + res->cert_list = gnutls_realloc_fast (res->cert_list, (1 + res->ncerts) * diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 9512ece8c5..b7bd12626d 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1759,6 +1759,7 @@ extern "C" #define GNUTLS_E_PKCS11_USER_ERROR -317 #define GNUTLS_E_CRYPTO_INIT_FAILED -318 +#define GNUTLS_E_CERTIFICATE_LIST_UNSORTED -324 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 |