From: Nikos Mavrogiannopoulos Date: Thu, 27 Nov 2014 21:39:08 +0000 (+0100) Subject: GNUTLS_E_CERTIFICATE_LIST_UNSORTED can be returned from gnutls_pcert_import_x509_list X-Git-Tag: gnutls_3_4_0~549 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9aeb326b3736ede65fd7de2a63ee0fc525bb4946;p=thirdparty%2Fgnutls.git GNUTLS_E_CERTIFICATE_LIST_UNSORTED can be returned from gnutls_pcert_import_x509_list That is when it cannot sort the list and GNUTLS_X509_CRT_LIST_SORT is specified. --- diff --git a/lib/gnutls_pcert.c b/lib/gnutls_pcert.c index 580bb48bdc..53e9a21d3a 100644 --- a/lib/gnutls_pcert.c +++ b/lib/gnutls_pcert.c @@ -96,6 +96,11 @@ int gnutls_pcert_import_x509(gnutls_pcert_st * pcert, * #gnutls_pcert_st structure. The structure must be deinitialized * afterwards using gnutls_pcert_deinit(); * + * In the case %GNUTLS_X509_CRT_LIST_SORT is specified and that + * function cannot sort the list, %GNUTLS_E_CERTIFICATE_LIST_UNSORTED + * will be returned. Currently sorting can fail if the list size + * exceeds an internal constraint (16). + * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * @@ -112,11 +117,20 @@ int gnutls_pcert_import_x509_list(gnutls_pcert_st * pcert, gnutls_x509_crt_t *s; s = crt; - if (flags & GNUTLS_X509_CRT_LIST_SORT && *ncrt > 1 && *ncrt < DEFAULT_MAX_VERIFY_DEPTH) { - s = _gnutls_sort_clist(sorted, crt, ncrt, NULL); - if (s == crt) { - gnutls_assert(); - return GNUTLS_E_UNIMPLEMENTED_FEATURE; + + if (flags & GNUTLS_X509_CRT_LIST_SORT && *ncrt > 1) { + if (*ncrt > DEFAULT_MAX_VERIFY_DEPTH) { + ret = _gnutls_check_if_sorted(crt, *ncrt); + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_CERTIFICATE_LIST_UNSORTED; + } + } else { + s = _gnutls_sort_clist(sorted, crt, ncrt, NULL); + if (s == crt) { + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } } } diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index c9b099b55c..8703cd96e2 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -949,51 +949,6 @@ gnutls_certificate_set_x509_key_mem2(gnutls_certificate_credentials_t res, return 0; } -static int check_if_sorted(gnutls_pcert_st * crt, int nr) -{ - gnutls_x509_crt_t x509; - gnutls_x509_crt_t prev = NULL; - 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) { - if (gnutls_x509_crt_check_issuer(prev, x509) == 0) { - ret = - gnutls_assert_val - (GNUTLS_E_CERTIFICATE_LIST_UNSORTED); - goto cleanup; - } - - gnutls_x509_crt_deinit(prev); - } - - prev = x509; - } - gnutls_x509_crt_deinit(prev); - } - - return 0; - -cleanup: - gnutls_x509_crt_deinit(prev); - gnutls_x509_crt_deinit(x509); - return ret; -} - int certificate_credential_append_crt_list(gnutls_certificate_credentials_t res, gnutls_str_array_t names, @@ -1001,10 +956,6 @@ certificate_credential_append_crt_list(gnutls_certificate_credentials_t { int ret; - ret = check_if_sorted(crt, nr); - if (ret < 0) - return gnutls_assert_val(ret); - res->certs = gnutls_realloc_fast(res->certs, (1 + res->ncerts) * sizeof(certs_st)); diff --git a/lib/x509/common.c b/lib/x509/common.c index a34cdd5582..cfb4ad9195 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -2048,3 +2048,36 @@ gnutls_x509_crt_t *_gnutls_sort_clist(gnutls_x509_crt_t return sorted; } + +int _gnutls_check_if_sorted(gnutls_x509_crt_t * crt, int nr) +{ + void *prev_dn = NULL; + void *dn; + size_t prev_dn_size = 0, dn_size; + int i, ret; + + /* check if the X.509 list is ordered */ + if (nr > 1) { + for (i = 0; i < nr; i++) { + if (i > 0) { + dn = crt[i]->raw_dn.data; + dn_size = crt[i]->raw_dn.size; + + 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 = crt[i]->raw_issuer_dn.data; + prev_dn_size = crt[i]->raw_issuer_dn.size; + } + } + ret = 0; + +cleanup: + return ret; +} diff --git a/lib/x509/common.h b/lib/x509/common.h index f319b5be1e..e7431e8c01 100644 --- a/lib/x509/common.h +++ b/lib/x509/common.h @@ -240,4 +240,6 @@ gnutls_x509_crt_t *_gnutls_sort_clist(gnutls_x509_crt_t unsigned int *clist_size, gnutls_cert_vfunc func); +int _gnutls_check_if_sorted(gnutls_x509_crt_t * crt, int nr); + #endif diff --git a/lib/x509/x509.c b/lib/x509/x509.c index d2b594876c..83b1272597 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -3281,40 +3281,6 @@ gnutls_x509_crt_list_import2(gnutls_x509_crt_t ** certs, return 0; } -static int check_if_sorted(gnutls_x509_crt_t * crt, int nr) -{ - void *prev_dn = NULL; - void *dn; - size_t prev_dn_size = 0, dn_size; - int i, ret; - - /* check if the X.509 list is ordered */ - if (nr > 1) { - for (i = 0; i < nr; i++) { - if (i > 0) { - dn = crt[i]->raw_dn.data; - dn_size = crt[i]->raw_dn.size; - - 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 = crt[i]->raw_issuer_dn.data; - prev_dn_size = crt[i]->raw_issuer_dn.size; - } - } - ret = 0; - -cleanup: - return ret; -} - - /** * gnutls_x509_crt_list_import: * @certs: The structures to store the parsed certificate. Must not be initialized. @@ -3463,7 +3429,7 @@ gnutls_x509_crt_list_import(gnutls_x509_crt_t * certs, } if (flags & GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED) { - ret = check_if_sorted(certs, *cert_max); + ret = _gnutls_check_if_sorted(certs, *cert_max); if (ret < 0) { gnutls_assert(); goto error;