summaryrefslogtreecommitdiff
path: root/net-libs/gnutls/files/gnutls-3.7.0-ignore-duplicate-certificates.patch
diff options
context:
space:
mode:
Diffstat (limited to 'net-libs/gnutls/files/gnutls-3.7.0-ignore-duplicate-certificates.patch')
-rw-r--r--net-libs/gnutls/files/gnutls-3.7.0-ignore-duplicate-certificates.patch403
1 files changed, 0 insertions, 403 deletions
diff --git a/net-libs/gnutls/files/gnutls-3.7.0-ignore-duplicate-certificates.patch b/net-libs/gnutls/files/gnutls-3.7.0-ignore-duplicate-certificates.patch
deleted file mode 100644
index b0143818b46b..000000000000
--- a/net-libs/gnutls/files/gnutls-3.7.0-ignore-duplicate-certificates.patch
+++ /dev/null
@@ -1,403 +0,0 @@
-From 09b40be6e0e0a59ba4bd764067eb353241043a70 Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Mon, 28 Dec 2020 12:14:13 +0100
-Subject: [PATCH] gnutls_x509_trust_list_verify_crt2: ignore duplicate
- certificates
-
-The commit ebb19db9165fed30d73c83bab1b1b8740c132dfd caused a
-regression, where duplicate certificates in a certificate chain are no
-longer ignored but treated as a non-contiguous segment and that
-results in calling the issuer callback, or a verification failure.
-
-This adds a mechanism to record certificates already seen in the
-chain, and skip them while still allow the caller to inject missing
-certificates.
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
-Co-authored-by: Andreas Metzler <ametzler@debian.org>
----
- lib/x509/common.c | 8 ++
- lib/x509/verify-high.c | 157 +++++++++++++++++++++++++++++++------
- tests/missingissuer.c | 2 +
- tests/test-chains-issuer.h | 101 +++++++++++++++++++++++-
- 4 files changed, 245 insertions(+), 23 deletions(-)
-
-diff --git a/lib/x509/common.c b/lib/x509/common.c
-index 3301aaad0c..10c8db53c0 100644
---- a/lib/x509/common.c
-+++ b/lib/x509/common.c
-@@ -1758,6 +1758,14 @@ unsigned int _gnutls_sort_clist(gnutls_x509_crt_t *clist,
- * increasing DEFAULT_MAX_VERIFY_DEPTH.
- */
- for (i = 0; i < clist_size; i++) {
-+ /* Self-signed certificate found in the chain; skip it
-+ * as it should only appear in the trusted set.
-+ */
-+ if (gnutls_x509_crt_check_issuer(clist[i], clist[i])) {
-+ _gnutls_cert_log("self-signed cert found", clist[i]);
-+ continue;
-+ }
-+
- for (j = 1; j < clist_size; j++) {
- if (i == j)
- continue;
-diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
-index 588e7ee0dc..9a16e6b42a 100644
---- a/lib/x509/verify-high.c
-+++ b/lib/x509/verify-high.c
-@@ -67,6 +67,80 @@ struct gnutls_x509_trust_list_iter {
-
- #define DEFAULT_SIZE 127
-
-+struct cert_set_node_st {
-+ gnutls_x509_crt_t *certs;
-+ unsigned int size;
-+};
-+
-+struct cert_set_st {
-+ struct cert_set_node_st *node;
-+ unsigned int size;
-+};
-+
-+static int
-+cert_set_init(struct cert_set_st *set, unsigned int size)
-+{
-+ memset(set, 0, sizeof(*set));
-+
-+ set->size = size;
-+ set->node = gnutls_calloc(size, sizeof(*set->node));
-+ if (!set->node) {
-+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-+ }
-+
-+ return 0;
-+}
-+
-+static void
-+cert_set_deinit(struct cert_set_st *set)
-+{
-+ size_t i;
-+
-+ for (i = 0; i < set->size; i++) {
-+ gnutls_free(set->node[i].certs);
-+ }
-+
-+ gnutls_free(set->node);
-+}
-+
-+static bool
-+cert_set_contains(struct cert_set_st *set, const gnutls_x509_crt_t cert)
-+{
-+ size_t hash, i;
-+
-+ hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size);
-+ hash %= set->size;
-+
-+ for (i = 0; i < set->node[hash].size; i++) {
-+ if (unlikely(gnutls_x509_crt_equals(set->node[hash].certs[i], cert))) {
-+ return true;
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+static int
-+cert_set_add(struct cert_set_st *set, const gnutls_x509_crt_t cert)
-+{
-+ size_t hash;
-+
-+ hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size);
-+ hash %= set->size;
-+
-+ set->node[hash].certs =
-+ gnutls_realloc_fast(set->node[hash].certs,
-+ (set->node[hash].size + 1) *
-+ sizeof(*set->node[hash].certs));
-+ if (!set->node[hash].certs) {
-+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-+ }
-+ set->node[hash].certs[set->node[hash].size] = cert;
-+ set->node[hash].size++;
-+
-+ return 0;
-+}
-+
- /**
- * gnutls_x509_trust_list_init:
- * @list: A pointer to the type to be initialized
-@@ -1328,6 +1402,7 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
- unsigned have_set_name = 0;
- unsigned saved_output;
- gnutls_datum_t ip = {NULL, 0};
-+ struct cert_set_st cert_set = { NULL, 0 };
-
- if (cert_list == NULL || cert_list_size < 1)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-@@ -1376,36 +1451,68 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
- memcpy(sorted, cert_list, cert_list_size * sizeof(gnutls_x509_crt_t));
- cert_list = sorted;
-
-+ ret = cert_set_init(&cert_set, DEFAULT_MAX_VERIFY_DEPTH);
-+ if (ret < 0) {
-+ return ret;
-+ }
-+
- for (i = 0; i < cert_list_size &&
-- cert_list_size <= DEFAULT_MAX_VERIFY_DEPTH; i++) {
-- if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN)) {
-- unsigned int sorted_size;
-+ cert_list_size <= DEFAULT_MAX_VERIFY_DEPTH; ) {
-+ unsigned int sorted_size = 1;
-+ unsigned int j;
-+ gnutls_x509_crt_t issuer;
-
-+ if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN)) {
- sorted_size = _gnutls_sort_clist(&cert_list[i],
- cert_list_size - i);
-- i += sorted_size - 1;
- }
-
-- if (i == cert_list_size - 1) {
-- gnutls_x509_crt_t issuer;
--
-- /* If it is the last certificate and its issuer is
-- * known, don't need to run issuer callback. */
-- if (_gnutls_trust_list_get_issuer(list,
-- cert_list[i],
-- &issuer,
-- 0) == 0) {
-+ /* Remove duplicates. Start with index 1, as the first element
-+ * may be re-checked after issuer retrieval. */
-+ for (j = 1; j < sorted_size; j++) {
-+ if (cert_set_contains(&cert_set, cert_list[i + j])) {
-+ if (i + j < cert_list_size - 1) {
-+ memmove(&cert_list[i + j],
-+ &cert_list[i + j + 1],
-+ sizeof(cert_list[i]));
-+ }
-+ cert_list_size--;
- break;
- }
-- } else if (gnutls_x509_crt_check_issuer(cert_list[i],
-- cert_list[i + 1])) {
-- /* There is no gap between this and the next
-- * certificate. */
-+ }
-+ /* Found a duplicate, try again with the same index. */
-+ if (j < sorted_size) {
-+ continue;
-+ }
-+
-+ /* Record the certificates seen. */
-+ for (j = 0; j < sorted_size; j++, i++) {
-+ ret = cert_set_add(&cert_set, cert_list[i]);
-+ if (ret < 0) {
-+ goto cleanup;
-+ }
-+ }
-+
-+ /* If the issuer of the certificate is known, no need
-+ * for further processing. */
-+ if (_gnutls_trust_list_get_issuer(list,
-+ cert_list[i - 1],
-+ &issuer,
-+ 0) == 0) {
-+ cert_list_size = i;
-+ break;
-+ }
-+
-+ /* If there is no gap between this and the next certificate,
-+ * proceed with the next certificate. */
-+ if (i < cert_list_size &&
-+ gnutls_x509_crt_check_issuer(cert_list[i - 1],
-+ cert_list[i])) {
- continue;
- }
-
- ret = retrieve_issuers(list,
-- cert_list[i],
-+ cert_list[i - 1],
- &retrieved[retrieved_size],
- DEFAULT_MAX_VERIFY_DEPTH -
- MAX(retrieved_size,
-@@ -1413,15 +1520,20 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
- if (ret < 0) {
- break;
- } else if (ret > 0) {
-- memmove(&cert_list[i + 1 + ret],
-- &cert_list[i + 1],
-- (cert_list_size - i - 1) *
-+ assert((unsigned int)ret <=
-+ DEFAULT_MAX_VERIFY_DEPTH - cert_list_size);
-+ memmove(&cert_list[i + ret],
-+ &cert_list[i],
-+ (cert_list_size - i) *
- sizeof(gnutls_x509_crt_t));
-- memcpy(&cert_list[i + 1],
-+ memcpy(&cert_list[i],
- &retrieved[retrieved_size],
- ret * sizeof(gnutls_x509_crt_t));
- retrieved_size += ret;
- cert_list_size += ret;
-+
-+ /* Start again from the end of the previous segment. */
-+ i--;
- }
- }
-
-@@ -1581,6 +1693,7 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
- for (i = 0; i < retrieved_size; i++) {
- gnutls_x509_crt_deinit(retrieved[i]);
- }
-+ cert_set_deinit(&cert_set);
- return ret;
- }
-
-diff --git a/tests/missingissuer.c b/tests/missingissuer.c
-index f21e2b6b0c..226d095929 100644
---- a/tests/missingissuer.c
-+++ b/tests/missingissuer.c
-@@ -145,6 +145,8 @@ void doit(void)
- printf("[%d]: Chain '%s'...\n", (int)i, chains[i].name);
-
- for (j = 0; chains[i].chain[j]; j++) {
-+ assert(j < MAX_CHAIN);
-+
- if (debug > 2)
- printf("\tAdding certificate %d...", (int)j);
-
-diff --git a/tests/test-chains-issuer.h b/tests/test-chains-issuer.h
-index 543e2d71fb..bf1e65c956 100644
---- a/tests/test-chains-issuer.h
-+++ b/tests/test-chains-issuer.h
-@@ -24,7 +24,7 @@
- #ifndef GNUTLS_TESTS_TEST_CHAINS_ISSUER_H
- #define GNUTLS_TESTS_TEST_CHAINS_ISSUER_H
-
--#define MAX_CHAIN 6
-+#define MAX_CHAIN 15
-
- #define SERVER_CERT "-----BEGIN CERTIFICATE-----\n" \
- "MIIDATCCAbmgAwIBAgIUQdvdegP8JFszFHLfV4+lrEdafzAwPQYJKoZIhvcNAQEK\n" \
-@@ -338,11 +338,102 @@ static const char *missing_middle_unrelated_extra_insert[] = {
- NULL,
- };
-
-+static const char *missing_middle_single_duplicate[] = {
-+ SERVER_CERT,
-+ SERVER_CERT,
-+ CA_CERT_5,
-+ CA_CERT_5,
-+ CA_CERT_4,
-+ CA_CERT_4,
-+ CA_CERT_2,
-+ CA_CERT_2,
-+ CA_CERT_1,
-+ CA_CERT_1,
-+ NULL,
-+};
-+
-+static const char *missing_middle_multiple_duplicate[] = {
-+ SERVER_CERT,
-+ SERVER_CERT,
-+ CA_CERT_5,
-+ CA_CERT_5,
-+ CA_CERT_4,
-+ CA_CERT_4,
-+ CA_CERT_1,
-+ CA_CERT_1,
-+ NULL,
-+};
-+
-+static const char *missing_last_single_duplicate[] = {
-+ SERVER_CERT,
-+ SERVER_CERT,
-+ CA_CERT_5,
-+ CA_CERT_5,
-+ CA_CERT_4,
-+ CA_CERT_4,
-+ CA_CERT_3,
-+ CA_CERT_3,
-+ CA_CERT_2,
-+ CA_CERT_2,
-+ NULL,
-+};
-+
-+static const char *missing_last_multiple_duplicate[] = {
-+ SERVER_CERT,
-+ SERVER_CERT,
-+ CA_CERT_5,
-+ CA_CERT_5,
-+ CA_CERT_4,
-+ CA_CERT_4,
-+ CA_CERT_3,
-+ CA_CERT_3,
-+ NULL,
-+};
-+
-+static const char *missing_skip_single_duplicate[] = {
-+ SERVER_CERT,
-+ SERVER_CERT,
-+ CA_CERT_5,
-+ CA_CERT_5,
-+ CA_CERT_3,
-+ CA_CERT_3,
-+ CA_CERT_1,
-+ CA_CERT_1,
-+ NULL,
-+};
-+
-+static const char *missing_skip_multiple_duplicate[] = {
-+ SERVER_CERT,
-+ SERVER_CERT,
-+ CA_CERT_5,
-+ CA_CERT_5,
-+ CA_CERT_3,
-+ CA_CERT_3,
-+ NULL,
-+};
-+
- static const char *missing_ca[] = {
- CA_CERT_0,
- NULL,
- };
-
-+static const char *middle_single_duplicate_ca[] = {
-+ SERVER_CERT,
-+ CA_CERT_5,
-+ CA_CERT_0,
-+ CA_CERT_4,
-+ CA_CERT_0,
-+ CA_CERT_2,
-+ CA_CERT_0,
-+ CA_CERT_1,
-+ NULL,
-+};
-+
-+static const char *missing_middle_single_duplicate_ca_unrelated_insert[] = {
-+ CA_CERT_0,
-+ NULL,
-+};
-+
- static struct chains {
- const char *name;
- const char **chain;
-@@ -377,6 +468,14 @@ static struct chains {
- { "skip multiple unsorted", missing_skip_multiple_unsorted, missing_skip_multiple_insert, missing_ca, 0, 0 },
- { "unrelated", missing_middle_single, missing_middle_unrelated_insert, missing_ca, 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND },
- { "unrelated extra", missing_middle_single, missing_middle_unrelated_extra_insert, missing_ca, 0, 0 },
-+ { "middle single duplicate", missing_middle_single_duplicate, missing_middle_single_insert, missing_ca, 0, 0 },
-+ { "middle multiple duplicate", missing_middle_multiple_duplicate, missing_middle_multiple_insert, missing_ca, 0, 0 },
-+ { "last single duplicate", missing_last_single_duplicate, missing_last_single_insert, missing_ca, 0, 0 },
-+ { "last multiple duplicate", missing_last_multiple_duplicate, missing_last_multiple_insert, missing_ca, 0, 0 },
-+ { "skip single duplicate", missing_skip_single_duplicate, missing_skip_single_insert, missing_ca, 0, 0 },
-+ { "skip multiple duplicate", missing_skip_multiple_duplicate, missing_skip_multiple_insert, missing_ca, 0, 0 },
-+ { "middle single duplicate ca", middle_single_duplicate_ca, missing_middle_single_insert, missing_ca, 0, 0 },
-+ { "middle single duplicate ca - insert unrelated", middle_single_duplicate_ca, missing_middle_single_duplicate_ca_unrelated_insert, missing_ca, 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND },
- { NULL, NULL, NULL, NULL },
- };
-
---
-GitLab
-