| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/pickle.h" | 8 #include "base/pickle.h" |
| 9 #include "base/string_tokenizer.h" | 9 #include "base/string_tokenizer.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 // characters, so we can use WideToASCII here. | 421 // characters, so we can use WideToASCII here. |
| 422 if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) | 422 if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) |
| 423 dns_names->push_back(WideToASCII(alt_name->rgAltEntry[i].pwszDNSName)); | 423 dns_names->push_back(WideToASCII(alt_name->rgAltEntry[i].pwszDNSName)); |
| 424 } | 424 } |
| 425 } | 425 } |
| 426 if (dns_names->empty()) | 426 if (dns_names->empty()) |
| 427 dns_names->push_back(subject_.common_name); | 427 dns_names->push_back(subject_.common_name); |
| 428 } | 428 } |
| 429 | 429 |
| 430 int X509Certificate::Verify(const std::string& hostname, | 430 int X509Certificate::Verify(const std::string& hostname, |
| 431 bool rev_checking_enabled, | 431 int flags, |
| 432 CertVerifyResult* verify_result) const { | 432 CertVerifyResult* verify_result) const { |
| 433 verify_result->Reset(); | 433 verify_result->Reset(); |
| 434 | 434 |
| 435 // Build and validate certificate chain. | 435 // Build and validate certificate chain. |
| 436 | 436 |
| 437 CERT_CHAIN_PARA chain_para; | 437 CERT_CHAIN_PARA chain_para; |
| 438 memset(&chain_para, 0, sizeof(chain_para)); | 438 memset(&chain_para, 0, sizeof(chain_para)); |
| 439 chain_para.cbSize = sizeof(chain_para); | 439 chain_para.cbSize = sizeof(chain_para); |
| 440 // TODO(wtc): consider requesting the usage szOID_PKIX_KP_SERVER_AUTH | 440 // TODO(wtc): consider requesting the usage szOID_PKIX_KP_SERVER_AUTH |
| 441 // or szOID_SERVER_GATED_CRYPTO or szOID_SGC_NETSCAPE | 441 // or szOID_SERVER_GATED_CRYPTO or szOID_SGC_NETSCAPE |
| 442 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND; | 442 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND; |
| 443 chain_para.RequestedUsage.Usage.cUsageIdentifier = 0; | 443 chain_para.RequestedUsage.Usage.cUsageIdentifier = 0; |
| 444 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = NULL; // LPSTR* | 444 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = NULL; // LPSTR* |
| 445 // We can set CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS to get more chains. | 445 // We can set CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS to get more chains. |
| 446 DWORD flags = CERT_CHAIN_CACHE_END_CERT; | 446 DWORD chain_flags = CERT_CHAIN_CACHE_END_CERT; |
| 447 if (rev_checking_enabled) { | 447 if (flags & VERIFY_REV_CHECKING_ENABLED) { |
| 448 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 448 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 449 flags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; | 449 chain_flags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; |
| 450 } else { | 450 } else { |
| 451 flags |= CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; | 451 chain_flags |= CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; |
| 452 // EV requires revocation checking. |
| 453 flags &= ~VERIFY_EV_CERT; |
| 452 } | 454 } |
| 453 PCCERT_CHAIN_CONTEXT chain_context; | 455 PCCERT_CHAIN_CONTEXT chain_context; |
| 454 if (!CertGetCertificateChain( | 456 if (!CertGetCertificateChain( |
| 455 NULL, // default chain engine, HCCE_CURRENT_USER | 457 NULL, // default chain engine, HCCE_CURRENT_USER |
| 456 cert_handle_, | 458 cert_handle_, |
| 457 NULL, // current system time | 459 NULL, // current system time |
| 458 cert_handle_->hCertStore, // search this store | 460 cert_handle_->hCertStore, // search this store |
| 459 &chain_para, | 461 &chain_para, |
| 460 flags, | 462 chain_flags, |
| 461 NULL, // reserved | 463 NULL, // reserved |
| 462 &chain_context)) { | 464 &chain_context)) { |
| 463 return MapSecurityError(GetLastError()); | 465 return MapSecurityError(GetLastError()); |
| 464 } | 466 } |
| 465 ScopedCertChainContext scoped_chain_context(chain_context); | 467 ScopedCertChainContext scoped_chain_context(chain_context); |
| 466 | 468 |
| 467 GetCertChainInfo(chain_context, verify_result); | 469 GetCertChainInfo(chain_context, verify_result); |
| 468 | 470 |
| 469 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( | 471 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( |
| 470 chain_context->TrustStatus.dwErrorStatus); | 472 chain_context->TrustStatus.dwErrorStatus); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 } | 548 } |
| 547 } | 549 } |
| 548 } | 550 } |
| 549 | 551 |
| 550 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be | 552 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be |
| 551 // compatible with WinHTTP, which doesn't report this error (bug 3004). | 553 // compatible with WinHTTP, which doesn't report this error (bug 3004). |
| 552 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; | 554 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; |
| 553 | 555 |
| 554 if (IsCertStatusError(verify_result->cert_status)) | 556 if (IsCertStatusError(verify_result->cert_status)) |
| 555 return MapCertStatusToNetError(verify_result->cert_status); | 557 return MapCertStatusToNetError(verify_result->cert_status); |
| 558 |
| 559 // TODO(ukai): combine regular cert verification and EV cert verification. |
| 560 if ((flags & VERIFY_EV_CERT) && VerifyEV()) |
| 561 verify_result->cert_status |= CERT_STATUS_IS_EV; |
| 556 return OK; | 562 return OK; |
| 557 } | 563 } |
| 558 | 564 |
| 559 // Returns true if the certificate is an extended-validation certificate. | 565 // Returns true if the certificate is an extended-validation certificate. |
| 560 // | 566 // |
| 561 // The certificate has already been verified by the HTTP library. cert_status | 567 // This function checks the certificatePolicies extensions of the |
| 562 // represents the result of that verification. This function performs | 568 // certificates in the certificate chain according to Section 7 (pp. 11-12) |
| 563 // additional checks of the certificatePolicies extensions of the certificates | 569 // of the EV Certificate Guidelines Version 1.0 at |
| 564 // in the certificate chain according to Section 7 (pp. 11-12) of the EV | |
| 565 // Certificate Guidelines Version 1.0 at | |
| 566 // http://cabforum.org/EV_Certificate_Guidelines.pdf. | 570 // http://cabforum.org/EV_Certificate_Guidelines.pdf. |
| 567 bool X509Certificate::IsEV(int cert_status) const { | 571 bool X509Certificate::VerifyEV() const { |
| 568 if (net::IsCertStatusError(cert_status) || | |
| 569 (cert_status & net::CERT_STATUS_REV_CHECKING_ENABLED) == 0) | |
| 570 return false; | |
| 571 | |
| 572 net::EVRootCAMetadata* metadata = net::EVRootCAMetadata::GetInstance(); | 572 net::EVRootCAMetadata* metadata = net::EVRootCAMetadata::GetInstance(); |
| 573 | 573 |
| 574 PCCERT_CHAIN_CONTEXT chain_context = ConstructCertChain(cert_handle_, | 574 PCCERT_CHAIN_CONTEXT chain_context = ConstructCertChain(cert_handle_, |
| 575 metadata->GetPolicyOIDs(), metadata->NumPolicyOIDs()); | 575 metadata->GetPolicyOIDs(), metadata->NumPolicyOIDs()); |
| 576 if (!chain_context) | 576 if (!chain_context) |
| 577 return false; | 577 return false; |
| 578 ScopedCertChainContext scoped_chain_context(chain_context); | 578 ScopedCertChainContext scoped_chain_context(chain_context); |
| 579 | 579 |
| 580 DCHECK(chain_context->cChain != 0); | 580 DCHECK(chain_context->cChain != 0); |
| 581 // If the cert doesn't match any of the policies, the | 581 // If the cert doesn't match any of the policies, the |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 DWORD sha1_size = sizeof(sha1.data); | 643 DWORD sha1_size = sizeof(sha1.data); |
| 644 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, | 644 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, |
| 645 cert->cbCertEncoded, sha1.data, &sha1_size); | 645 cert->cbCertEncoded, sha1.data, &sha1_size); |
| 646 DCHECK(rv && sha1_size == sizeof(sha1.data)); | 646 DCHECK(rv && sha1_size == sizeof(sha1.data)); |
| 647 if (!rv) | 647 if (!rv) |
| 648 memset(sha1.data, 0, sizeof(sha1.data)); | 648 memset(sha1.data, 0, sizeof(sha1.data)); |
| 649 return sha1; | 649 return sha1; |
| 650 } | 650 } |
| 651 | 651 |
| 652 } // namespace net | 652 } // namespace net |
| OLD | NEW |