]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Add extv3 X509 field support to --x509-username-field
authorMarkus Koetter <koetter@rrzn-hiwi.uni-hannover.de>
Fri, 10 Dec 2010 19:30:09 +0000 (20:30 +0100)
committerDavid Sommerseth <davids@redhat.com>
Fri, 25 Mar 2011 08:05:18 +0000 (09:05 +0100)
This allows using other X509 certificate fields for the certificate
authentication.  To use altSubjectName, use
--x509-username-field ext:altSubjectName

This feature requires OpenVPN to be built with --enable-x509-alt-username

This patch is slightly modified, to honour --enable-x509-alt-username
compile time configuration.  Two #ifdef's are added.

Signed-off-by: Markus Koetter <koetter@rrzn-hiwi.uni-hannover.de>
Signed-off-by: David Sommerseth <davids@redhat.com>
Acked-by: David Sommerseth <davids@redhat.com>
Signed-off-by: David Sommerseth <davids@redhat.com>
options.c
ssl.c

index f4eeaee23b4fb4f78f7e6084defaec5db0a093e1..4c28a8f7b8ba653cbf261612246c6603d366e30b 100644 (file)
--- a/options.c
+++ b/options.c
@@ -5907,7 +5907,8 @@ add_option (struct options *options,
     {
       char *s = p[1];
       VERIFY_PERMISSION (OPT_P_GENERAL);
-      while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */
+      if( strncmp ("ext:",s,4) != 0 )
+        while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */
       options->x509_username_field = p[1];
     }
 #endif /* ENABLE_X509ALTUSERNAME */
diff --git a/ssl.c b/ssl.c
index ed107148146a77226df4c60c8e4094da0739ae71..7b2291c6b3bd86a62ca02830e3fdf3c6f1ac310a 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -520,6 +520,61 @@ extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, int
   }
 }
 
+#ifdef ENABLE_X509ALTUSERNAME
+static
+bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size)
+{
+  bool retval = false;
+  X509_EXTENSION *pExt;
+  char *buf = 0;
+  int length = 0;
+  GENERAL_NAMES *extensions;
+  int nid = OBJ_txt2nid(fieldname);
+
+  extensions = (GENERAL_NAMES *)X509_get_ext_d2i(cert, nid, NULL, NULL);
+  if ( extensions )
+    {
+      int numalts;
+      int i;
+      /* get amount of alternatives,
+       * RFC2459 claims there MUST be at least
+       * one, but we don't depend on it...
+       */
+
+      numalts = sk_GENERAL_NAME_num(extensions);
+
+      /* loop through all alternatives */
+      for (i=0; i<numalts; i++)
+        {
+          /* get a handle to alternative name number i */
+          const GENERAL_NAME *name = sk_GENERAL_NAME_value (extensions, i );
+
+          switch (name->type)
+            {
+              case GEN_EMAIL:
+                ASN1_STRING_to_UTF8((unsigned char**)&buf, name->d.ia5);
+                if ( strlen (buf) != name->d.ia5->length )
+                  {
+                    msg (D_TLS_ERRORS, "ASN1 ERROR: string contained terminating zero");
+                    OPENSSL_free (buf);
+                  } else {
+                    strncpynt(out, buf, size);
+                    OPENSSL_free(buf);
+                    retval = true;
+                  }
+                break;
+              default:
+                msg (D_TLS_ERRORS, "ASN1 ERROR: can not handle field type %i",
+                     name->type);
+                break;
+            }
+          }
+        sk_GENERAL_NAME_free (extensions);
+    }
+  return retval;
+}
+#endif
+
 /*
  * Save X509 fields to environment, using the naming convention:
  *
@@ -805,6 +860,20 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
   string_replace_leading (subject, '-', '_');
 
   /* extract the username (default is CN) */
+#ifdef ENABLE_X509ALTUSERNAME
+  if (strncmp("ext:",x509_username_field,4) == 0)
+    {
+      if (!extract_x509_extension (ctx->current_cert, x509_username_field+4, common_name, sizeof(common_name)))
+        {
+          msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract %s extension from X509 subject string ('%s') "
+                             "-- note that the username length is limited to %d characters",
+                             x509_username_field+4,
+                             subject,
+                             TLS_USERNAME_LEN);
+          goto err;
+        }
+    } else
+#endif
   if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), x509_username_field, common_name, sizeof(common_name)))
     {
       if (!ctx->error_depth)