Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: net/cert/cert_verify_proc_win.cc

Issue 22893021: Normalize certificate name verification across all platforms (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update cert Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698