nss-fix-hang-when-hashing-certificates.patch

application/octet-stream

Filename: nss-fix-hang-when-hashing-certificates.patch
Type: application/octet-stream
Part: 0
Message: Re: Support for NSS as a libpq TLS backend

Patch

Format: format-patch
Subject: nss: fix hang when hashing certificates
File+
src/backend/libpq/be-secure-nss.c 12 7
src/interfaces/libpq/fe-secure-nss.c 16 6
From 2f1d58f9c376429ca3ff84d0489824603d2bcd52 Mon Sep 17 00:00:00 2001
From: Jacob Champion <pchampion@vmware.com>
Date: Mon, 16 Nov 2020 08:55:33 -0800
Subject: [PATCH] nss: fix hang when hashing certificates

---
 src/backend/libpq/be-secure-nss.c    | 19 ++++++++++++-------
 src/interfaces/libpq/fe-secure-nss.c | 22 ++++++++++++++++------
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/src/backend/libpq/be-secure-nss.c b/src/backend/libpq/be-secure-nss.c
index e7540c4756..b1982ee596 100644
--- a/src/backend/libpq/be-secure-nss.c
+++ b/src/backend/libpq/be-secure-nss.c
@@ -813,6 +813,7 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
 	SECOidTag	signature_alg;
 	SECOidTag	digest_alg;
 	int			digest_len;
+	const NSSSignatureAlgorithms *candidate;
 	SECStatus	status;
 	PLArenaPool *arena = NULL;
 	SECItem		digest;
@@ -824,20 +825,24 @@ be_tls_get_certificate_hash(Port *port, size_t *len)
 		return NULL;
 
 	signature_alg = SECOID_GetAlgorithmTag(&certificate->signature);
-	/* Set sha-256 as a default */
-	digest_alg = SEC_OID_SHA256;
-	digest_len = SHA256_LENGTH;
 
-	while (NSS_SCRAMDigestAlgorithm->signature)
+	candidate = NSS_SCRAMDigestAlgorithm;
+	while (candidate->signature)
 	{
-		if (signature_alg == NSS_SCRAMDigestAlgorithm->signature)
+		if (signature_alg == candidate->signature)
 		{
-			digest_alg = NSS_SCRAMDigestAlgorithm->hash;
-			digest_len = NSS_SCRAMDigestAlgorithm->len;
+			digest_alg = candidate->hash;
+			digest_len = candidate->len;
 			break;
 		}
+
+		candidate++;
 	}
 
+	if (!candidate->signature)
+		elog(ERROR, "could not find digest for OID '%s'",
+			 SECOID_FindOIDTagDescription(signature_alg));
+
 	arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
 	digest.data = PORT_ArenaZAlloc(arena, sizeof(unsigned char) * digest_len);
 	digest.len = digest_len;
diff --git a/src/interfaces/libpq/fe-secure-nss.c b/src/interfaces/libpq/fe-secure-nss.c
index 787bc140a6..2f10e94f72 100644
--- a/src/interfaces/libpq/fe-secure-nss.c
+++ b/src/interfaces/libpq/fe-secure-nss.c
@@ -540,6 +540,7 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 	SECOidTag	signature_alg;
 	SECOidTag	digest_alg;
 	int			digest_len;
+	const NSSSignatureAlgorithms *candidate;
 	PLArenaPool *arena;
 	SECItem		digest;
 	char	   *ret;
@@ -552,17 +553,26 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
 		return NULL;
 
 	signature_alg = SECOID_GetAlgorithmTag(&server_cert->signature);
-	digest_alg = SEC_OID_SHA256;
-	digest_len = SHA256_LENGTH;
 
-	while (NSS_SCRAMDigestAlgorithm->signature)
+	candidate = NSS_SCRAMDigestAlgorithm;
+	while (candidate->signature)
 	{
-		if (signature_alg == NSS_SCRAMDigestAlgorithm->signature)
+		if (signature_alg == candidate->signature)
 		{
-			digest_alg = NSS_SCRAMDigestAlgorithm->hash;
-			digest_len = NSS_SCRAMDigestAlgorithm->len;
+			digest_alg = candidate->hash;
+			digest_len = candidate->len;
 			break;
 		}
+
+		candidate++;
+	}
+
+	if (!candidate->signature)
+	{
+		printfPQExpBuffer(&conn->errorMessage,
+						  libpq_gettext("could not find digest for OID '%s'\n"),
+						  SECOID_FindOIDTagDescription(signature_alg));
+		return NULL;
 	}
 
 	arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
-- 
2.24.1