summaryrefslogtreecommitdiff
path: root/net-vpn/openconnect/files/8.09-gnutls-buffer-overflow.patch
blob: bf8990ae3d3c4f07f9f58d9ce3fae6b1f3cd6304 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
From eef4c1f9d24478aa1d2dd9ac7ec32efb2137f474 Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <slyfox@gentoo.org>
Date: Fri, 8 May 2020 10:39:41 -0400
Subject: [PATCH] gnutls: prevent buffer overflow in get_cert_name

The test suite for ocserv calls openconnect with a certificate that has
a name that is 84 bytes in length. The buffer passed to get_cert_name is
currently 80 bytes.

The gnutls_x509_crt_get_dn_by_oid function will update the buffer size
parameter if the buffer is too small.

http://man7.org/linux/man-pages/man3/gnutls_x509_crt_get_dn_by_oid.3.html

RETURNS
       GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long
       enough, and in that case the  buf_size will be updated with the
       required size. GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if there are no
       data in the current index. On success 0 is returned.

Use a temporary variable to avoid clobbering the namelen variable that is
passed to get_cert_name.

Bug: https://bugs.gentoo.org/721570
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
Signed-off-by: Mike Gilbert <floppym@gentoo.org>
---
 gnutls.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/gnutls.c b/gnutls.c
index 36bc82e0..53bf2a43 100644
--- a/gnutls.c
+++ b/gnutls.c
@@ -546,12 +546,19 @@ static int count_x509_certificates(gnutls_datum_t *datum)
 
 static int get_cert_name(gnutls_x509_crt_t cert, char *name, size_t namelen)
 {
+	/* When the name buffer is not big enough, gnutls_x509_crt_get_dn*() will
+	 * update the length argument to the required size, and return
+	 * GNUTLS_E_SHORT_MEMORY_BUFFER. We need to avoid clobbering the original
+	 * length variable. */
+	size_t nl = namelen;
 	if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
-					  0, 0, name, &namelen) &&
-	    gnutls_x509_crt_get_dn(cert, name, &namelen)) {
-		name[namelen-1] = 0;
-		snprintf(name, namelen-1, "<unknown>");
-		return -EINVAL;
+					  0, 0, name, &nl)) {
+		nl = namelen;
+		if (gnutls_x509_crt_get_dn(cert, name, &nl)) {
+			name[namelen-1] = 0;
+			snprintf(name, namelen-1, "<unknown>");
+			return -EINVAL;
+		}
 	}
 	return 0;
 }
-- 
2.26.2