]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
gnutls: prevent buffer overflow in get_cert_name
authorSergei Trofimovich <slyfox@gentoo.org>
Fri, 8 May 2020 14:39:41 +0000 (10:39 -0400)
committerMike Gilbert <floppym@gentoo.org>
Fri, 8 May 2020 19:55:13 +0000 (15:55 -0400)
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

index 36bc82e06a833033ae7d1b8120b0f066114e4f93..53bf2a4361acb5f152e810164c9ea14904af0360 100644 (file)
--- 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;
 }