Browse code

Merged --remote-cert-ku, --remote-cert-eku, and --remote-cert-tls from Alon's branch: svn merge -r 793:796 $SO/contrib/alon/BETA21/openvpn .

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@797 e7ae566f-a301-0410-adde-c780ea21d3b5

james authored on 2005/11/12 17:26:57
Showing 7 changed files
... ...
@@ -207,6 +207,8 @@ nsCertType			= server
207 207
 nsComment			= "OpenSSL Generated Server Certificate"
208 208
 subjectKeyIdentifier=hash
209 209
 authorityKeyIdentifier=keyid,issuer:always
210
+extendedKeyUsage=serverAuth
211
+keyUsage = digitalSignature, keyEncipherment
210 212
 
211 213
 [ v3_req ]
212 214
 
... ...
@@ -1445,6 +1445,8 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
1445 1445
   to.verify_x509name = options->tls_remote;
1446 1446
   to.crl_file = options->crl_file;
1447 1447
   to.ns_cert_type = options->ns_cert_type;
1448
+  memmove (to.remote_cert_ku, options->remote_cert_ku, sizeof (to.remote_cert_ku));
1449
+  to.remote_cert_eku = options->remote_cert_eku;
1448 1450
   to.es = c->c2.es;
1449 1451
 
1450 1452
 #ifdef ENABLE_DEBUG
... ...
@@ -225,6 +225,9 @@ openvpn \- secure IP tunnel daemon.
225 225
 [\ \fB\-\-remap\-usr1\fR\ \fIsignal\fR\ ]
226 226
 [\ \fB\-\-remote\-random\fR\ ]
227 227
 [\ \fB\-\-remote\fR\ \fIhost\ [port]\fR\ ]
228
+[\ \fB\-\-remote\-cert\-ku\ \fIv...\fR\ ]
229
+[\ \fB\-\-remote\-cert\-eku\ \fIoid\fR\ ]
230
+[\ \fB\-\-remote\-cert\-tls\ \fIt\fR\ ]
228 231
 [\ \fB\-\-reneg\-bytes\fR\ \fIn\fR\ ]
229 232
 [\ \fB\-\-reneg\-pkts\fR\ \fIn\fR\ ]
230 233
 [\ \fB\-\-reneg\-sec\fR\ \fIn\fR\ ]
... ...
@@ -4044,6 +4047,58 @@ or
4044 4044
 .B --tls-verify.
4045 4045
 .\"*********************************************************
4046 4046
 .TP
4047
+.B --remote-cert-ku v...
4048
+Require that peer certificate was signed with an explicit
4049
+.B key usage.
4050
+
4051
+This is useful security option for clients, to ensure that
4052
+the host they connect with is a designated server.
4053
+
4054
+The key usage should be encoded in hex, more than one key
4055
+usage can be specified.
4056
+.\"*********************************************************
4057
+.TP
4058
+.B --remote-cert-eku oid
4059
+Require that peer certificate was signed with an explicit
4060
+.B extended key usage.
4061
+
4062
+This is useful security option for clients, to ensure that
4063
+the host they connect with is a designated server.
4064
+
4065
+The extended key usage should be encoded in oid notation, or
4066
+OpenSSL symbolic representation.
4067
+.\"*********************************************************
4068
+.TP
4069
+.B --remote-cert-tls client|server
4070
+Require that peer certificate was signed with an explicit
4071
+.B key usage
4072
+and
4073
+.B extended key usage
4074
+based on TLS rules.
4075
+
4076
+This is a useful security option for clients, to ensure that
4077
+the host they connect with is a designated server.
4078
+
4079
+The
4080
+.B --remote-cert-tls client
4081
+option is equivalent to
4082
+.B --remote-cert-ku 80 08 88 --remote-cert-eku \fB"TLS Web Client Authentication" 
4083
+
4084
+The
4085
+.B --remote-cert-tls server
4086
+option is equivalent to
4087
+.B --remote-cert-ku a0 08 --remote-cert-eku \fB"TLS Web Server Authentication"
4088
+
4089
+This is an important security precaution to protect against
4090
+a man-in-the-middle attack where an authorized client
4091
+attempts to connect to another client by impersonating the server.
4092
+The attack is easily prevented by having clients verify
4093
+the server certificate using any one of
4094
+.B --remote-cert-tls, --tls-remote,
4095
+or
4096
+.B --tls-verify.
4097
+.\"*********************************************************
4098
+.TP
4047 4099
 .B --crl-verify crl
4048 4100
 Check peer certificate against the file
4049 4101
 .B crl
... ...
@@ -463,6 +463,17 @@ static const char usage_message[] =
463 463
   "                  of verification.\n"
464 464
   "--ns-cert-type t: Require that peer certificate was signed with an explicit\n"
465 465
   "                  nsCertType designation t = 'client' | 'server'.\n"
466
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
467
+  "--remote-cert-ku v ... : Require that the peer certificate was signed with\n"
468
+  "                  explicit key usage, you can specify more than one value.\n"
469
+  "                  value should be given in hex format.\n"
470
+  "--remote-cert-eku oid : Require that the peer certificate was signed with\n"
471
+  "                  explicit extended key usage. Extended key usage can be encoded\n"
472
+  "                  as on object identifier or OpenSSL string representation.\n"
473
+  "--remote-cert-tls t: Require that peer certificate was signed with explicit\n"
474
+  "                  key usage and extended key usage based on TLS rules.\n"
475
+  "                  t = 'client | 'server'.\n"
476
+#endif				/* OPENSSL_VERSION_NUMBER */
466 477
 #endif				/* USE_SSL */
467 478
 #ifdef ENABLE_PKCS11
468 479
   "\n"
... ...
@@ -1197,6 +1208,12 @@ show_settings (const struct options *o)
1197 1197
   SHOW_STR (tls_remote);
1198 1198
   SHOW_STR (crl_file);
1199 1199
   SHOW_INT (ns_cert_type);
1200
+  {
1201
+    int i;
1202
+    for (i=0;i<MAX_PARMS;i++)
1203
+      SHOW_INT (remote_cert_ku[i]);
1204
+  }
1205
+  SHOW_STR (remote_cert_eku);
1200 1206
 
1201 1207
   SHOW_INT (tls_timeout);
1202 1208
 
... ...
@@ -1813,6 +1830,8 @@ options_postprocess (struct options *options, bool first_time)
1813 1813
       MUST_BE_UNDEF (crl_file);
1814 1814
       MUST_BE_UNDEF (key_method);
1815 1815
       MUST_BE_UNDEF (ns_cert_type);
1816
+      MUST_BE_UNDEF (remote_cert_ku[0]);
1817
+      MUST_BE_UNDEF (remote_cert_eku);
1816 1818
 #ifdef ENABLE_PKCS11
1817 1819
       MUST_BE_UNDEF (pkcs11_providers[0]);
1818 1820
       MUST_BE_UNDEF (pkcs11_sign_mode[0]);
... ...
@@ -4786,6 +4805,45 @@ add_option (struct options *options,
4786 4786
 	  goto err;
4787 4787
 	}
4788 4788
     }
4789
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
4790
+  else if (streq (p[0], "remote-cert-ku"))
4791
+    {
4792
+      int j;
4793
+
4794
+      VERIFY_PERMISSION (OPT_P_GENERAL);
4795
+
4796
+      for (j = 1; j < MAX_PARMS && p[j] != NULL; ++j)
4797
+	sscanf (p[j], "%x", &(options->remote_cert_ku[j-1]));
4798
+    }
4799
+  else if (streq (p[0], "remote-cert-eku") && p[1])
4800
+    {
4801
+      VERIFY_PERMISSION (OPT_P_GENERAL);
4802
+      options->remote_cert_eku = p[1];
4803
+    }
4804
+  else if (streq (p[0], "remote-cert-tls") && p[1])
4805
+    {
4806
+      VERIFY_PERMISSION (OPT_P_GENERAL);
4807
+
4808
+      if (streq (p[1], "server"))
4809
+	{
4810
+	  options->remote_cert_ku[0] = 0xa0;
4811
+	  options->remote_cert_ku[1] = 0x08;
4812
+	  options->remote_cert_eku = "TLS Web Server Authentication";
4813
+	}
4814
+      else if (streq (p[1], "client"))
4815
+	{
4816
+	  options->remote_cert_ku[0] = 0x80;
4817
+	  options->remote_cert_ku[1] = 0x08;
4818
+	  options->remote_cert_ku[2] = 0x88;
4819
+	  options->remote_cert_eku = "TLS Web Client Authentication";
4820
+	}
4821
+      else
4822
+	{
4823
+	  msg (msglevel, "--remote-cert-tls must be 'client' or 'server'");
4824
+	  goto err;
4825
+	}
4826
+    }
4827
+#endif	/* OPENSSL_VERSION_NUMBER */
4789 4828
   else if (streq (p[0], "tls-timeout") && p[1])
4790 4829
     {
4791 4830
       VERIFY_PERMISSION (OPT_P_TLS_PARMS);
... ...
@@ -392,6 +392,8 @@ struct options
392 392
 #endif
393 393
 
394 394
   int ns_cert_type; /* set to 0, NS_SSL_SERVER, or NS_SSL_CLIENT */
395
+  unsigned remote_cert_ku[MAX_PARMS];
396
+  const char *remote_cert_eku;
395 397
   const char *pkcs11_providers[MAX_PARMS];
396 398
   const char *pkcs11_sign_mode[MAX_PARMS];
397 399
   const char *pkcs11_slot_type;
... ...
@@ -389,6 +389,91 @@ set_common_name (struct tls_session *session, const char *common_name)
389 389
     }
390 390
 }
391 391
 
392
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
393
+
394
+bool verify_cert_eku (X509 *x509, const char * const expected_oid) {
395
+
396
+	EXTENDED_KEY_USAGE *eku = NULL;
397
+	bool fFound = false;
398
+
399
+	if ((eku = (EXTENDED_KEY_USAGE *)X509_get_ext_d2i (x509, NID_ext_key_usage, NULL, NULL)) == NULL) {
400
+		msg (D_HANDSHAKE, "Certificate does not have extended key usage extension");
401
+	}
402
+	else {
403
+		int i;
404
+
405
+		msg (D_HANDSHAKE, "Validating certificate extended key usage");
406
+		for(i = 0; !fFound && i < sk_ASN1_OBJECT_num (eku); i++) {
407
+			ASN1_OBJECT *oid = sk_ASN1_OBJECT_value (eku, i);
408
+			char szOid[1024];
409
+
410
+			if (!fFound && OBJ_obj2txt (szOid, sizeof (szOid), oid, 0) != -1) {
411
+				msg (D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", szOid, expected_oid);
412
+				if (!strcmp (expected_oid, szOid)) {
413
+					fFound = true;
414
+				}
415
+			}
416
+			if (!fFound && OBJ_obj2txt (szOid, sizeof (szOid), oid, 1) != -1) {
417
+				msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", szOid, expected_oid);
418
+				if (!strcmp (expected_oid, szOid)) {
419
+					fFound = true;
420
+				}
421
+			}
422
+		}
423
+	}
424
+
425
+	if (eku != NULL) {
426
+		sk_ASN1_OBJECT_pop_free (eku, ASN1_OBJECT_free);
427
+	}
428
+
429
+	return fFound;
430
+}
431
+
432
+bool verify_cert_ku (X509 *x509, const unsigned * const expected_ku, int expected_len) {
433
+
434
+	ASN1_BIT_STRING *ku = NULL;
435
+	bool fFound = false;
436
+
437
+	if ((ku = (ASN1_BIT_STRING *)X509_get_ext_d2i (x509, NID_key_usage, NULL, NULL)) == NULL) {
438
+		msg (D_HANDSHAKE, "Certificate does not have key usage extension");
439
+	}
440
+	else {
441
+		unsigned nku = 0;
442
+		int i;
443
+		for (i=0;i<8;i++) {
444
+			if (ASN1_BIT_STRING_get_bit (ku, i)) {
445
+				nku |= 1<<(7-i);
446
+			}
447
+		}
448
+
449
+		/*
450
+		 * Fixup if no LSB bits
451
+		 */
452
+		if ((nku & 0xff) == 0) {
453
+			nku >>= 8;
454
+		}
455
+
456
+		msg (D_HANDSHAKE, "Validating certificate key usage");
457
+		for (i=0;!fFound && i<expected_len;i++) {
458
+			if (expected_ku[i] != 0) {
459
+				msg (D_HANDSHAKE, "++ Certificate has key usage  %04x, expects %04x", nku, expected_ku[i]);
460
+
461
+				if (nku == expected_ku[i]) {
462
+					fFound = true;
463
+				}
464
+			}
465
+		}
466
+	}
467
+
468
+	if (ku != NULL) {
469
+		ASN1_BIT_STRING_free (ku);
470
+	}
471
+
472
+	return fFound;
473
+}
474
+
475
+#endif	/* OPENSSL_VERSION_NUMBER */
476
+
392 477
 /*
393 478
  * nsCertType checking
394 479
  */
... ...
@@ -506,6 +591,38 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
506 506
 	}
507 507
     }
508 508
 
509
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
510
+
511
+  /* verify certificate ku */
512
+  if (opt->remote_cert_ku[0] != 0 &&  ctx->error_depth == 0)
513
+    {
514
+      if (verify_cert_ku (ctx->current_cert, opt->remote_cert_ku, MAX_PARMS))
515
+	{
516
+	  msg (D_HANDSHAKE, "VERIFY KU OK");
517
+	}
518
+        else
519
+        {
520
+	  msg (D_HANDSHAKE, "VERIFY KU ERROR");
521
+          goto err;		/* Reject connection */
522
+	}
523
+    }
524
+
525
+  /* verify certificate eku */
526
+  if (opt->remote_cert_eku != NULL && ctx->error_depth == 0)
527
+    {
528
+      if (verify_cert_eku (ctx->current_cert, opt->remote_cert_eku))
529
+        {
530
+	  msg (D_HANDSHAKE, "VERIFY EKU OK");
531
+	}
532
+      else
533
+	{
534
+	  msg (D_HANDSHAKE, "VERIFY EKU ERROR");
535
+          goto err;		/* Reject connection */
536
+	}
537
+    }
538
+
539
+#endif	/* OPENSSL_VERSION_NUMBER */
540
+
509 541
   /* verify X509 name or common name against --tls-remote */
510 542
   if (opt->verify_x509name && strlen (opt->verify_x509name) > 0 && ctx->error_depth == 0)
511 543
     {
... ...
@@ -410,6 +410,8 @@ struct tls_options
410 410
   const char *verify_x509name;
411 411
   const char *crl_file;
412 412
   int ns_cert_type;
413
+  unsigned remote_cert_ku[MAX_PARMS];
414
+  const char *remote_cert_eku;
413 415
 
414 416
   /* allow openvpn config info to be
415 417
      passed over control channel */