Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/cert/cert_verify_proc_win.h" | 5 #include "net/cert/cert_verify_proc_win.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 710 CERT_TRUST_IS_OFFLINE_REVOCATION) { | 710 CERT_TRUST_IS_OFFLINE_REVOCATION) { |
| 711 verify_result->cert_status |= CERT_STATUS_REVOKED; | 711 verify_result->cert_status |= CERT_STATUS_REVOKED; |
| 712 } | 712 } |
| 713 } | 713 } |
| 714 | 714 |
| 715 ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context); | 715 ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context); |
| 716 | 716 |
| 717 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( | 717 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( |
| 718 chain_context->TrustStatus.dwErrorStatus); | 718 chain_context->TrustStatus.dwErrorStatus); |
| 719 | 719 |
| 720 // Flag certificates that have a Subject common name with a NULL character. | 720 // Flag certificates that have a Subject common name with a NULL character. |
|
wtc
2013/08/16 19:59:19
Perhaps this workaround can be removed?
Ryan Sleevi
2013/08/16 20:38:28
I think it's still reasonable to bounce such certs
| |
| 721 if (CertSubjectCommonNameHasNull(cert_handle)) | 721 if (CertSubjectCommonNameHasNull(cert_handle)) |
| 722 verify_result->cert_status |= CERT_STATUS_INVALID; | 722 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 723 | 723 |
| 724 std::wstring wstr_hostname = ASCIIToWide(hostname); | 724 std::wstring wstr_hostname = ASCIIToWide(hostname); |
| 725 | 725 |
| 726 SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para; | 726 SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para; |
| 727 memset(&extra_policy_para, 0, sizeof(extra_policy_para)); | 727 memset(&extra_policy_para, 0, sizeof(extra_policy_para)); |
| 728 extra_policy_para.cbSize = sizeof(extra_policy_para); | 728 extra_policy_para.cbSize = sizeof(extra_policy_para); |
| 729 extra_policy_para.dwAuthType = AUTHTYPE_SERVER; | 729 extra_policy_para.dwAuthType = AUTHTYPE_SERVER; |
| 730 extra_policy_para.fdwChecks = 0; | 730 extra_policy_para.fdwChecks = |
| 731 0x00001000; // SECURITY_FLAG_IGNORE_CERT_CN_INVALID | |
|
wtc
2013/08/16 19:59:19
Is this macro not defined in Wincrypt.h?
A commen
Ryan Sleevi
2013/08/16 20:38:28
No. The flags here are similar to the flags on the
| |
| 731 extra_policy_para.pwszServerName = | 732 extra_policy_para.pwszServerName = |
| 732 const_cast<wchar_t*>(wstr_hostname.c_str()); | 733 const_cast<wchar_t*>(wstr_hostname.c_str()); |
| 733 | 734 |
| 734 CERT_CHAIN_POLICY_PARA policy_para; | 735 CERT_CHAIN_POLICY_PARA policy_para; |
| 735 memset(&policy_para, 0, sizeof(policy_para)); | 736 memset(&policy_para, 0, sizeof(policy_para)); |
| 736 policy_para.cbSize = sizeof(policy_para); | 737 policy_para.cbSize = sizeof(policy_para); |
| 737 policy_para.dwFlags = 0; | 738 policy_para.dwFlags = 0; |
| 738 policy_para.pvExtraPolicyPara = &extra_policy_para; | 739 policy_para.pvExtraPolicyPara = &extra_policy_para; |
| 739 | 740 |
| 740 CERT_CHAIN_POLICY_STATUS policy_status; | 741 CERT_CHAIN_POLICY_STATUS policy_status; |
| 741 memset(&policy_status, 0, sizeof(policy_status)); | 742 memset(&policy_status, 0, sizeof(policy_status)); |
| 742 policy_status.cbSize = sizeof(policy_status); | 743 policy_status.cbSize = sizeof(policy_status); |
| 743 | 744 |
| 744 if (!CertVerifyCertificateChainPolicy( | 745 if (!CertVerifyCertificateChainPolicy( |
| 745 CERT_CHAIN_POLICY_SSL, | 746 CERT_CHAIN_POLICY_SSL, |
| 746 chain_context, | 747 chain_context, |
| 747 &policy_para, | 748 &policy_para, |
| 748 &policy_status)) { | 749 &policy_status)) { |
| 749 return MapSecurityError(GetLastError()); | 750 return MapSecurityError(GetLastError()); |
| 750 } | 751 } |
| 751 | 752 |
| 752 if (policy_status.dwError) { | 753 if (policy_status.dwError) { |
| 753 verify_result->cert_status |= MapNetErrorToCertStatus( | 754 verify_result->cert_status |= MapNetErrorToCertStatus( |
| 754 MapSecurityError(policy_status.dwError)); | 755 MapSecurityError(policy_status.dwError)); |
| 755 | |
| 756 // CertVerifyCertificateChainPolicy reports only one error (in | |
| 757 // policy_status.dwError) if the certificate has multiple errors. | |
| 758 // CertGetCertificateChain doesn't report certificate name mismatch, so | |
| 759 // CertVerifyCertificateChainPolicy is the only function that can report | |
| 760 // certificate name mismatch. | |
| 761 // | |
| 762 // To prevent a potential certificate name mismatch from being hidden by | |
| 763 // some other certificate error, if we get any other certificate error, | |
| 764 // we call CertVerifyCertificateChainPolicy again, ignoring all other | |
| 765 // certificate errors. Both extra_policy_para.fdwChecks and | |
| 766 // policy_para.dwFlags allow us to ignore certificate errors, so we set | |
| 767 // them both. | |
| 768 if (policy_status.dwError != CERT_E_CN_NO_MATCH) { | |
| 769 const DWORD extra_ignore_flags = | |
| 770 0x00000080 | // SECURITY_FLAG_IGNORE_REVOCATION | |
| 771 0x00000100 | // SECURITY_FLAG_IGNORE_UNKNOWN_CA | |
| 772 0x00002000 | // SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | |
| 773 0x00000200; // SECURITY_FLAG_IGNORE_WRONG_USAGE | |
| 774 extra_policy_para.fdwChecks = extra_ignore_flags; | |
| 775 const DWORD ignore_flags = | |
| 776 CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS | | |
| 777 CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG | | |
| 778 CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG | | |
| 779 CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG | | |
| 780 CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG | | |
| 781 CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG | | |
| 782 CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS | | |
| 783 CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG | | |
| 784 CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG | | |
| 785 CERT_CHAIN_POLICY_IGNORE_NOT_SUPPORTED_CRITICAL_EXT_FLAG | | |
| 786 CERT_CHAIN_POLICY_IGNORE_PEER_TRUST_FLAG; | |
| 787 policy_para.dwFlags = ignore_flags; | |
| 788 if (!CertVerifyCertificateChainPolicy( | |
| 789 CERT_CHAIN_POLICY_SSL, | |
| 790 chain_context, | |
| 791 &policy_para, | |
| 792 &policy_status)) { | |
| 793 return MapSecurityError(GetLastError()); | |
| 794 } | |
| 795 if (policy_status.dwError) { | |
| 796 verify_result->cert_status |= MapNetErrorToCertStatus( | |
| 797 MapSecurityError(policy_status.dwError)); | |
| 798 } | |
| 799 } | |
| 800 } | 756 } |
| 801 | 757 |
| 802 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be | 758 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be |
| 803 // compatible with WinHTTP, which doesn't report this error (bug 3004). | 759 // compatible with WinHTTP, which doesn't report this error (bug 3004). |
| 804 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; | 760 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; |
| 805 | 761 |
| 762 // Perform hostname verification independent of | |
| 763 // CertVerifyCertificateChainPolicy. | |
| 764 if (!cert->VerifyNameMatch(hostname)) | |
| 765 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | |
| 766 | |
| 767 | |
|
wtc
2013/08/16 19:59:19
Nit: delete one blank line.
| |
| 806 if (!rev_checking_enabled) { | 768 if (!rev_checking_enabled) { |
| 807 // If we didn't do online revocation checking then Windows will report | 769 // If we didn't do online revocation checking then Windows will report |
| 808 // CERT_UNABLE_TO_CHECK_REVOCATION unless it had cached OCSP or CRL | 770 // CERT_UNABLE_TO_CHECK_REVOCATION unless it had cached OCSP or CRL |
| 809 // information for every certificate. We only want to put up revoked | 771 // information for every certificate. We only want to put up revoked |
| 810 // statuses from the offline checks so we squash this error. | 772 // statuses from the offline checks so we squash this error. |
| 811 verify_result->cert_status &= ~CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; | 773 verify_result->cert_status &= ~CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; |
| 812 } | 774 } |
| 813 | 775 |
| 814 AppendPublicKeyHashes(chain_context, &verify_result->public_key_hashes); | 776 AppendPublicKeyHashes(chain_context, &verify_result->public_key_hashes); |
| 815 verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(chain_context); | 777 verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(chain_context); |
| 816 | 778 |
| 817 if (IsCertStatusError(verify_result->cert_status)) | 779 if (IsCertStatusError(verify_result->cert_status)) |
| 818 return MapCertStatusToNetError(verify_result->cert_status); | 780 return MapCertStatusToNetError(verify_result->cert_status); |
| 819 | 781 |
| 820 if (ev_policy_oid && | 782 if (ev_policy_oid && |
| 821 CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) { | 783 CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) { |
| 822 verify_result->cert_status |= CERT_STATUS_IS_EV; | 784 verify_result->cert_status |= CERT_STATUS_IS_EV; |
| 823 } | 785 } |
| 824 return OK; | 786 return OK; |
| 825 } | 787 } |
| 826 | 788 |
| 827 } // namespace net | 789 } // namespace net |
| OLD | NEW |