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
... ...
@@ -46,6 +46,7 @@
46 46
 #include "helper.h"
47 47
 #include "manage.h"
48 48
 #include "configure.h"
49
+#include <ctype.h>
49 50
 
50 51
 #include "memdbg.h"
51 52
 
... ...
@@ -500,6 +501,8 @@ static const char usage_message[] =
500 500
   "--key file      : Local private key in .pem format.\n"
501 501
   "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"
502 502
   "                  and optionally the root CA certificate.\n"
503
+  "--x509-username-field : Field used in x509 certificat to be username.\n"
504
+  "                        Default is CN.\n"
503 505
 #ifdef WIN32
504 506
   "--cryptoapicert select-string : Load the certificate and private key from the\n"
505 507
   "                  Windows Certificate System Store.\n"
... ...
@@ -753,6 +756,7 @@ init_options (struct options *o, const bool init_gc)
753 753
   o->renegotiate_seconds = 3600;
754 754
   o->handshake_window = 60;
755 755
   o->transition_window = 3600;
756
+  o->x509_username_field = X509_USERNAME_FIELD_DEFAULT;
756 757
 #endif
757 758
 #endif
758 759
 #ifdef ENABLE_PKCS11
... ...
@@ -5667,6 +5671,13 @@ add_option (struct options *options,
5667 5667
 	}
5668 5668
       options->key_method = key_method;
5669 5669
     }
5670
+  else if (streq (p[0], "x509-username-field") && p[1])
5671
+    {
5672
+      char *s = p[1];
5673
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5674
+      while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */
5675
+      options->x509_username_field = p[1];
5676
+    }
5670 5677
 #endif /* USE_SSL */
5671 5678
 #endif /* USE_CRYPTO */
5672 5679
 #ifdef ENABLE_PKCS11
... ...
@@ -484,6 +484,9 @@ struct options
484 484
      within n seconds of handshake initiation. */
485 485
   int handshake_window;
486 486
 
487
+  /* Field used to be the username in X509 cert. */
488
+  char *x509_username_field;
489
+
487 490
   /* Old key allowed to live n seconds after new key goes active */
488 491
   int transition_window;
489 492
 
... ...
@@ -730,6 +730,8 @@ get_peer_cert(X509_STORE_CTX *ctx, const char *tmp_dir, struct gc_arena *gc)
730 730
   return peercert_filename;
731 731
 }
732 732
 
733
+char * x509_username_field; /* GLOBAL */
734
+
733 735
 /*
734 736
  * Our verify callback function -- check
735 737
  * that an incoming peer certificate is good.
... ...
@@ -740,7 +742,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
740 740
 {
741 741
   char *subject = NULL;
742 742
   char envname[64];
743
-  char common_name[TLS_CN_LEN];
743
+  char common_name[TLS_USERNAME_LEN];
744 744
   SSL *ssl;
745 745
   struct tls_session *session;
746 746
   const struct tls_options *opt;
... ...
@@ -772,18 +774,20 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
772 772
   string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
773 773
   string_replace_leading (subject, '-', '_');
774 774
 
775
-  /* extract the common name */
776
-  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), "CN", common_name, TLS_CN_LEN))
775
+  /* extract the username (default is CN) */
776
+  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), x509_username_field, common_name, TLS_USERNAME_LEN))
777 777
     {
778 778
       if (!ctx->error_depth)
779
-	{
780
-	  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",
781
-	       subject,
782
-	       TLS_CN_LEN);
783
-	  goto err;
784
-	}
779
+        {
780
+          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",
781
+                 x509_username_field,
782
+                 subject,
783
+                 TLS_USERNAME_LEN);
784
+          goto err;
785
+        }
785 786
     }
786 787
 
788
+
787 789
   string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags);
788 790
 
789 791
   cert_hash_remember (session, ctx->error_depth, ctx->current_cert->sha1_hash);
... ...
@@ -1786,7 +1790,8 @@ init_ssl (const struct options *options)
1786 1786
     }
1787 1787
   else
1788 1788
 #endif
1789
-    SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1789
+  x509_username_field = (char *) options->x509_username_field;
1790
+  SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1790 1791
 			verify_callback);
1791 1792
 
1792 1793
   /* Connection information callback */
... ...
@@ -3594,9 +3599,9 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3594 3594
 	s2 = verify_user_pass_script (session, up);
3595 3595
 
3596 3596
       /* check sizing of username if it will become our common name */
3597
-      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_CN_LEN)
3597
+      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_USERNAME_LEN)
3598 3598
 	{
3599
-	  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);
3599
+	  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);
3600 3600
 	  s1 = OPENVPN_PLUGIN_FUNC_ERROR;
3601 3601
 	}
3602 3602
 
... ...
@@ -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
  */