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

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: Do not use CertVerifier for good certs 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 of worker task can't start.
davidben 2015/10/05 22:19:11 of -> if the
davidben 2015/10/05 22:19:11 As with the previous CL, the thread-hopping here g
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 verifyCert: and verifyTrust: will be called for ma
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Done.
88 - (void)verifyTrust:(base::ScopedCFTypeRef<SecTrustRef>)trust
89 completionHandler:(void (^)(SecTrustResultType))completionHandler;
90
83 @end 91 @end
84 92
85 @implementation CRWCertVerificationController 93 @implementation CRWCertVerificationController
86 94
87 #pragma mark - Superclass 95 #pragma mark - Superclass
88 96
89 - (void)dealloc { 97 - (void)dealloc {
90 DCHECK(!_certVerifier); 98 DCHECK(!_certVerifier);
91 [super dealloc]; 99 [super dealloc];
92 } 100 }
(...skipping 12 matching lines...) Expand all
105 if (self) { 113 if (self) {
106 _contextGetter = browserState->GetRequestContext(); 114 _contextGetter = browserState->GetRequestContext();
107 DCHECK(_contextGetter); 115 DCHECK(_contextGetter);
108 [self createCertVerifier]; 116 [self createCertVerifier];
109 } 117 }
110 return self; 118 return self;
111 } 119 }
112 120
113 - (void)decidePolicyForCert:(const scoped_refptr<net::X509Certificate>&)cert 121 - (void)decidePolicyForCert:(const scoped_refptr<net::X509Certificate>&)cert
114 host:(NSString*)host 122 host:(NSString*)host
115 completionHandler:(web::PolicyDecisionHandler)handler { 123 completionHandler:(web::PolicyDecisionHandler)completionHandler {
116 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 124 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
117 // completionHandler of |verifyCert:forHost:completionHandler:| is called on 125 // completionHandler of |verifyCert:forHost:completionHandler:| is called on
118 // IO thread and then bounces back to UI thread. As a result all objects 126 // 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. 127 // captured by completionHandler may be released on either UI or IO thread.
120 // Since |handler| can potentially capture multiple thread unsafe objects 128 // Since |completionHandler| can potentially capture multiple thread unsafe
121 // (like Web Controller) |handler| itself should never be released on 129 // objects (like Web Controller) |completionHandler| itself should never be
122 // background thread and |BlockHolder| ensures that. 130 // released on background thread and |BlockHolder| ensures that.
123 __block scoped_refptr<BlockHolder<web::PolicyDecisionHandler>> handlerHolder( 131 __block scoped_refptr<BlockHolder<web::PolicyDecisionHandler>> handlerHolder(
124 new BlockHolder<web::PolicyDecisionHandler>(handler)); 132 new BlockHolder<web::PolicyDecisionHandler>(completionHandler));
125 [self verifyCert:cert 133 [self verifyCert:cert
126 forHost:host 134 forHost:host
127 completionHandler:^(net::CertVerifyResult result, int error) { 135 completionHandler:^(net::CertVerifyResult result, int error) {
128 web::CertAcceptPolicy policy = 136 web::CertAcceptPolicy policy =
129 web::CERT_ACCEPT_POLICY_NON_RECOVERABLE_ERROR; 137 web::CERT_ACCEPT_POLICY_NON_RECOVERABLE_ERROR;
130 if (error == net::OK) { 138 if (error == net::OK) {
131 policy = web::CERT_ACCEPT_POLICY_ALLOW; 139 policy = web::CERT_ACCEPT_POLICY_ALLOW;
132 } else if (net::IsCertStatusError(result.cert_status)) { 140 } else if (net::IsCertStatusError(result.cert_status)) {
133 policy = net::IsCertStatusMinorError(result.cert_status) 141 policy = net::IsCertStatusMinorError(result.cert_status)
134 ? web::CERT_ACCEPT_POLICY_ALLOW 142 ? web::CERT_ACCEPT_POLICY_ALLOW
135 : web::CERT_ACCEPT_POLICY_RECOVERABLE_ERROR; 143 : web::CERT_ACCEPT_POLICY_RECOVERABLE_ERROR;
136 } 144 }
137 145
138 dispatch_async(dispatch_get_main_queue(), ^{ 146 dispatch_async(dispatch_get_main_queue(), ^{
139 handlerHolder->call(policy, result.cert_status); 147 handlerHolder->call(policy, result.cert_status);
140 }); 148 });
141 }]; 149 }];
142 } 150 }
143 151
152 - (void)querySSLStatusForTrust:(base::ScopedCFTypeRef<SecTrustRef>)trust
153 host:(NSString*)host
154 completionHandler:(web::StatusQueryHandler)completionHandler {
155 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
156
157 // Completion handler of |verifyCert:forHost:completionHandler:| will be
davidben 2015/10/05 22:19:10 verifyCert:forHost -> verifyTrust?
davidben 2015/10/05 22:19:11 Nit: Completion -> The completion
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Updated comments.
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Done.
158 // deallocated on IO thread. |completionHandler| itself should never be
159 // released on background thread and |BlockHolder| ensures that.
160 __block scoped_refptr<BlockHolder<web::StatusQueryHandler>> handlerHolder(
161 new BlockHolder<web::StatusQueryHandler>(completionHandler));
162 scoped_refptr<net::X509Certificate> cert(web::CreateCertFromTrust(trust));
163 [self verifyTrust:trust
164 completionHandler:^(SecTrustResultType trustResult) {
165 web::SecurityStyle securityStyle =
166 web::GetSecurityStyleFromTrustResult(trustResult);
167
168 if (securityStyle == web::SECURITY_STYLE_AUTHENTICATED) {
169 // SecTrust API considers this cert as valid.
170 dispatch_async(dispatch_get_main_queue(), ^{
171 handlerHolder->call(securityStyle, net::CertStatus());
172 });
173 return;
174 }
175
176 // Retrieve the net::CertStatus for invalid certificates to determine
177 // the rejection reason.
178 // TODO(eugenebut): Add UMA for CertVerifier and SecTrust verification
179 // mismatch (crbug.com/535699).
180 [self verifyCert:cert
181 forHost:host
davidben 2015/10/05 22:19:11 This will end up calling verifyCert if posting to
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Good point. Fixed.
182 completionHandler:^(net::CertVerifyResult certVerifierResult, int) {
183 dispatch_async(dispatch_get_main_queue(), ^{
184 handlerHolder->call(securityStyle,
185 certVerifierResult.cert_status);
186 });
187 }];
188 }];
189 }
190
144 - (void)shutDown { 191 - (void)shutDown {
145 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 192 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
146 web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{ 193 web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{
147 // This block captures |self| delaying its deallocation and causing dealloc 194 // 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). 195 // to happen on either IO or UI thread (which is fine for this class).
149 _certVerifier.reset(); 196 _certVerifier.reset();
150 })); 197 }));
151 } 198 }
152 199
153 #pragma mark - Private 200 #pragma mark - Private
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 237
191 web::CertVerifierBlockAdapter::Params params( 238 web::CertVerifierBlockAdapter::Params params(
192 blockCert.Pass(), base::SysNSStringToUTF8(host)); 239 blockCert.Pass(), base::SysNSStringToUTF8(host));
193 params.flags = self.certVerifyFlags; 240 params.flags = self.certVerifyFlags;
194 params.crl_set = net::SSLConfigService::GetCRLSet(); 241 params.crl_set = net::SSLConfigService::GetCRLSet();
195 // OCSP response is not provided by iOS API. 242 // OCSP response is not provided by iOS API.
196 _certVerifier->Verify(params, completionHandler); 243 _certVerifier->Verify(params, completionHandler);
197 })); 244 }));
198 } 245 }
199 246
247 - (void)verifyTrust:(base::ScopedCFTypeRef<SecTrustRef>)trust
248 completionHandler:(void (^)(SecTrustResultType))completionHandler {
249 DCHECK(completionHandler);
250 // SecTrustEvaluate performs trust evaluation synchronously, possibly making
251 // network requests. IO thread should not be blocked by that operation.
davidben 2015/10/05 22:19:11 Nit: The IO thread
Eugene But (OOO till 7-30) 2015/10/06 03:10:09 Done.
252 bool result = base::WorkerPool::PostTask(FROM_HERE, base::BindBlock(^{
253 SecTrustResultType trustResult = kSecTrustResultInvalid;
254 if (SecTrustEvaluate(trust.get(), &trustResult) != errSecSuccess) {
255 trustResult = kSecTrustResultInvalid;
256 }
257 completionHandler(trustResult);
258 }), false /* task_is_slow */);
259
260 if (!result) {
261 completionHandler(kSecTrustResultInvalid);
262 }
263 }
264
200 @end 265 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698