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 |