diff options
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_purp.c')
-rw-r--r-- | src/lib/libcrypto/x509v3/v3_purp.c | 75 |
1 files changed, 46 insertions, 29 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_purp.c b/src/lib/libcrypto/x509v3/v3_purp.c index b3d1ae5d1c..bbdf6da493 100644 --- a/src/lib/libcrypto/x509v3/v3_purp.c +++ b/src/lib/libcrypto/x509v3/v3_purp.c | |||
@@ -63,7 +63,6 @@ | |||
63 | 63 | ||
64 | static void x509v3_cache_extensions(X509 *x); | 64 | static void x509v3_cache_extensions(X509 *x); |
65 | 65 | ||
66 | static int ca_check(const X509 *x); | ||
67 | static int check_ssl_ca(const X509 *x); | 66 | static int check_ssl_ca(const X509 *x); |
68 | static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca); | 67 | static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca); |
69 | static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca); | 68 | static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca); |
@@ -286,7 +285,8 @@ int X509_supported_extension(X509_EXTENSION *ex) | |||
286 | NID_key_usage, /* 83 */ | 285 | NID_key_usage, /* 83 */ |
287 | NID_subject_alt_name, /* 85 */ | 286 | NID_subject_alt_name, /* 85 */ |
288 | NID_basic_constraints, /* 87 */ | 287 | NID_basic_constraints, /* 87 */ |
289 | NID_ext_key_usage /* 126 */ | 288 | NID_ext_key_usage, /* 126 */ |
289 | NID_proxyCertInfo /* 661 */ | ||
290 | }; | 290 | }; |
291 | 291 | ||
292 | int ex_nid; | 292 | int ex_nid; |
@@ -307,6 +307,7 @@ int X509_supported_extension(X509_EXTENSION *ex) | |||
307 | static void x509v3_cache_extensions(X509 *x) | 307 | static void x509v3_cache_extensions(X509 *x) |
308 | { | 308 | { |
309 | BASIC_CONSTRAINTS *bs; | 309 | BASIC_CONSTRAINTS *bs; |
310 | PROXY_CERT_INFO_EXTENSION *pci; | ||
310 | ASN1_BIT_STRING *usage; | 311 | ASN1_BIT_STRING *usage; |
311 | ASN1_BIT_STRING *ns; | 312 | ASN1_BIT_STRING *ns; |
312 | EXTENDED_KEY_USAGE *extusage; | 313 | EXTENDED_KEY_USAGE *extusage; |
@@ -335,6 +336,16 @@ static void x509v3_cache_extensions(X509 *x) | |||
335 | BASIC_CONSTRAINTS_free(bs); | 336 | BASIC_CONSTRAINTS_free(bs); |
336 | x->ex_flags |= EXFLAG_BCONS; | 337 | x->ex_flags |= EXFLAG_BCONS; |
337 | } | 338 | } |
339 | /* Handle proxy certificates */ | ||
340 | if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { | ||
341 | if (x->ex_flags & EXFLAG_CA | ||
342 | || X509_get_ext_by_NID(x, NID_subject_alt_name, 0) >= 0 | ||
343 | || X509_get_ext_by_NID(x, NID_issuer_alt_name, 0) >= 0) { | ||
344 | x->ex_flags |= EXFLAG_INVALID; | ||
345 | } | ||
346 | PROXY_CERT_INFO_EXTENSION_free(pci); | ||
347 | x->ex_flags |= EXFLAG_PROXY; | ||
348 | } | ||
338 | /* Handle key usage */ | 349 | /* Handle key usage */ |
339 | if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { | 350 | if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { |
340 | if(usage->length > 0) { | 351 | if(usage->length > 0) { |
@@ -426,7 +437,7 @@ static void x509v3_cache_extensions(X509 *x) | |||
426 | #define ns_reject(x, usage) \ | 437 | #define ns_reject(x, usage) \ |
427 | (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) | 438 | (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) |
428 | 439 | ||
429 | static int ca_check(const X509 *x) | 440 | static int check_ca(const X509 *x) |
430 | { | 441 | { |
431 | /* keyUsage if present should allow cert signing */ | 442 | /* keyUsage if present should allow cert signing */ |
432 | if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0; | 443 | if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0; |
@@ -435,25 +446,37 @@ static int ca_check(const X509 *x) | |||
435 | /* If basicConstraints says not a CA then say so */ | 446 | /* If basicConstraints says not a CA then say so */ |
436 | else return 0; | 447 | else return 0; |
437 | } else { | 448 | } else { |
449 | /* we support V1 roots for... uh, I don't really know why. */ | ||
438 | if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3; | 450 | if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3; |
439 | /* If key usage present it must have certSign so tolerate it */ | 451 | /* If key usage present it must have certSign so tolerate it */ |
440 | else if (x->ex_flags & EXFLAG_KUSAGE) return 4; | 452 | else if (x->ex_flags & EXFLAG_KUSAGE) return 4; |
441 | else return 2; | 453 | /* Older certificates could have Netscape-specific CA types */ |
454 | else if (x->ex_flags & EXFLAG_NSCERT | ||
455 | && x->ex_nscert & NS_ANY_CA) return 5; | ||
456 | /* can this still be regarded a CA certificate? I doubt it */ | ||
457 | return 0; | ||
442 | } | 458 | } |
443 | } | 459 | } |
444 | 460 | ||
461 | int X509_check_ca(X509 *x) | ||
462 | { | ||
463 | if(!(x->ex_flags & EXFLAG_SET)) { | ||
464 | CRYPTO_w_lock(CRYPTO_LOCK_X509); | ||
465 | x509v3_cache_extensions(x); | ||
466 | CRYPTO_w_unlock(CRYPTO_LOCK_X509); | ||
467 | } | ||
468 | |||
469 | return check_ca(x); | ||
470 | } | ||
471 | |||
445 | /* Check SSL CA: common checks for SSL client and server */ | 472 | /* Check SSL CA: common checks for SSL client and server */ |
446 | static int check_ssl_ca(const X509 *x) | 473 | static int check_ssl_ca(const X509 *x) |
447 | { | 474 | { |
448 | int ca_ret; | 475 | int ca_ret; |
449 | ca_ret = ca_check(x); | 476 | ca_ret = check_ca(x); |
450 | if(!ca_ret) return 0; | 477 | if(!ca_ret) return 0; |
451 | /* check nsCertType if present */ | 478 | /* check nsCertType if present */ |
452 | if(x->ex_flags & EXFLAG_NSCERT) { | 479 | if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret; |
453 | if(x->ex_nscert & NS_SSL_CA) return ca_ret; | ||
454 | return 0; | ||
455 | } | ||
456 | if(ca_ret != 2) return ca_ret; | ||
457 | else return 0; | 480 | else return 0; |
458 | } | 481 | } |
459 | 482 | ||
@@ -498,14 +521,10 @@ static int purpose_smime(const X509 *x, int ca) | |||
498 | if(xku_reject(x,XKU_SMIME)) return 0; | 521 | if(xku_reject(x,XKU_SMIME)) return 0; |
499 | if(ca) { | 522 | if(ca) { |
500 | int ca_ret; | 523 | int ca_ret; |
501 | ca_ret = ca_check(x); | 524 | ca_ret = check_ca(x); |
502 | if(!ca_ret) return 0; | 525 | if(!ca_ret) return 0; |
503 | /* check nsCertType if present */ | 526 | /* check nsCertType if present */ |
504 | if(x->ex_flags & EXFLAG_NSCERT) { | 527 | if(ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret; |
505 | if(x->ex_nscert & NS_SMIME_CA) return ca_ret; | ||
506 | return 0; | ||
507 | } | ||
508 | if(ca_ret != 2) return ca_ret; | ||
509 | else return 0; | 528 | else return 0; |
510 | } | 529 | } |
511 | if(x->ex_flags & EXFLAG_NSCERT) { | 530 | if(x->ex_flags & EXFLAG_NSCERT) { |
@@ -539,7 +558,7 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca) | |||
539 | { | 558 | { |
540 | if(ca) { | 559 | if(ca) { |
541 | int ca_ret; | 560 | int ca_ret; |
542 | if((ca_ret = ca_check(x)) != 2) return ca_ret; | 561 | if((ca_ret = check_ca(x)) != 2) return ca_ret; |
543 | else return 0; | 562 | else return 0; |
544 | } | 563 | } |
545 | if(ku_reject(x, KU_CRL_SIGN)) return 0; | 564 | if(ku_reject(x, KU_CRL_SIGN)) return 0; |
@@ -552,17 +571,9 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca) | |||
552 | 571 | ||
553 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) | 572 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) |
554 | { | 573 | { |
555 | /* Must be a valid CA */ | 574 | /* Must be a valid CA. Should we really support the "I don't know" |
556 | if(ca) { | 575 | value (2)? */ |
557 | int ca_ret; | 576 | if(ca) return check_ca(x); |
558 | ca_ret = ca_check(x); | ||
559 | if(ca_ret != 2) return ca_ret; | ||
560 | if(x->ex_flags & EXFLAG_NSCERT) { | ||
561 | if(x->ex_nscert & NS_ANY_CA) return ca_ret; | ||
562 | return 0; | ||
563 | } | ||
564 | return 0; | ||
565 | } | ||
566 | /* leaf certificate is checked in OCSP_verify() */ | 577 | /* leaf certificate is checked in OCSP_verify() */ |
567 | return 1; | 578 | return 1; |
568 | } | 579 | } |
@@ -624,7 +635,13 @@ int X509_check_issued(X509 *issuer, X509 *subject) | |||
624 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; | 635 | return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; |
625 | } | 636 | } |
626 | } | 637 | } |
627 | if(ku_reject(issuer, KU_KEY_CERT_SIGN)) return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; | 638 | if(subject->ex_flags & EXFLAG_PROXY) |
639 | { | ||
640 | if(ku_reject(issuer, KU_DIGITAL_SIGNATURE)) | ||
641 | return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; | ||
642 | } | ||
643 | else if(ku_reject(issuer, KU_KEY_CERT_SIGN)) | ||
644 | return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; | ||
628 | return X509_V_OK; | 645 | return X509_V_OK; |
629 | } | 646 | } |
630 | 647 | ||