]> 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, 17 Jun 2010 19:46:09 +0000 (21:46 +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 86279e437739f22c2001ba471f7fff4a83053416..ea2dcbe18809f665d16c42dc427061825fc71ad4 100644 (file)
--- a/options.c
+++ b/options.c
@@ -46,6 +46,7 @@
 #include "helper.h"
 #include "manage.h"
 #include "configure.h"
+#include <ctype.h>
 
 #include "memdbg.h"
 
@@ -500,6 +501,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"
@@ -753,6 +756,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
@@ -5667,6 +5671,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 a3114e2fc415fc953d3effff6076d924a3cd0af8..10109e7d2ce7ecabb83c558092881c12543fa81e 100644 (file)
--- a/options.h
+++ b/options.h
@@ -484,6 +484,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 276322f63fbe037713d71ffa40c759701eb43a46..970270b285391a1dc098985301683228d30da458 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -730,6 +730,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.
@@ -740,7 +742,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;
@@ -772,18 +774,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);
@@ -1786,7 +1790,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 */
@@ -3594,9 +3599,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 a22c8546b0f8c389db83f249070b7d43b9cb0e11..93aac783c528778571dbe76865cdfae46e316335 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
  */