From eef4c1f9d24478aa1d2dd9ac7ec32efb2137f474 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich 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 Signed-off-by: Mike Gilbert --- 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, ""); - 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, ""); + return -EINVAL; + } } return 0; } -- 2.26.2