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

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: Rebase Created 9 years, 1 month 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
« no previous file with comments | « net/base/x509_certificate_mac.cc ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #define PRArenaPool PLArenaPool // Required by <blapi.h>. 7 #define PRArenaPool PLArenaPool // Required by <blapi.h>.
8 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. 8 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS.
9 9
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
12 #include "base/pickle.h" 13 #include "base/pickle.h"
13 #include "base/sha1.h" 14 #include "base/sha1.h"
14 #include "base/string_tokenizer.h" 15 #include "base/string_tokenizer.h"
15 #include "base/string_util.h" 16 #include "base/string_util.h"
16 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
17 #include "crypto/rsa_private_key.h" 18 #include "crypto/rsa_private_key.h"
18 #include "crypto/scoped_capi_types.h" 19 #include "crypto/scoped_capi_types.h"
19 #include "net/base/asn1_util.h" 20 #include "net/base/asn1_util.h"
20 #include "net/base/cert_status_flags.h" 21 #include "net/base/cert_status_flags.h"
21 #include "net/base/cert_verify_result.h" 22 #include "net/base/cert_verify_result.h"
22 #include "net/base/ev_root_ca_metadata.h" 23 #include "net/base/ev_root_ca_metadata.h"
23 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
24 #include "net/base/scoped_cert_chain_context.h"
25 #include "net/base/test_root_certs.h" 25 #include "net/base/test_root_certs.h"
26 #include "net/base/x509_certificate_known_roots_win.h" 26 #include "net/base/x509_certificate_known_roots_win.h"
27 27
28 #pragma comment(lib, "crypt32.lib") 28 #pragma comment(lib, "crypt32.lib")
29 29
30 using base::Time; 30 using base::Time;
31 31
32 namespace net { 32 namespace net {
33 33
34 namespace { 34 namespace {
35 35
36 typedef crypto::ScopedCAPIHandle<
37 HCERTSTORE,
38 crypto::CAPIDestroyerWithFlags<HCERTSTORE,
39 CertCloseStore, 0> > ScopedHCERTSTORE;
40
41 struct FreeChainEngineFunctor { 36 struct FreeChainEngineFunctor {
42 void operator()(HCERTCHAINENGINE engine) const { 37 void operator()(HCERTCHAINENGINE engine) const {
43 if (engine) 38 if (engine)
44 CertFreeCertificateChainEngine(engine); 39 CertFreeCertificateChainEngine(engine);
45 } 40 }
46 }; 41 };
47 42
43 struct FreeCertContextFunctor {
44 void operator()(PCCERT_CONTEXT context) const {
45 if (context)
46 CertFreeCertificateContext(context);
47 }
48 };
49
50 struct FreeCertChainContextFunctor {
51 void operator()(PCCERT_CHAIN_CONTEXT chain_context) const {
52 if (chain_context)
53 CertFreeCertificateChain(chain_context);
54 }
55 };
56
48 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> 57 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor>
49 ScopedHCERTCHAINENGINE; 58 ScopedHCERTCHAINENGINE;
50 59
60 typedef crypto::ScopedCAPIHandle<
61 HCERTSTORE,
62 crypto::CAPIDestroyerWithFlags<HCERTSTORE,
63 CertCloseStore, 0> > ScopedHCERTSTORE;
64
65 typedef scoped_ptr_malloc<const CERT_CONTEXT,
66 FreeCertContextFunctor> ScopedPCCERT_CONTEXT;
67
68 typedef scoped_ptr_malloc<const CERT_CHAIN_CONTEXT,
69 FreeCertChainContextFunctor>
70 ScopedPCCERT_CHAIN_CONTEXT;
71
51 //----------------------------------------------------------------------------- 72 //-----------------------------------------------------------------------------
52 73
53 // TODO(wtc): This is a copy of the MapSecurityError function in 74 // TODO(wtc): This is a copy of the MapSecurityError function in
54 // ssl_client_socket_win.cc. Another function that maps Windows error codes 75 // ssl_client_socket_win.cc. Another function that maps Windows error codes
55 // to our network error codes is WinInetUtil::OSErrorToNetError. We should 76 // to our network error codes is WinInetUtil::OSErrorToNetError. We should
56 // eliminate the code duplication. 77 // eliminate the code duplication.
57 int MapSecurityError(SECURITY_STATUS err) { 78 int MapSecurityError(SECURITY_STATUS err) {
58 // There are numerous security error codes, but these are the ones we thus 79 // There are numerous security error codes, but these are the ones we thus
59 // far find interesting. 80 // far find interesting.
60 switch (err) { 81 switch (err) {
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 709
689 static base::LazyInstance<GlobalCertStore, 710 static base::LazyInstance<GlobalCertStore,
690 base::LeakyLazyInstanceTraits<GlobalCertStore> > 711 base::LeakyLazyInstanceTraits<GlobalCertStore> >
691 g_cert_store(base::LINKER_INITIALIZED); 712 g_cert_store(base::LINKER_INITIALIZED);
692 713
693 // static 714 // static
694 HCERTSTORE X509Certificate::cert_store() { 715 HCERTSTORE X509Certificate::cert_store() {
695 return g_cert_store.Get().cert_store(); 716 return g_cert_store.Get().cert_store();
696 } 717 }
697 718
719 PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const {
720 // Create an in-memory certificate store to hold this certificate and
721 // any intermediate certificates in |intermediate_ca_certs_|. The store
722 // will be referenced in the returned PCCERT_CONTEXT, and will not be freed
723 // until the PCCERT_CONTEXT is freed.
724 ScopedHCERTSTORE store(CertOpenStore(
725 CERT_STORE_PROV_MEMORY, 0, NULL,
726 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL));
727 if (!store.get())
728 return NULL;
729
730 // NOTE: This preserves all of the properties of |os_cert_handle()| except
731 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
732 // properties that hold access to already-opened private keys. If a handle
733 // has already been unlocked (eg: PIN prompt), then the first time that the
734 // identity is used for client auth, it may prompt the user again.
735 PCCERT_CONTEXT primary_cert;
736 BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(),
737 CERT_STORE_ADD_ALWAYS,
738 &primary_cert);
739 if (!ok || !primary_cert)
740 return NULL;
741
742 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
743 CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i],
744 CERT_STORE_ADD_ALWAYS, NULL);
745 }
746
747 // Note: |store| is explicitly not released, as the call to CertCloseStore()
748 // when |store| goes out of scope will not actually free the store. Instead,
749 // the store will be freed when |primary_cert| is freed.
750 return primary_cert;
751 }
752
698 int X509Certificate::VerifyInternal(const std::string& hostname, 753 int X509Certificate::VerifyInternal(const std::string& hostname,
699 int flags, 754 int flags,
700 CRLSet* crl_set, 755 CRLSet* crl_set,
701 CertVerifyResult* verify_result) const { 756 CertVerifyResult* verify_result) const {
702 if (!cert_handle_) 757 if (!cert_handle_)
703 return ERR_UNEXPECTED; 758 return ERR_UNEXPECTED;
704 759
705 // Build and validate certificate chain. 760 // Build and validate certificate chain.
706 CERT_CHAIN_PARA chain_para; 761 CERT_CHAIN_PARA chain_para;
707 memset(&chain_para, 0, sizeof(chain_para)); 762 memset(&chain_para, 0, sizeof(chain_para));
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by 810 // corresponds to HCCE_CURRENT_USER and is is initialized as needed by
756 // crypt32. However, when testing, it is necessary to create a new 811 // crypt32. However, when testing, it is necessary to create a new
757 // HCERTCHAINENGINE and use that instead. This is because each 812 // HCERTCHAINENGINE and use that instead. This is because each
758 // HCERTCHAINENGINE maintains a cache of information about certificates 813 // HCERTCHAINENGINE maintains a cache of information about certificates
759 // encountered, and each test run may modify the trust status of a 814 // encountered, and each test run may modify the trust status of a
760 // certificate. 815 // certificate.
761 ScopedHCERTCHAINENGINE chain_engine(NULL); 816 ScopedHCERTCHAINENGINE chain_engine(NULL);
762 if (TestRootCerts::HasInstance()) 817 if (TestRootCerts::HasInstance())
763 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); 818 chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
764 819
820 ScopedPCCERT_CONTEXT cert_list(CreateOSCertChainForCert());
765 PCCERT_CHAIN_CONTEXT chain_context; 821 PCCERT_CHAIN_CONTEXT chain_context;
766 // IE passes a non-NULL pTime argument that specifies the current system 822 // IE passes a non-NULL pTime argument that specifies the current system
767 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the 823 // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
768 // chain_flags argument. 824 // chain_flags argument.
769 if (!CertGetCertificateChain( 825 if (!CertGetCertificateChain(
770 chain_engine, 826 chain_engine,
771 cert_handle_, 827 cert_list.get(),
772 NULL, // current system time 828 NULL, // current system time
773 cert_handle_->hCertStore, 829 cert_list->hCertStore,
774 &chain_para, 830 &chain_para,
775 chain_flags, 831 chain_flags,
776 NULL, // reserved 832 NULL, // reserved
777 &chain_context)) { 833 &chain_context)) {
778 return MapSecurityError(GetLastError()); 834 return MapSecurityError(GetLastError());
779 } 835 }
836
780 if (chain_context->TrustStatus.dwErrorStatus & 837 if (chain_context->TrustStatus.dwErrorStatus &
781 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { 838 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
782 ev_policy_oid = NULL; 839 ev_policy_oid = NULL;
783 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0; 840 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
784 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL; 841 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = NULL;
785 CertFreeCertificateChain(chain_context); 842 CertFreeCertificateChain(chain_context);
786 if (!CertGetCertificateChain( 843 if (!CertGetCertificateChain(
787 chain_engine, 844 chain_engine,
788 cert_handle_, 845 cert_list.get(),
789 NULL, // current system time 846 NULL, // current system time
790 cert_handle_->hCertStore, 847 cert_list->hCertStore,
791 &chain_para, 848 &chain_para,
792 chain_flags, 849 chain_flags,
793 NULL, // reserved 850 NULL, // reserved
794 &chain_context)) { 851 &chain_context)) {
795 return MapSecurityError(GetLastError()); 852 return MapSecurityError(GetLastError());
796 } 853 }
797 } 854 }
798 ScopedCertChainContext scoped_chain_context(chain_context); 855
856 ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context);
799 857
800 GetCertChainInfo(chain_context, verify_result); 858 GetCertChainInfo(chain_context, verify_result);
801 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( 859 verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
802 chain_context->TrustStatus.dwErrorStatus); 860 chain_context->TrustStatus.dwErrorStatus);
803 861
804 // Treat certificates signed using broken signature algorithms as invalid. 862 // Treat certificates signed using broken signature algorithms as invalid.
805 if (verify_result->has_md4) 863 if (verify_result->has_md4)
806 verify_result->cert_status |= CERT_STATUS_INVALID; 864 verify_result->cert_status |= CERT_STATUS_INVALID;
807 865
808 // Flag certificates signed using weak signature algorithms. 866 // Flag certificates signed using weak signature algorithms.
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0], 1135 if (!CertSerializeCertificateStoreElement(cert_handle, 0, &buffer[0],
1078 &length)) { 1136 &length)) {
1079 return false; 1137 return false;
1080 } 1138 }
1081 1139
1082 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]), 1140 return pickle->WriteData(reinterpret_cast<const char*>(&buffer[0]),
1083 length); 1141 length);
1084 } 1142 }
1085 1143
1086 } // namespace net 1144 } // namespace net
OLDNEW
« no previous file with comments | « net/base/x509_certificate_mac.cc ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698