From a6dbec1cb481d6f0237372a7dec059f1c572b7b7 Mon Sep 17 00:00:00 2001
From: Steffan Karger <steffan.karger@fox-it.com>
Date: Mon, 19 Jun 2017 11:28:39 +0200
Subject: [PATCH 2/5] Restrict --x509-alt-username extension types

The code never supported all extension types.  Make this explicit by only
allowing subjectAltName and issuerAltName (for which the current code does
work).

Using unsupported extension fields would most likely cause OpenVPN to crash
as soon as a client connects.  This does not have a real-world security
impact, as such a configuration would not be possible to use in practice.

This bug was discovered, analysed and reported to the OpenVPN team by
Guido Vranken.

Note: small code changes in to avoid "variable declaration in the middle
of a code block" when backporting changes to extract_x509_extension(),
as 2.3 can not assume a C99 compiler.

Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Acked-by: David Sommerseth <davids@openvpn.net>
Acked-by: Guido Vranken <guidovranken@gmail.com>
Message-Id: <1497864520-12219-5-git-send-email-steffan.karger@fox-it.com>
URL: https://www.mail-archive.com/search?l=mid&q=1497864520-12219-5-git-send-email-steffan.karger@fox-it.com
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit d2a19185fd78030ce4a1bba6c9f83e0dac9e15a6)
---
 doc/openvpn.8                    |  2 ++
 src/openvpn/options.c            |  4 ++++
 src/openvpn/ssl_verify_backend.h |  8 ++++++++
 src/openvpn/ssl_verify_openssl.c | 18 +++++++++++++++++-
 4 files changed, 31 insertions(+), 1 deletion(-)

Index: openvpn-2.3.2/doc/openvpn.8
===================================================================
--- openvpn-2.3.2.orig/doc/openvpn.8	2017-06-21 19:57:37.350346754 +0200
+++ openvpn-2.3.2/doc/openvpn.8	2017-06-21 19:57:42.239422794 +0200
@@ -3491,6 +3491,8 @@ It ensures compatibility with server con
 .B \-\-no\-name\-remapping
 option.
 
+Only the subjectAltName and issuerAltName X.509 extensions are supported.
+
 .B Please note:
 This option is now deprecated.  It will be removed either in OpenVPN v2.4
 or v2.5.  So please make sure you support the new X.509 name formatting
Index: openvpn-2.3.2/src/openvpn/options.c
===================================================================
--- openvpn-2.3.2.orig/src/openvpn/options.c	2017-06-21 19:57:42.240422809 +0200
+++ openvpn-2.3.2/src/openvpn/options.c	2017-06-21 19:57:58.874681518 +0200
@@ -6738,6 +6738,10 @@ add_option (struct options *options,
       VERIFY_PERMISSION (OPT_P_GENERAL);
       if( strncmp ("ext:",s,4) != 0 )
         while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */
+      else if (!x509_username_field_ext_supported(s+4))
+        {
+          msg(msglevel, "Unsupported x509-username-field extension: %s", s);
+        }
       options->x509_username_field = p[1];
     }
 #endif /* ENABLE_X509ALTUSERNAME */
Index: openvpn-2.3.2/src/openvpn/ssl_verify_backend.h
===================================================================
--- openvpn-2.3.2.orig/src/openvpn/ssl_verify_backend.h	2017-06-21 19:57:37.351346770 +0200
+++ openvpn-2.3.2/src/openvpn/ssl_verify_backend.h	2017-06-21 19:57:42.241422825 +0200
@@ -112,6 +112,14 @@ unsigned char *x509_get_sha1_hash (openv
 result_t x509_get_username (char *common_name, int cn_len,
     char * x509_username_field, openvpn_x509_cert_t *peer_cert);
 
+#ifdef ENABLE_X509ALTUSERNAME
+/**
+ * Return true iff the supplied extension field is supported by the
+ * --x509-username-field option.
+ */
+bool x509_username_field_ext_supported(const char *extname);
+#endif
+
 /*
  * Return the certificate's serial number.
  *
Index: openvpn-2.3.2/src/openvpn/ssl_verify_openssl.c
===================================================================
--- openvpn-2.3.2.orig/src/openvpn/ssl_verify_openssl.c	2017-06-21 19:57:42.242422840 +0200
+++ openvpn-2.3.2/src/openvpn/ssl_verify_openssl.c	2017-06-21 19:58:15.735943741 +0200
@@ -93,6 +93,13 @@ cleanup:
 }
 
 #ifdef ENABLE_X509ALTUSERNAME
+bool
+x509_username_field_ext_supported(const char *fieldname)
+{
+  int nid = OBJ_txt2nid(fieldname);
+  return nid == NID_subject_alt_name || nid == NID_issuer_alt_name;
+}
+
 static
 bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size)
 {
@@ -101,8 +108,17 @@ bool extract_x509_extension(X509 *cert,
   char *buf = 0;
   int length = 0;
   GENERAL_NAMES *extensions;
-  int nid = OBJ_txt2nid(fieldname);
+  int nid;
+
+  if (!x509_username_field_ext_supported(fieldname))
+    {
+      msg(D_TLS_ERRORS,
+          "ERROR: --x509-alt-username field 'ext:%s' not supported",
+          fieldname);
+      return false;
+    }
 
+  nid = OBJ_txt2nid(fieldname);
   extensions = (GENERAL_NAMES *)X509_get_ext_d2i(cert, nid, NULL, NULL);
   if ( extensions )
     {
