summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-07-31 17:47:42 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-07-31 17:55:11 +0200
commit5c0711523df8f108ecc1707dcd0cc4134003343e (patch)
tree02fbce6b4c44b86544fe845aca128b1f2e6a8896
parent7544a585429668e0b5b4eccc463a9cd3ac247bad (diff)
downloadgnutls-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--NEWS7
-rw-r--r--lib/gnutls_errors.c2
-rw-r--r--lib/gnutls_x509.c67
-rw-r--r--lib/includes/gnutls/gnutls.h.in1
4 files changed, 77 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index b5850dbb6f..bc8b829dbe 100644
--- a/NEWS
+++ b/NEWS
@@ -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