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

Side by Side Diff: ios/web/net/crw_cert_verification_controller.mm

Issue 1322193003: WKWebView(iOS9): correctly update SSL status for current navigation item (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@reland_cert_verification
Patch Set: Updated comments Created 5 years, 2 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 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 #import "ios/web/net/crw_cert_verification_controller.h" 5 #import "ios/web/net/crw_cert_verification_controller.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/mac/bind_objc_block.h" 8 #include "base/mac/bind_objc_block.h"
9 #import "base/memory/ref_counted.h" 9 #import "base/memory/ref_counted.h"
10 #import "base/memory/scoped_ptr.h" 10 #import "base/memory/scoped_ptr.h"
11 #include "base/strings/sys_string_conversions.h" 11 #include "base/strings/sys_string_conversions.h"
12 #include "base/threading/worker_pool.h"
12 #include "ios/web/net/cert_verifier_block_adapter.h" 13 #include "ios/web/net/cert_verifier_block_adapter.h"
13 #include "ios/web/public/browser_state.h" 14 #include "ios/web/public/browser_state.h"
14 #include "ios/web/public/web_thread.h" 15 #include "ios/web/public/web_thread.h"
16 #import "ios/web/web_state/wk_web_view_security_util.h"
15 #include "net/cert/cert_verify_result.h" 17 #include "net/cert/cert_verify_result.h"
16 #include "net/ssl/ssl_config_service.h" 18 #include "net/ssl/ssl_config_service.h"
17 #include "net/url_request/url_request_context.h" 19 #include "net/url_request/url_request_context.h"
18 #include "net/url_request/url_request_context_getter.h" 20 #include "net/url_request/url_request_context_getter.h"
19 21
20 namespace { 22 namespace {
21 23
22 // This class takes ownership of block and releases it on UI thread, even if 24 // This class takes ownership of block and releases it on UI thread, even if
23 // |BlockHolder| is destructed on a background thread. 25 // |BlockHolder| is destructed on a background thread.
24 template <class T> 26 template <class T>
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 // URLRequestContextGetter for obtaining net layer objects. 68 // URLRequestContextGetter for obtaining net layer objects.
67 net::URLRequestContextGetter* _contextGetter; 69 net::URLRequestContextGetter* _contextGetter;
68 } 70 }
69 71
70 // Cert verification flags. Must be used on IO Thread. 72 // Cert verification flags. Must be used on IO Thread.
71 @property(nonatomic, readonly) int certVerifyFlags; 73 @property(nonatomic, readonly) int certVerifyFlags;
72 74
73 // Creates _certVerifier object on IO thread. 75 // Creates _certVerifier object on IO thread.
74 - (void)createCertVerifier; 76 - (void)createCertVerifier;
75 77
76 // Verifies the given |cert| for the given |host| and calls |completionHandler| 78 // Verifies the given |cert| for the given |host| using |net::CertVerifier| and
77 // on completion. |completionHandler| cannot be null and will be called 79 // calls |completionHandler| on completion. |completionHandler| cannot be null
78 // synchronously or asynchronously on IO thread. 80 // and will be called asynchronously on IO thread.
79 - (void)verifyCert:(const scoped_refptr<net::X509Certificate>&)cert 81 - (void)verifyCert:(const scoped_refptr<net::X509Certificate>&)cert
80 forHost:(NSString*)host 82 forHost:(NSString*)host
81 completionHandler:(void (^)(net::CertVerifyResult, int))completionHandler; 83 completionHandler:(void (^)(net::CertVerifyResult, int))completionHandler;
82 84
85 // Verifies the given |trust| using SecTrustRef API. |completionHandler| cannot
86 // be null and will be either called asynchronously on Worker thread or
87 // synchronously on current thread if the worker task can't start (in this
88 // case |success| argument will be NO).
89 - (void)verifyTrust:(base::ScopedCFTypeRef<SecTrustRef>)trust
90 completionHandler:(void (^)(SecTrustResultType, BOOL success))handler;
davidben 2015/10/12 23:21:50 If you want to keep this double-threaded thing, pe
Eugene But (OOO till 7-30) 2015/10/13 20:40:33 Done.
91
83 @end 92 @end
84 93
85 @implementation CRWCertVerificationController 94 @implementation CRWCertVerificationController
86 95
87 #pragma mark - Superclass 96 #pragma mark - Superclass
88 97
89 - (void)dealloc { 98 - (void)dealloc {
90 DCHECK(!_certVerifier); 99 DCHECK(!_certVerifier);
91 [super dealloc]; 100 [super dealloc];
92 } 101 }
(...skipping 12 matching lines...) Expand all
105 if (self) { 114 if (self) {
106 _contextGetter = browserState->GetRequestContext(); 115 _contextGetter = browserState->GetRequestContext();
107 DCHECK(_contextGetter); 116 DCHECK(_contextGetter);
108 [self createCertVerifier]; 117 [self createCertVerifier];
109 } 118 }
110 return self; 119 return self;
111 } 120 }
112 121
113 - (void)decidePolicyForCert:(const scoped_refptr<net::X509Certificate>&)cert 122 - (void)decidePolicyForCert:(const scoped_refptr<net::X509Certificate>&)cert
114 host:(NSString*)host 123 host:(NSString*)host
115 completionHandler:(web::PolicyDecisionHandler)handler { 124 completionHandler:(web::PolicyDecisionHandler)completionHandler {
116 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 125 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
117 // completionHandler of |verifyCert:forHost:completionHandler:| is called on 126 // completionHandler of |verifyCert:forHost:completionHandler:| is called on
118 // IO thread and then bounces back to UI thread. As a result all objects 127 // IO thread and then bounces back to UI thread. As a result all objects
119 // captured by completionHandler may be released on either UI or IO thread. 128 // captured by completionHandler may be released on either UI or IO thread.
120 // Since |handler| can potentially capture multiple thread unsafe objects 129 // Since |completionHandler| can potentially capture multiple thread unsafe
121 // (like Web Controller) |handler| itself should never be released on 130 // objects (like Web Controller) |completionHandler| itself should never be
122 // background thread and |BlockHolder| ensures that. 131 // released on background thread and |BlockHolder| ensures that.
123 __block scoped_refptr<BlockHolder<web::PolicyDecisionHandler>> handlerHolder( 132 __block scoped_refptr<BlockHolder<web::PolicyDecisionHandler>> handlerHolder(
124 new BlockHolder<web::PolicyDecisionHandler>(handler)); 133 new BlockHolder<web::PolicyDecisionHandler>(completionHandler));
125 [self verifyCert:cert 134 [self verifyCert:cert
126 forHost:host 135 forHost:host
127 completionHandler:^(net::CertVerifyResult result, int error) { 136 completionHandler:^(net::CertVerifyResult result, int error) {
128 web::CertAcceptPolicy policy = 137 web::CertAcceptPolicy policy =
129 web::CERT_ACCEPT_POLICY_NON_RECOVERABLE_ERROR; 138 web::CERT_ACCEPT_POLICY_NON_RECOVERABLE_ERROR;
130 if (error == net::OK) { 139 if (error == net::OK) {
131 policy = web::CERT_ACCEPT_POLICY_ALLOW; 140 policy = web::CERT_ACCEPT_POLICY_ALLOW;
132 } else if (net::IsCertStatusError(result.cert_status)) { 141 } else if (net::IsCertStatusError(result.cert_status)) {
133 policy = net::IsCertStatusMinorError(result.cert_status) 142 policy = net::IsCertStatusMinorError(result.cert_status)
134 ? web::CERT_ACCEPT_POLICY_ALLOW 143 ? web::CERT_ACCEPT_POLICY_ALLOW
135 : web::CERT_ACCEPT_POLICY_RECOVERABLE_ERROR; 144 : web::CERT_ACCEPT_POLICY_RECOVERABLE_ERROR;
136 } 145 }
137 146
138 dispatch_async(dispatch_get_main_queue(), ^{ 147 dispatch_async(dispatch_get_main_queue(), ^{
139 handlerHolder->call(policy, result.cert_status); 148 handlerHolder->call(policy, result.cert_status);
140 }); 149 });
141 }]; 150 }];
142 } 151 }
143 152
153 - (void)querySSLStatusForTrust:(base::ScopedCFTypeRef<SecTrustRef>)trust
154 host:(NSString*)host
155 completionHandler:(web::StatusQueryHandler)completionHandler {
156 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
157
158 // The completion handlers of |verifyCert:forHost:completionHandler:| and
159 // |verifyTrust:completionHandler:| will be deallocated on background thread.
160 // |completionHandler| itself should never be released on background thread
161 // and |BlockHolder| ensures that.
162 __block scoped_refptr<BlockHolder<web::StatusQueryHandler>> handlerHolder(
163 new BlockHolder<web::StatusQueryHandler>(completionHandler));
164 [self verifyTrust:trust
165 completionHandler:^(SecTrustResultType trustResult, BOOL success) {
166 if (!success) {
167 dispatch_async(dispatch_get_main_queue(), ^{
168 handlerHolder->call(web::SECURITY_STYLE_UNKNOWN, net::CertStatus());
169 });
170 return;
171 }
172
173 web::SecurityStyle securityStyle =
174 web::GetSecurityStyleFromTrustResult(trustResult);
175 if (securityStyle == web::SECURITY_STYLE_AUTHENTICATED) {
176 // SecTrust API considers this cert as valid.
177 dispatch_async(dispatch_get_main_queue(), ^{
178 handlerHolder->call(securityStyle, net::CertStatus());
179 });
180 return;
181 }
182
183 // Retrieve the net::CertStatus for invalid certificates to determine
184 // the rejection reason.
185 // TODO(eugenebut): Add UMA for CertVerifier and SecTrust verification
186 // mismatch (crbug.com/535699).
187 scoped_refptr<net::X509Certificate> cert(
188 web::CreateCertFromTrust(trust));
189 [self verifyCert:cert
190 forHost:host
191 completionHandler:^(net::CertVerifyResult certVerifierResult, int) {
192 dispatch_async(dispatch_get_main_queue(), ^{
193 handlerHolder->call(securityStyle,
194 certVerifierResult.cert_status);
195 });
196 }];
197 }];
198 }
199
144 - (void)shutDown { 200 - (void)shutDown {
145 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 201 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
146 web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{ 202 web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{
147 // This block captures |self| delaying its deallocation and causing dealloc 203 // This block captures |self| delaying its deallocation and causing dealloc
148 // to happen on either IO or UI thread (which is fine for this class). 204 // to happen on either IO or UI thread (which is fine for this class).
149 _certVerifier.reset(); 205 _certVerifier.reset();
150 })); 206 }));
151 } 207 }
152 208
153 #pragma mark - Private 209 #pragma mark - Private
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 246
191 web::CertVerifierBlockAdapter::Params params( 247 web::CertVerifierBlockAdapter::Params params(
192 blockCert.Pass(), base::SysNSStringToUTF8(host)); 248 blockCert.Pass(), base::SysNSStringToUTF8(host));
193 params.flags = self.certVerifyFlags; 249 params.flags = self.certVerifyFlags;
194 params.crl_set = net::SSLConfigService::GetCRLSet(); 250 params.crl_set = net::SSLConfigService::GetCRLSet();
195 // OCSP response is not provided by iOS API. 251 // OCSP response is not provided by iOS API.
196 _certVerifier->Verify(params, completionHandler); 252 _certVerifier->Verify(params, completionHandler);
197 })); 253 }));
198 } 254 }
199 255
256 - (void)verifyTrust:(base::ScopedCFTypeRef<SecTrustRef>)trust
257 completionHandler:(void (^)(SecTrustResultType, BOOL))completionHandler {
258 DCHECK(completionHandler);
259 // SecTrustEvaluate performs trust evaluation synchronously, possibly making
260 // network requests. The UI thread should not be blocked by that operation.
261 bool result = base::WorkerPool::PostTask(FROM_HERE, base::BindBlock(^{
262 SecTrustResultType trustResult = kSecTrustResultInvalid;
263 if (SecTrustEvaluate(trust.get(), &trustResult) != errSecSuccess) {
264 trustResult = kSecTrustResultInvalid;
265 }
266 completionHandler(trustResult, YES);
267 }), false /* task_is_slow */);
268
269 if (!result) {
270 completionHandler(kSecTrustResultInvalid, NO);
271 }
272 }
273
200 @end 274 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698