Browse code

add new option for X.509 name verification

Add the option --verify-x509-name to provide the functionality
of the now deprecated --tls-remote.

The new option accepts RFC 2253 subject DNs only and compares
RDN or RDN prefix only if configured explicitly.

Signed-off-by: Heiko Hund <heiko.hund@sophos.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: 1362670601-18660-1-git-send-email-heiko.hund@sophos.com
URL: http://article.gmane.org/gmane.network.openvpn.devel/7376
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Heiko Hund authored on 2013/03/08 00:36:41
Showing 7 changed files
... ...
@@ -3431,7 +3431,7 @@ the authenticated username as the common name,
3431 3431
 rather than the common name from the client cert.
3432 3432
 .\"*********************************************************
3433 3433
 .TP
3434
-.B \-\-compat\-names [no\-remapping]
3434
+.B \-\-compat\-names [no\-remapping] (DEPRECATED)
3435 3435
 Until OpenVPN v2.3 the format of the X.509 Subject fields was formatted
3436 3436
 like this:
3437 3437
 .IP
... ...
@@ -3467,17 +3467,20 @@ The
3467 3467
 mode flag can be used with the
3468 3468
 .B
3469 3469
 \-\-compat\-names
3470
-option to be compatible with the now deprecated \-\-no\-name\-remapping feature
3471
-present in older OpenVPN versions. When this mode flag is used, the Common Name,
3470
+option to be compatible with the now deprecated \-\-no\-name\-remapping option.
3471
+It is only available at the server. When this mode flag is used, the Common Name,
3472 3472
 Subject, and username strings are allowed to include any printable character
3473 3473
 including space, but excluding control characters such as tab, newline, and
3474
-carriage-return.
3474
+carriage-return. no-remapping is only available on the server side.
3475 3475
 
3476 3476
 .B Please note:
3477
-This option will not be around for a long time.  It is only implemented
3477
+This option is immediately deprecated.  It is only implemented
3478 3478
 to make the transition to the new formatting less intrusive.  It will be
3479
-removed either in OpenVPN v2.4 or v2.5.  So please make sure you start
3480
-the process to support the new formatting as soon as possible.
3479
+removed either in OpenVPN v2.4 or v2.5.  So please make sure you use the
3480
+.B \-\-verify-x509-name
3481
+option instead of
3482
+.B \-\-tls-remote
3483
+as soon as possible and update your scripts where necessary.
3481 3484
 .\"*********************************************************
3482 3485
 .TP
3483 3486
 .B \-\-no\-name\-remapping (DEPRECATED)
... ...
@@ -3485,7 +3488,7 @@ The
3485 3485
 .B \-\-no\-name\-remapping
3486 3486
 option is an alias for
3487 3487
 .B \-\-compat\-names\ no\-remapping.
3488
-It ensures compatibility with configurations using the
3488
+It ensures compatibility with server configurations using the
3489 3489
 .B \-\-no\-name\-remapping
3490 3490
 option.
3491 3491
 
... ...
@@ -4671,11 +4674,11 @@ is available via the peer_cert environment variable.
4671 4671
 Field in x509 certificate subject to be used as username (default=CN).
4672 4672
 .B Fieldname
4673 4673
 will be uppercased before matching. When this option is used, the
4674
-of the CN.
4674
+.B \-\-verify-x509-username
4675
+option will match against the chosen fieldname instead of the CN.
4675 4676
 .\"*********************************************************
4676 4677
 .TP
4677
-.B \-\-tls-remote name
4678
+.B \-\-tls-remote name (DEPRECATED)
4678 4679
 Accept connections only from a host with X509 name
4679 4680
 or common name equal to
4680 4681
 .B name.
... ...
@@ -4707,6 +4710,59 @@ option to verify the remote host, because
4707 4707
 works in a
4708 4708
 .B \-\-chroot
4709 4709
 environment too.
4710
+
4711
+.B Please also note:
4712
+This option is now deprecated.  It will be removed either in OpenVPN v2.4
4713
+or v2.5.  So please make sure you support the new X.509 name formatting
4714
+described with the
4715
+.B \-\-compat-names
4716
+option as soon as possible by updating your configurations to use
4717
+.B \-\-verify-x509-name
4718
+instead.
4719
+.\"*********************************************************
4720
+.TP
4721
+.B \-\-verify-x509-name name type
4722
+Accept connections only if a host's X.509 name is equal to
4723
+.B name.
4724
+The remote host must also pass all other tests of verification.
4725
+
4726
+Which X.509 name is compared to
4727
+.B name
4728
+depends on the setting of type.
4729
+.B type
4730
+can be "subject" to match the complete subject DN (default),
4731
+"name" to match a subject RDN or "name-prefix" to match a subject RDN prefix.
4732
+Which RDN is verified as name depends on the
4733
+.B \-\-x509-username-field
4734
+option. But it defaults to the common name (CN), e.g. a certificate with a
4735
+subject DN "C=KG, ST=NA, L=Bishkek, CN=Server-1" would be matched by:
4736
+
4737
+.B \-\-verify-x509-name 'C=KG, ST=NA, L=Bishkek, CN=Server-1'
4738
+and
4739
+.B \-\-verify-x509-name Server-1 name
4740
+or you could use
4741
+.B \-\-verify-x509-name Server- name-prefix
4742
+if you want a client to only accept connections to "Server-1", "Server-2", etc.
4743
+
4744
+.B \-\-verify-x509-name
4745
+is a useful replacement for the
4746
+.B \-\-tls-verify
4747
+option to verify the remote host, because
4748
+.B \-\-verify-x509-name
4749
+works in a
4750
+.B \-\-chroot
4751
+environment without any dependencies.
4752
+
4753
+Using a name prefix is a useful alternative to managing
4754
+a CRL (Certificate Revocation List) on the client, since it allows the client
4755
+to refuse all certificates except for those associated
4756
+with designated servers.
4757
+
4758
+.B NOTE:
4759
+Test against a name prefix only when you are using OpenVPN with
4760
+a custom CA certificate that is under your control.
4761
+Never use this option with type "name-prefix" when your client certificates
4762
+are signed by a third party, such as a commercial web CA.
4710 4763
 .\"*********************************************************
4711 4764
 .TP
4712 4765
 .B \-\-x509-track attribute
... ...
@@ -4744,7 +4800,7 @@ a man-in-the-middle attack where an authorized client
4744 4744
 attempts to connect to another client by impersonating the server.
4745 4745
 The attack is easily prevented by having clients verify
4746 4746
 the server certificate using any one of
4747
-.B \-\-ns-cert-type, \-\-tls-remote,
4747
+.B \-\-ns-cert-type, \-\-verify-x509-name,
4748 4748
 or
4749 4749
 .B \-\-tls-verify.
4750 4750
 .\"*********************************************************
... ...
@@ -4802,7 +4858,7 @@ a man-in-the-middle attack where an authorized client
4802 4802
 attempts to connect to another client by impersonating the server.
4803 4803
 The attack is easily prevented by having clients verify
4804 4804
 the server certificate using any one of
4805
-.B \-\-remote-cert-tls, \-\-tls-remote,
4805
+.B \-\-remote-cert-tls, \-\-verify-x509-name,
4806 4806
 or
4807 4807
 .B \-\-tls-verify.
4808 4808
 .\"*********************************************************
... ...
@@ -2205,7 +2205,8 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
2205 2205
 
2206 2206
   to.verify_command = options->tls_verify;
2207 2207
   to.verify_export_cert = options->tls_export_cert;
2208
-  to.verify_x509name = options->tls_remote;
2208
+  to.verify_x509_type = (options->verify_x509_type & 0xff);
2209
+  to.verify_x509_name = options->verify_x509_name;
2209 2210
   to.crl_file = options->crl_file;
2210 2211
   to.ssl_flags = options->ssl_flags;
2211 2212
   to.ns_cert_type = options->ns_cert_type;
... ...
@@ -2467,12 +2468,10 @@ do_option_warnings (struct context *c)
2467 2467
     warn_on_use_of_common_subnets ();
2468 2468
   if (o->tls_client
2469 2469
       && !o->tls_verify
2470
-      && !o->tls_remote
2470
+      && o->verify_x509_type == VERIFY_X509_NONE
2471 2471
       && !(o->ns_cert_type & NS_CERT_CHECK_SERVER)
2472 2472
       && !o->remote_cert_eku)
2473 2473
     msg (M_WARN, "WARNING: No server certificate verification method has been enabled.  See http://openvpn.net/howto.html#mitm for more info.");
2474
-  if (o->tls_remote)
2475
-    msg (M_WARN, "WARNING: Make sure you understand the semantics of --tls-remote before using it (see the man page).");
2476 2474
 #endif
2477 2475
 #endif
2478 2476
 
... ...
@@ -614,8 +614,8 @@ static const char usage_message[] =
614 614
   "--tls-export-cert [directory] : Get peer cert in PEM format and store it \n"
615 615
   "                  in an openvpn temporary file in [directory]. Peer cert is \n"
616 616
   "                  stored before tls-verify script execution and deleted after.\n"
617
-  "--tls-remote x509name: Accept connections only from a host with X509 name\n"
618
-  "                  x509name. The remote host must also pass all other tests\n"
617
+  "--verify-x509-name name: Accept connections only from a host with X509 subject\n"
618
+  "                  DN name. The remote host must also pass all other tests\n"
619 619
   "                  of verification.\n"
620 620
   "--ns-cert-type t: Require that peer certificate was signed with an explicit\n"
621 621
   "                  nsCertType designation t = 'client' | 'server'.\n"
... ...
@@ -1596,7 +1596,8 @@ show_settings (const struct options *o)
1596 1596
   SHOW_STR (cipher_list);
1597 1597
   SHOW_STR (tls_verify);
1598 1598
   SHOW_STR (tls_export_cert);
1599
-  SHOW_STR (tls_remote);
1599
+  SHOW_INT (verify_x509_type);
1600
+  SHOW_STR (verify_x509_name);
1600 1601
   SHOW_STR (crl_file);
1601 1602
   SHOW_INT (ns_cert_type);
1602 1603
   {
... ...
@@ -2130,7 +2131,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
2130 2130
 
2131 2131
       if (options->stale_routes_check_interval)
2132 2132
         msg (M_USAGE, "--stale-routes-check requires --mode server");
2133
-
2134 2133
       if (compat_flag (COMPAT_FLAG_QUERY | COMPAT_NO_NAME_REMAPPING))
2135 2134
         msg (M_USAGE, "--compat-x509-names no-remapping requires --mode server");
2136 2135
     }
... ...
@@ -2302,7 +2302,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
2302 2302
       MUST_BE_UNDEF (cipher_list);
2303 2303
       MUST_BE_UNDEF (tls_verify);
2304 2304
       MUST_BE_UNDEF (tls_export_cert);
2305
-      MUST_BE_UNDEF (tls_remote);
2305
+      MUST_BE_UNDEF (verify_x509_name);
2306 2306
       MUST_BE_UNDEF (tls_timeout);
2307 2307
       MUST_BE_UNDEF (renegotiate_bytes);
2308 2308
       MUST_BE_UNDEF (renegotiate_packets);
... ...
@@ -6514,27 +6514,97 @@ add_option (struct options *options,
6514 6514
   else if (streq (p[0], "compat-names"))
6515 6515
     {
6516 6516
       VERIFY_PERMISSION (OPT_P_GENERAL);
6517
+      if (options->verify_x509_type != VERIFY_X509_NONE &&
6518
+          options->verify_x509_type != TLS_REMOTE_SUBJECT_DN &&
6519
+          options->verify_x509_type != TLS_REMOTE_SUBJECT_RDN_PREFIX)
6520
+        {
6521
+          msg (msglevel, "you cannot use --compat-names with --verify-x509-name");
6522
+          goto err;
6523
+        }
6524
+      msg (M_WARN, "DEPRECATED OPTION: --compat-names, please update your configuration");
6517 6525
       compat_flag (COMPAT_FLAG_SET | COMPAT_NAMES);
6526
+#if P2MP_SERVER
6518 6527
       if (p[1] && streq (p[1], "no-remapping"))
6519 6528
         compat_flag (COMPAT_FLAG_SET | COMPAT_NO_NAME_REMAPPING);
6520 6529
     }
6521 6530
   else if (streq (p[0], "no-name-remapping"))
6522 6531
     {
6523 6532
       VERIFY_PERMISSION (OPT_P_GENERAL);
6533
+      if (options->verify_x509_type != VERIFY_X509_NONE &&
6534
+          options->verify_x509_type != TLS_REMOTE_SUBJECT_DN &&
6535
+          options->verify_x509_type != TLS_REMOTE_SUBJECT_RDN_PREFIX)
6536
+        {
6537
+          msg (msglevel, "you cannot use --no-name-remapping with --verify-x509-name");
6538
+          goto err;
6539
+        }
6524 6540
       msg (M_WARN, "DEPRECATED OPTION: --no-name-remapping, please update your configuration");
6525 6541
       compat_flag (COMPAT_FLAG_SET | COMPAT_NAMES);
6526 6542
       compat_flag (COMPAT_FLAG_SET | COMPAT_NO_NAME_REMAPPING);
6543
+#endif
6527 6544
     }
6528 6545
   else if (streq (p[0], "tls-remote") && p[1])
6529 6546
     {
6530 6547
       VERIFY_PERMISSION (OPT_P_GENERAL);
6531
-      /*
6532
-       * Enable legacy openvpn format for DNs that have not been converted
6533
-       * yet and X.509 common names (not containing an '=' or ', ')
6534
-       */
6535
-      if (p[1][0] == '/' || !strchr (p[1], '=') || !strstr (p[1], ", "))
6536
-        compat_flag (COMPAT_FLAG_SET | COMPAT_NAMES);
6537
-      options->tls_remote = p[1];
6548
+
6549
+      if (options->verify_x509_type != VERIFY_X509_NONE &&
6550
+          options->verify_x509_type != TLS_REMOTE_SUBJECT_DN &&
6551
+          options->verify_x509_type != TLS_REMOTE_SUBJECT_RDN_PREFIX)
6552
+        {
6553
+          msg (msglevel, "you cannot use --tls-remote with --verify-x509-name");
6554
+          goto err;
6555
+        }
6556
+      msg (M_WARN, "DEPRECATED OPTION: --tls-remote, please update your configuration");
6557
+
6558
+      if (strlen (p[1]))
6559
+        {
6560
+          int is_username = (!strchr (p[1], '=') || !strstr (p[1], ", "));
6561
+          int type = TLS_REMOTE_SUBJECT_DN;
6562
+          if (p[1][0] != '/' && is_username)
6563
+            type = TLS_REMOTE_SUBJECT_RDN_PREFIX;
6564
+
6565
+          /*
6566
+           * Enable legacy openvpn format for DNs that have not been converted
6567
+           * yet and --x509-username-field (not containing an '=' or ', ')
6568
+           */
6569
+          if (p[1][0] == '/' || is_username)
6570
+            compat_flag (COMPAT_FLAG_SET | COMPAT_NAMES);
6571
+
6572
+          options->verify_x509_type = type;
6573
+          options->verify_x509_name = p[1];
6574
+        }
6575
+    }
6576
+  else if (streq (p[0], "verify-x509-name") && p[1] && strlen (p[1]))
6577
+    {
6578
+      int type = VERIFY_X509_SUBJECT_DN;
6579
+      VERIFY_PERMISSION (OPT_P_GENERAL);
6580
+      if (options->verify_x509_type == TLS_REMOTE_SUBJECT_DN ||
6581
+          options->verify_x509_type == TLS_REMOTE_SUBJECT_RDN_PREFIX)
6582
+        {
6583
+          msg (msglevel, "you cannot use --verify-x509-name with --tls-remote");
6584
+          goto err;
6585
+        }
6586
+      if (compat_flag (COMPAT_FLAG_QUERY | COMPAT_NAMES))
6587
+        {
6588
+          msg (msglevel, "you cannot use --verify-x509-name with "
6589
+                         "--compat-names or --no-name-remapping");
6590
+          goto err;
6591
+        }
6592
+      if (p[2])
6593
+        {
6594
+          if (streq (p[2], "subject"))
6595
+            type = VERIFY_X509_SUBJECT_DN;
6596
+          else if (streq (p[2], "name"))
6597
+            type = VERIFY_X509_SUBJECT_RDN;
6598
+          else if (streq (p[2], "name-prefix"))
6599
+            type = VERIFY_X509_SUBJECT_RDN_PREFIX;
6600
+          else
6601
+            {
6602
+              msg (msglevel, "unknown X.509 name type: %s", p[2]);
6603
+              goto err;
6604
+            }
6605
+        }
6606
+      options->verify_x509_type = type;
6607
+      options->verify_x509_name = p[1];
6538 6608
     }
6539 6609
   else if (streq (p[0], "ns-cert-type") && p[1])
6540 6610
     {
... ...
@@ -506,8 +506,9 @@ struct options
506 506
   const char *pkcs12_file;
507 507
   const char *cipher_list;
508 508
   const char *tls_verify;
509
+  int verify_x509_type;
510
+  const char *verify_x509_name;
509 511
   const char *tls_export_cert;
510
-  const char *tls_remote;
511 512
   const char *crl_file;
512 513
 
513 514
   const char *ca_file_inline;
... ...
@@ -245,7 +245,8 @@ struct tls_options
245 245
   /* cert verification parms */
246 246
   const char *verify_command;
247 247
   const char *verify_export_cert;
248
-  const char *verify_x509name;
248
+  int verify_x509_type;
249
+  const char *verify_x509_name;
249 250
   const char *crl_file;
250 251
   int ns_cert_type;
251 252
   unsigned remote_cert_ku[MAX_PARMS];
... ...
@@ -369,16 +369,21 @@ verify_peer_cert(const struct tls_options *opt, openvpn_x509_cert_t *peer_cert,
369 369
 
370 370
 #endif /* OPENSSL_VERSION_NUMBER */
371 371
 
372
-  /* verify X509 name or common name against --tls-remote */
373
-  if (opt->verify_x509name && strlen (opt->verify_x509name) > 0)
372
+  /* verify X509 name or username against --verify-x509-[user]name */
373
+  if (opt->verify_x509_type != VERIFY_X509_NONE)
374 374
     {
375
-      if (strcmp (opt->verify_x509name, subject) == 0
376
-	  || strncmp (opt->verify_x509name, common_name, strlen (opt->verify_x509name)) == 0)
375
+      if ( (opt->verify_x509_type == VERIFY_X509_SUBJECT_DN
376
+            && strcmp (opt->verify_x509_name, subject) == 0)
377
+        || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN
378
+            && strcmp (opt->verify_x509_name, common_name) == 0)
379
+        || (opt->verify_x509_type == VERIFY_X509_SUBJECT_RDN_PREFIX
380
+            && strncmp (opt->verify_x509_name, common_name,
381
+                        strlen (opt->verify_x509_name)) == 0) )
377 382
 	msg (D_HANDSHAKE, "VERIFY X509NAME OK: %s", subject);
378 383
       else
379 384
 	{
380 385
 	  msg (D_HANDSHAKE, "VERIFY X509NAME ERROR: %s, must be %s",
381
-	       subject, opt->verify_x509name);
386
+	       subject, opt->verify_x509_name);
382 387
 	  return FAILURE;		/* Reject connection */
383 388
 	}
384 389
     }
... ...
@@ -62,6 +62,12 @@ struct cert_hash_set {
62 62
   struct cert_hash *ch[MAX_CERT_DEPTH]; /**< Array of certificate hashes */
63 63
 };
64 64
 
65
+#define VERIFY_X509_NONE                0
66
+#define VERIFY_X509_SUBJECT_DN          1
67
+#define VERIFY_X509_SUBJECT_RDN         2
68
+#define VERIFY_X509_SUBJECT_RDN_PREFIX  3
69
+#define TLS_REMOTE_SUBJECT_DN           1 + 0x100
70
+#define TLS_REMOTE_SUBJECT_RDN_PREFIX   3 + 0x100
65 71
 
66 72
 #define TLS_AUTHENTICATION_SUCCEEDED  0
67 73
 #define TLS_AUTHENTICATION_FAILED     1