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 | ||
