OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |