1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/platform_keys/verify_trust_api.h"
9 #include "base/lazy_instance.h"
10 #include "base/macros.h"
11 #include "base/memory/linked_ptr.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/stl_util.h"
14 #include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
15 #include "chrome/common/extensions/api/platform_keys_internal.h"
16 #include "extensions/browser/extension_registry_factory.h"
17 #include "net/base/net_errors.h"
18 #include "net/cert/cert_verifier.h"
19 #include "net/cert/cert_verify_result.h"
20 #include "net/cert/x509_certificate.h"
21 #include "net/log/net_log.h"
22 #include "net/ssl/ssl_config_service.h"
24 namespace extensions
{
28 base::LazyInstance
<BrowserContextKeyedAPIFactory
<VerifyTrustAPI
>>::Leaky
29 g_factory
= LAZY_INSTANCE_INITIALIZER
;
31 const char kErrorEmptyCertificateChain
[] =
32 "Server certificate chain must not be empty.";
36 // This class bundles IO data and functions of the VerifyTrustAPI that are to be
37 // used on the IO thread only.
38 // It is created on the UI thread and afterwards lives on the IO thread.
39 class VerifyTrustAPI::IOPart
{
43 // Verifies the certificate as stated by |params| and calls back |callback|
44 // with the result (see the declaration of VerifyCallback).
45 // Will not call back after this object is destructed or the verifier for this
46 // extension is deleted (see OnExtensionUnloaded).
47 void Verify(scoped_ptr
<Params
> params
,
48 const std::string
& extension_id
,
49 const VerifyCallback
& callback
);
51 // Must be called when the extension with id |extension_id| is unloaded.
52 // Deletes the verifier for |extension_id| and cancels all pending
53 // verifications of this verifier.
54 void OnExtensionUnloaded(const std::string
& extension_id
);
60 scoped_ptr
<net::CertVerifier::Request
> request
;
63 DISALLOW_COPY_AND_ASSIGN(RequestState
);
66 // Calls back |callback| with the result and no error.
67 void CallBackWithResult(const VerifyCallback
& callback
,
68 scoped_ptr
<net::CertVerifyResult
> verify_result
,
69 RequestState
* request_state
,
72 // One CertVerifier per extension to verify trust. Each verifier is created on
73 // first usage and deleted when this IOPart is destructed or the respective
74 // extension is unloaded.
75 std::map
<std::string
, linked_ptr
<net::CertVerifier
>> extension_to_verifier_
;
79 BrowserContextKeyedAPIFactory
<VerifyTrustAPI
>*
80 VerifyTrustAPI::GetFactoryInstance() {
81 return g_factory
.Pointer();
85 void BrowserContextKeyedAPIFactory
<
86 VerifyTrustAPI
>::DeclareFactoryDependencies() {
87 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
88 DependsOn(ExtensionRegistryFactory::GetInstance());
91 VerifyTrustAPI::VerifyTrustAPI(content::BrowserContext
* context
)
92 : io_part_(new IOPart
), registry_observer_(this), weak_factory_(this) {
93 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
94 registry_observer_
.Add(ExtensionRegistry::Get(context
));
97 VerifyTrustAPI::~VerifyTrustAPI() {
98 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
101 void VerifyTrustAPI::Verify(scoped_ptr
<Params
> params
,
102 const std::string
& extension_id
,
103 const VerifyCallback
& ui_callback
) {
104 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
106 // Call back through the VerifyTrustAPI object on the UIThread. Because of the
107 // WeakPtr usage, this will ensure that |ui_callback| is not called after the
109 VerifyCallback
finish_callback(base::Bind(
110 &CallBackOnUI
, base::Bind(&VerifyTrustAPI::FinishedVerificationOnUI
,
111 weak_factory_
.GetWeakPtr(), ui_callback
)));
113 content::BrowserThread::PostTask(
114 content::BrowserThread::IO
, FROM_HERE
,
115 base::Bind(&IOPart::Verify
, base::Unretained(io_part_
.get()),
116 base::Passed(¶ms
), extension_id
, finish_callback
));
119 void VerifyTrustAPI::OnExtensionUnloaded(
120 content::BrowserContext
* browser_context
,
121 const Extension
* extension
,
122 UnloadedExtensionInfo::Reason reason
) {
123 content::BrowserThread::PostTask(
124 content::BrowserThread::IO
, FROM_HERE
,
125 base::Bind(&IOPart::OnExtensionUnloaded
, base::Unretained(io_part_
.get()),
129 void VerifyTrustAPI::FinishedVerificationOnUI(const VerifyCallback
& ui_callback
,
130 const std::string
& error
,
133 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
135 ui_callback
.Run(error
, return_value
, cert_status
);
139 void VerifyTrustAPI::CallBackOnUI(const VerifyCallback
& ui_callback
,
140 const std::string
& error
,
143 content::BrowserThread::PostTask(
144 content::BrowserThread::UI
, FROM_HERE
,
145 base::Bind(ui_callback
, error
, return_value
, cert_status
));
148 VerifyTrustAPI::IOPart::~IOPart() {
149 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
152 void VerifyTrustAPI::IOPart::Verify(scoped_ptr
<Params
> params
,
153 const std::string
& extension_id
,
154 const VerifyCallback
& callback
) {
155 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
157 const api::platform_keys::VerificationDetails
& details
= params
->details
;
159 if (details
.server_certificate_chain
.empty()) {
160 callback
.Run(kErrorEmptyCertificateChain
, 0, 0);
164 std::vector
<base::StringPiece
> der_cert_chain
;
165 for (const std::vector
<char>& cert_der
: details
.server_certificate_chain
) {
166 if (cert_der
.empty()) {
167 callback
.Run(platform_keys::kErrorInvalidX509Cert
, 0, 0);
170 der_cert_chain
.push_back(base::StringPiece(
171 reinterpret_cast<const char*>(vector_as_array(&cert_der
)),
174 scoped_refptr
<net::X509Certificate
> cert_chain(
175 net::X509Certificate::CreateFromDERCertChain(der_cert_chain
));
177 callback
.Run(platform_keys::kErrorInvalidX509Cert
, 0, 0);
181 if (!ContainsKey(extension_to_verifier_
, extension_id
)) {
182 extension_to_verifier_
[extension_id
] =
183 make_linked_ptr(net::CertVerifier::CreateDefault().release());
185 net::CertVerifier
* verifier
= extension_to_verifier_
[extension_id
].get();
187 scoped_ptr
<net::CertVerifyResult
> verify_result(new net::CertVerifyResult
);
188 scoped_ptr
<net::BoundNetLog
> net_log(new net::BoundNetLog
);
191 std::string ocsp_response
;
192 net::CertVerifyResult
* const verify_result_ptr
= verify_result
.get();
194 RequestState
* request_state
= new RequestState();
195 base::Callback
<void(int)> bound_callback(
196 base::Bind(&IOPart::CallBackWithResult
, base::Unretained(this), callback
,
197 base::Passed(&verify_result
), base::Owned(request_state
)));
199 const int return_value
= verifier
->Verify(
200 cert_chain
.get(), details
.hostname
, ocsp_response
, flags
,
201 net::SSLConfigService::GetCRLSet().get(), verify_result_ptr
,
202 bound_callback
, &request_state
->request
, *net_log
);
204 if (return_value
!= net::ERR_IO_PENDING
) {
205 bound_callback
.Run(return_value
);
210 void VerifyTrustAPI::IOPart::OnExtensionUnloaded(
211 const std::string
& extension_id
) {
212 extension_to_verifier_
.erase(extension_id
);
215 void VerifyTrustAPI::IOPart::CallBackWithResult(
216 const VerifyCallback
& callback
,
217 scoped_ptr
<net::CertVerifyResult
> verify_result
,
218 RequestState
* request_state
,
220 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
222 callback
.Run(std::string() /* no error message */, return_value
,
223 verify_result
->cert_status
);
226 } // namespace extensions