]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Choose a different field in X509 to be username
authorEmilien Mantel <emilien.mantel@businessdecision.com>
Thu, 17 Jun 2010 19:38:59 +0000 (21:38 +0200)
committerDavid Sommerseth <dazo@users.sourceforge.net>
Thu, 21 Oct 2010 19:26:59 +0000 (21:26 +0200)
For my company, we use a PKI (linked to a LDAP) with OpenVPN. We can't use "CN" to be
username (few people can have the same "CN"). In our case, we only use the UID.

With my patch, you can choose another field to be username with a new option called
--x509-username-field, the default value is "CN".

Signed-off-by: Emilien Mantel <emilien.mantel@businessdecision.com>
Acked-by: David Sommerseth <dazo@users.sourceforge.net>
Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
options.c
options.h
ssl.c
ssl.h

index 8c5af91e22a5ca84b82833940feee642989b07a6..717c5d70de6b9e64ac9307dc09c27b2c1bfbc781 100644 (file)
--- a/options.c
+++ b/options.c
@@ -49,6 +49,7 @@
 #include "helper.h"
 #include "manage.h"
 #include "configure.h"
+#include <ctype.h>
 
 #include "memdbg.h"
 
@@ -511,6 +512,8 @@ static const char usage_message[] =
   "--key file      : Local private key in .pem format.\n"
   "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"
   "                  and optionally the root CA certificate.\n"
+  "--x509-username-field : Field used in x509 certificat to be username.\n"
+  "                        Default is CN.\n"
 #ifdef WIN32
   "--cryptoapicert select-string : Load the certificate and private key from the\n"
   "                  Windows Certificate System Store.\n"
@@ -767,6 +770,7 @@ init_options (struct options *o, const bool init_gc)
   o->renegotiate_seconds = 3600;
   o->handshake_window = 60;
   o->transition_window = 3600;
+  o->x509_username_field = X509_USERNAME_FIELD_DEFAULT;
 #endif
 #endif
 #ifdef ENABLE_PKCS11
@@ -5921,6 +5925,13 @@ add_option (struct options *options,
        }
       options->key_method = key_method;
     }
+  else if (streq (p[0], "x509-username-field") && p[1])
+    {
+      char *s = p[1];
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */
+      options->x509_username_field = p[1];
+    }
 #endif /* USE_SSL */
 #endif /* USE_CRYPTO */
 #ifdef ENABLE_PKCS11
index 52763f3b1b5e2d2af8016698ee661970f7f4c6d4..cb29d797d4a7c7cb0e6595d3f6256ddfec57d200 100644 (file)
--- a/options.h
+++ b/options.h
@@ -512,6 +512,9 @@ struct options
      within n seconds of handshake initiation. */
   int handshake_window;
 
+  /* Field used to be the username in X509 cert. */
+  char *x509_username_field;
+
   /* Old key allowed to live n seconds after new key goes active */
   int transition_window;
 
diff --git a/ssl.c b/ssl.c
index cf4c7bf6096eac0317723abd2dbf2e86e391d73c..e6285040fb9f20ed7ba809c6aacbf247c42241ae 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -734,6 +734,8 @@ get_peer_cert(X509_STORE_CTX *ctx, const char *tmp_dir, struct gc_arena *gc)
   return peercert_filename;
 }
 
+char * x509_username_field; /* GLOBAL */
+
 /*
  * Our verify callback function -- check
  * that an incoming peer certificate is good.
@@ -744,7 +746,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
 {
   char *subject = NULL;
   char envname[64];
-  char common_name[TLS_CN_LEN];
+  char common_name[TLS_USERNAME_LEN];
   SSL *ssl;
   struct tls_session *session;
   const struct tls_options *opt;
@@ -776,18 +778,20 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
   string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
   string_replace_leading (subject, '-', '_');
 
-  /* extract the common name */
-  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), "CN", common_name, TLS_CN_LEN))
+  /* extract the username (default is CN) */
+  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), x509_username_field, common_name, TLS_USERNAME_LEN))
     {
       if (!ctx->error_depth)
-       {
-         msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract Common Name from X509 subject string ('%s') -- note that the Common Name length is limited to %d characters",
-              subject,
-              TLS_CN_LEN);
-         goto err;
-       }
+        {
+          msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract %s from X509 subject string ('%s') -- note that the username length is limited to %d characters",
+                 x509_username_field,
+                 subject,
+                 TLS_USERNAME_LEN);
+          goto err;
+        }
     }
 
+
   string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags);
 
   cert_hash_remember (session, ctx->error_depth, ctx->current_cert->sha1_hash);
@@ -1844,7 +1848,8 @@ init_ssl (const struct options *options)
     }
   else
 #endif
-    SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+  x509_username_field = (char *) options->x509_username_field;
+  SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                        verify_callback);
 
   /* Connection information callback */
@@ -3789,9 +3794,9 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
        s2 = verify_user_pass_script (session, up);
 
       /* check sizing of username if it will become our common name */
-      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_CN_LEN)
+      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_USERNAME_LEN)
        {
-         msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_CN_LEN);
+         msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_USERNAME_LEN);
          s1 = OPENVPN_PLUGIN_FUNC_ERROR;
        }
 
diff --git a/ssl.h b/ssl.h
index 19a85401bdb05b228fcde8d11c908a4be0a85514..8415d5555908ecbf9c7779106e6a452f082e488a 100644 (file)
--- a/ssl.h
+++ b/ssl.h
  * Buffer sizes (also see mtu.h).
  */
 
-/* Maximum length of common name */
-#define TLS_CN_LEN 64
+/* Maximum length of the username in cert */
+#define TLS_USERNAME_LEN 64
 
 /* Legal characters in an X509 or common name */
 #define X509_NAME_CHAR_CLASS   (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_COLON|CC_SLASH|CC_EQUAL)
 /* Maximum length of OCC options string passed as part of auth handshake */
 #define TLS_OPTIONS_LEN 512
 
+/* Default field in X509 to be username */
+#define X509_USERNAME_FIELD_DEFAULT "CN"
+
 /*
  * Range of key exchange methods
  */