Browse code

Choose a different field in X509 to be username

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>

Emilien Mantel authored on 2010/06/18 04:38:59
Showing 4 changed files
... ...
@@ -49,6 +49,7 @@
49 49
 #include "helper.h"
50 50
 #include "manage.h"
51 51
 #include "configure.h"
52
+#include <ctype.h>
52 53
 
53 54
 #include "memdbg.h"
54 55
 
... ...
@@ -511,6 +512,8 @@ static const char usage_message[] =
511 511
   "--key file      : Local private key in .pem format.\n"
512 512
   "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"
513 513
   "                  and optionally the root CA certificate.\n"
514
+  "--x509-username-field : Field used in x509 certificat to be username.\n"
515
+  "                        Default is CN.\n"
514 516
 #ifdef WIN32
515 517
   "--cryptoapicert select-string : Load the certificate and private key from the\n"
516 518
   "                  Windows Certificate System Store.\n"
... ...
@@ -767,6 +770,7 @@ init_options (struct options *o, const bool init_gc)
767 767
   o->renegotiate_seconds = 3600;
768 768
   o->handshake_window = 60;
769 769
   o->transition_window = 3600;
770
+  o->x509_username_field = X509_USERNAME_FIELD_DEFAULT;
770 771
 #endif
771 772
 #endif
772 773
 #ifdef ENABLE_PKCS11
... ...
@@ -5921,6 +5925,13 @@ add_option (struct options *options,
5921 5921
 	}
5922 5922
       options->key_method = key_method;
5923 5923
     }
5924
+  else if (streq (p[0], "x509-username-field") && p[1])
5925
+    {
5926
+      char *s = p[1];
5927
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5928
+      while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */
5929
+      options->x509_username_field = p[1];
5930
+    }
5924 5931
 #endif /* USE_SSL */
5925 5932
 #endif /* USE_CRYPTO */
5926 5933
 #ifdef ENABLE_PKCS11
... ...
@@ -512,6 +512,9 @@ struct options
512 512
      within n seconds of handshake initiation. */
513 513
   int handshake_window;
514 514
 
515
+  /* Field used to be the username in X509 cert. */
516
+  char *x509_username_field;
517
+
515 518
   /* Old key allowed to live n seconds after new key goes active */
516 519
   int transition_window;
517 520
 
... ...
@@ -734,6 +734,8 @@ get_peer_cert(X509_STORE_CTX *ctx, const char *tmp_dir, struct gc_arena *gc)
734 734
   return peercert_filename;
735 735
 }
736 736
 
737
+char * x509_username_field; /* GLOBAL */
738
+
737 739
 /*
738 740
  * Our verify callback function -- check
739 741
  * that an incoming peer certificate is good.
... ...
@@ -744,7 +746,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
744 744
 {
745 745
   char *subject = NULL;
746 746
   char envname[64];
747
-  char common_name[TLS_CN_LEN];
747
+  char common_name[TLS_USERNAME_LEN];
748 748
   SSL *ssl;
749 749
   struct tls_session *session;
750 750
   const struct tls_options *opt;
... ...
@@ -776,18 +778,20 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
776 776
   string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
777 777
   string_replace_leading (subject, '-', '_');
778 778
 
779
-  /* extract the common name */
780
-  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), "CN", common_name, TLS_CN_LEN))
779
+  /* extract the username (default is CN) */
780
+  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), x509_username_field, common_name, TLS_USERNAME_LEN))
781 781
     {
782 782
       if (!ctx->error_depth)
783
-	{
784
-	  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",
785
-	       subject,
786
-	       TLS_CN_LEN);
787
-	  goto err;
788
-	}
783
+        {
784
+          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",
785
+                 x509_username_field,
786
+                 subject,
787
+                 TLS_USERNAME_LEN);
788
+          goto err;
789
+        }
789 790
     }
790 791
 
792
+
791 793
   string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags);
792 794
 
793 795
   cert_hash_remember (session, ctx->error_depth, ctx->current_cert->sha1_hash);
... ...
@@ -1844,7 +1848,8 @@ init_ssl (const struct options *options)
1844 1844
     }
1845 1845
   else
1846 1846
 #endif
1847
-    SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1847
+  x509_username_field = (char *) options->x509_username_field;
1848
+  SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1848 1849
 			verify_callback);
1849 1850
 
1850 1851
   /* Connection information callback */
... ...
@@ -3789,9 +3794,9 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3789 3789
 	s2 = verify_user_pass_script (session, up);
3790 3790
 
3791 3791
       /* check sizing of username if it will become our common name */
3792
-      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_CN_LEN)
3792
+      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_USERNAME_LEN)
3793 3793
 	{
3794
-	  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);
3794
+	  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);
3795 3795
 	  s1 = OPENVPN_PLUGIN_FUNC_ERROR;
3796 3796
 	}
3797 3797
 
... ...
@@ -278,8 +278,8 @@
278 278
  * Buffer sizes (also see mtu.h).
279 279
  */
280 280
 
281
-/* Maximum length of common name */
282
-#define TLS_CN_LEN 64
281
+/* Maximum length of the username in cert */
282
+#define TLS_USERNAME_LEN 64
283 283
 
284 284
 /* Legal characters in an X509 or common name */
285 285
 #define X509_NAME_CHAR_CLASS   (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_COLON|CC_SLASH|CC_EQUAL)
... ...
@@ -288,6 +288,9 @@
288 288
 /* Maximum length of OCC options string passed as part of auth handshake */
289 289
 #define TLS_OPTIONS_LEN 512
290 290
 
291
+/* Default field in X509 to be username */
292
+#define X509_USERNAME_FIELD_DEFAULT "CN"
293
+
291 294
 /*
292 295
  * Range of key exchange methods
293 296
  */