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... | ... |
@@ -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 */ |