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

Side by Side Diff: net/base/x509_certificate_win.cc

Issue 7324039: Ensure X509Certificate::OSCertHandles are safe to be used on both UI and IO threads on Win (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 5 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/sha1.h" 9 #include "base/sha1.h"
10 #include "base/string_tokenizer.h" 10 #include "base/string_tokenizer.h"
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) 623 if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME)
624 dns_names->push_back( 624 dns_names->push_back(
625 WideToASCII(alt_name->rgAltEntry[i].pwszDNSName)); 625 WideToASCII(alt_name->rgAltEntry[i].pwszDNSName));
626 } 626 }
627 } 627 }
628 } 628 }
629 if (dns_names->empty()) 629 if (dns_names->empty())
630 dns_names->push_back(subject_.common_name); 630 dns_names->push_back(subject_.common_name);
631 } 631 }
632 632
633 X509Certificate::OSCertListHandle
634 X509Certificate::CreateOSCertListHandle() const {
635 // Create a temporary certificate store to hold |cert_handle_| and any
wtc 2011/10/04 00:26:34 temporary => in-memory
636 // associated intermediates. The store will be referenced in the returned
wtc 2011/10/04 00:26:34 intermediates => intermediate certificates
637 // OSCertListHandle, and will not be freed until the OSCertListHandle is
638 // freed.
639 OSCertListHandle cert_list = NULL;
640 DWORD flags = CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG;
641 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0,
642 NULL, flags, NULL);
643
644 if (store) {
645 // NOTE: This preserves all of the properties of |cert_handle_| except for
646 // CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
647 // properties that hold access to already-opened private keys. If a handle
648 // has already been unlocked (eg: PIN prompt), then the first time that
649 // the identity is used for client auth, it may prompt the user again.
wtc 2011/10/04 00:26:34 Nit: identity => certificate handle? Do we ever u
Ryan Sleevi 2011/10/04 03:38:07 Now that certificate prompting has been moved into
wtc 2011/10/04 18:00:51 You can keep this comment. I asked the question t
650 BOOL ok = CertAddCertificateContextToStore(store, cert_handle_,
651 CERT_STORE_ADD_ALWAYS,
652 &cert_list);
653 if (ok && cert_list) {
654 for (size_t i = 0; ok && i < intermediate_ca_certs_.size(); ++i) {
655 ok = CertAddCertificateContextToStore(store, intermediate_ca_certs_[i],
656 CERT_STORE_ADD_ALWAYS, NULL);
657 }
658 }
659
660 // If |cert_list| points to a valid certificate, this will not actually
661 // close and free |store| until |cert_list| is freed.
662 CertCloseStore(store, 0);
663
664 if (!ok) {
665 FreeOSCertListHandle(cert_list);
666 return NULL;
667 }
668 }
669
670 return cert_list;
671 }
672
633 int X509Certificate::VerifyInternal(const std::string& hostname, 673 int X509Certificate::VerifyInternal(const std::string& hostname,
634 int flags, 674 int flags,
635 CertVerifyResult* verify_result) const { 675 CertVerifyResult* verify_result) const {
636 if (!cert_handle_) 676 if (!cert_handle_)
637 return ERR_UNEXPECTED; 677 return ERR_UNEXPECTED;
638 678
639 // Build and validate certificate chain. 679 // Build and validate certificate chain.
640 CERT_CHAIN_PARA chain_para; 680 CERT_CHAIN_PARA chain_para;
641 memset(&chain_para, 0, sizeof(chain_para)); 681 memset(&chain_para, 0, sizeof(chain_para));
642 chain_para.cbSize = sizeof(chain_para); 682 chain_para.cbSize = sizeof(chain_para);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by 729 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by
690 // crypt32. However, when testing, it is necessary to create a new 730 // crypt32. However, when testing, it is necessary to create a new
691 // HCERTCHAINENGINE and use that instead. This is because each 731 // HCERTCHAINENGINE and use that instead. This is because each
692 // HCERTCHAINENGINE maintains a cache of information about certificates 732 // HCERTCHAINENGINE maintains a cache of information about certificates
693 // encountered, and each test run may modify the trust status of a 733 // encountered, and each test run may modify the trust status of a
694 // certificate. 734 // certificate.
695 ScopedHCERTCHAINENGINE chain_engine(NULL); 735 ScopedHCERTCHAINENGINE chain_engine(NULL);
696 if (TestRootCerts::HasInstance()) 736 if (TestRootCerts::HasInstance())
697 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); 737 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
698 738
739 OSCertListHandle cert_list = CreateOSCertListHandle();
699 PCCERT_CHAIN_CONTEXT chain_context; 740 PCCERT_CHAIN_CONTEXT chain_context;
700 // IE passes a non-NULL pTime argument that specifies the current system 741 // IE passes a non-NULL pTime argument that specifies the current system
701 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the 742 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
702 // chain_flags argument. 743 // chain_flags argument.
703 if (!CertGetCertificateChain( 744 if (!CertGetCertificateChain(
704 chain_engine, 745 chain_engine,
705 cert_handle_, 746 cert_list,
706 NULL, // current system time 747 NULL, // current system time
707 cert_handle_->hCertStore, 748 cert_list->hCertStore,
708 &chain_para, 749 &chain_para,
709 chain_flags, 750 chain_flags,
710 NULL, // reserved 751 NULL, // reserved
711 &chain_context)) { 752 &chain_context)) {
753 FreeOSCertListHandle(cert_list);
wtc 2011/10/04 00:26:34 Do we have a scoped type for PCCERTCONTEXT? We co
712 return MapSecurityError(GetLastError()); 754 return MapSecurityError(GetLastError());
713 } 755 }
756
714 if (chain_context->TrustStatus.dwErrorStatus & 757 if (chain_context->TrustStatus.dwErrorStatus &
715 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { 758 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
716 ev_policy_oid = NULL; 759 ev_policy_oid = NULL;
717 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; 760 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
718 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; 761 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL;
719 CertFreeCertificateChain(chain_context); 762 CertFreeCertificateChain(chain_context);
720 if (!CertGetCertificateChain( 763 if (!CertGetCertificateChain(
721 chain_engine, 764 chain_engine,
722 cert_handle_, 765 cert_list,
723 NULL, // current system time 766 NULL, // current system time
724 cert_handle_->hCertStore, 767 cert_list->hCertStore,
725 &chain_para, 768 &chain_para,
726 chain_flags, 769 chain_flags,
727 NULL, // reserved 770 NULL, // reserved
728 &chain_context)) { 771 &chain_context)) {
772 FreeOSCertListHandle(cert_list);
729 return MapSecurityError(GetLastError()); 773 return MapSecurityError(GetLastError());
730 } 774 }
731 } 775 }
776 FreeOSCertListHandle(cert_list);
777
732 ScopedCertChainContext scoped_chain_context(chain_context); 778 ScopedCertChainContext scoped_chain_context(chain_context);
733 779
734 GetCertChainInfo(chain_context, verify_result); 780 GetCertChainInfo(chain_context, verify_result);
735 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( 781 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
736 chain_context->TrustStatus.dwErrorStatus); 782 chain_context->TrustStatus.dwErrorStatus);
737 783
738 // Treat certificates signed using broken signature algorithms as invalid. 784 // Treat certificates signed using broken signature algorithms as invalid.
739 if (verify_result->has_md4) 785 if (verify_result->has_md4)
740 verify_result->cert_status |= CERT_STATUS_INVALID; 786 verify_result->cert_status |= CERT_STATUS_INVALID;
741 787
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 OSCertHandle cert_handle) { 979 OSCertHandle cert_handle) {
934 return CertDuplicateCertificateContext(cert_handle); 980 return CertDuplicateCertificateContext(cert_handle);
935 } 981 }
936 982
937 // static 983 // static
938 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 984 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
939 CertFreeCertificateContext(cert_handle); 985 CertFreeCertificateContext(cert_handle);
940 } 986 }
941 987
942 // static 988 // static
989 void X509Certificate::FreeOSCertListHandle(OSCertListHandle cert_list) {
990 CertFreeCertificateContext(cert_list);
991 }
992
993 // static
943 SHA1Fingerprint X509Certificate::CalculateFingerprint( 994 SHA1Fingerprint X509Certificate::CalculateFingerprint(
944 OSCertHandle cert) { 995 OSCertHandle cert) {
945 DCHECK(NULL != cert->pbCertEncoded); 996 DCHECK(NULL != cert->pbCertEncoded);
946 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); 997 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded);
947 998
948 BOOL rv; 999 BOOL rv;
949 SHA1Fingerprint sha1; 1000 SHA1Fingerprint sha1;
950 DWORD sha1_size = sizeof(sha1.data); 1001 DWORD sha1_size = sizeof(sha1.data);
951 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, 1002 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
952 cert->cbCertEncoded, sha1.data, &sha1_size); 1003 cert->cbCertEncoded, sha1.data, &sha1_size);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], 1042 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0],
992 &length)) { 1043 &length)) {
993 return false; 1044 return false;
994 } 1045 }
995 1046
996 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), 1047 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]),
997 length); 1048 length);
998 } 1049 }
999 1050
1000 } // namespace net 1051 } // namespace net
OLDNEW
« net/base/x509_certificate_openssl.cc ('K') | « net/base/x509_certificate_openssl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698