OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "net/socket/ssl_client_socket_mac.h" | |
6 | |
7 #include <CoreServices/CoreServices.h> | |
8 #include <netdb.h> | |
9 #include <sys/socket.h> | |
10 #include <sys/types.h> | |
11 | |
12 #include <algorithm> | |
13 | |
14 #include "base/bind.h" | |
15 #include "base/lazy_instance.h" | |
16 #include "base/mac/mac_logging.h" | |
17 #include "base/mac/scoped_cftyperef.h" | |
18 #include "base/string_util.h" | |
19 #include "net/base/address_list.h" | |
20 #include "net/base/cert_verifier.h" | |
21 #include "net/base/io_buffer.h" | |
22 #include "net/base/net_errors.h" | |
23 #include "net/base/net_log.h" | |
24 #include "net/base/single_request_cert_verifier.h" | |
25 #include "net/base/ssl_cert_request_info.h" | |
26 #include "net/base/ssl_connection_status_flags.h" | |
27 #include "net/base/ssl_info.h" | |
28 #include "net/base/x509_certificate_net_log_param.h" | |
29 #include "net/base/x509_util.h" | |
30 #include "net/socket/client_socket_handle.h" | |
31 #include "net/socket/ssl_error_params.h" | |
32 | |
33 // Welcome to Mac SSL. We've been waiting for you. | |
34 // | |
35 // The Mac SSL implementation is, like the Windows and NSS implementations, a | |
36 // giant state machine. This design constraint is due to the asynchronous nature | |
37 // of our underlying transport mechanism. We can call down to read/write on the | |
38 // network, but what happens is that either it completes immediately or returns | |
39 // saying that we'll get a callback sometime in the future. In that case, we | |
40 // have to return to our caller but pick up where we left off when we | |
41 // resume. Thus the fun. | |
42 // | |
43 // On Windows, we use Security Contexts, which are driven by us. We fetch data | |
44 // from the network, we call the context to decrypt the data, and so on. On the | |
45 // Mac, however, we provide Secure Transport with callbacks to get data from the | |
46 // network, and it calls us back to fetch the data from the network for | |
47 // it. Therefore, there are different sets of states in our respective state | |
48 // machines, fewer on the Mac because Secure Transport keeps a lot of its own | |
49 // state. The discussion about what each of the states means lives in comments | |
50 // in the DoHandshakeLoop() function. | |
51 // | |
52 // Secure Transport is designed for use by either blocking or non-blocking | |
53 // network I/O. If, for example, you called SSLRead() to fetch data, Secure | |
54 // Transport will, unless it has some cached data, issue a read to your network | |
55 // callback read function to fetch it some more encrypted data. It's expecting | |
56 // one of two things. If your function is hooked up to a blocking source, then | |
57 // it'll block pending receipt of the data from the other end. That's fine, as | |
58 // when you return with the data, Secure Transport will do its thing. On the | |
59 // other hand, suppose that your socket is non-blocking and tells your function | |
60 // that it would block. Then you let Secure Transport know, and it'll tell the | |
61 // original caller that it would have blocked and that they need to call it | |
62 // "later." | |
63 // | |
64 // When's "later," though? We have fully-asynchronous networking, so we get a | |
65 // callback when our data's ready. But Secure Transport has no way for us to | |
66 // tell it that data has arrived, so we must re-execute the call that triggered | |
67 // the I/O (we rely on our state machine to do this). When we do so Secure | |
68 // Transport will ask once again for the data. Chances are that it'll be the | |
69 // same request as the previous time, but that's not actually guaranteed. But as | |
70 // long as we buffer what we have and keep track of where we were, it works | |
71 // quite well. | |
72 // | |
73 // Except for network writes. They shoot this plan straight to hell. | |
74 // | |
75 // Faking a blocking connection with an asynchronous connection (theoretically | |
76 // more powerful) simply doesn't work for writing. Suppose that Secure Transport | |
77 // requests a write of data to the network. With blocking I/O, we'd just block | |
78 // until the write completed, and with non-blocking I/O we'd know how many bytes | |
79 // we wrote before we would have blocked. But with the asynchronous I/O, the | |
80 // transport underneath us can tell us that it'll let us know sometime "later" | |
81 // whether or not things succeeded, and how many bytes were written. What do we | |
82 // return to Secure Transport? We can't return a byte count, but we can't return | |
83 // "later" as we're not guaranteed to be called in the future with the same data | |
84 // to write. | |
85 // | |
86 // So, like in any good relationship, we're forced to lie. Whenever Secure | |
87 // Transport asks for data to be written, we take it all and lie about it always | |
88 // being written. We spin in a loop (see SSLWriteCallback() and | |
89 // OnTransportWriteComplete()) independent of the main state machine writing | |
90 // the data to the network, and get the data out. The main consequence of this | |
91 // independence from the state machine is that we require a full-duplex | |
92 // transport underneath us since we can't use it to keep our reading and | |
93 // writing straight. Fortunately, the NSS implementation also has this issue | |
94 // to deal with, so we share the same Libevent-based full-duplex TCP socket. | |
95 // | |
96 // A side comment on return values might be in order. Those who haven't taken | |
97 // the time to read the documentation (ahem, header comments) in our various | |
98 // files might be a bit surprised to see result values being treated as both | |
99 // lengths and errors. Like Shimmer, they are both. In both the case of | |
100 // immediate results as well as results returned in callbacks, a negative return | |
101 // value indicates an error, a zero return value indicates end-of-stream (for | |
102 // reads), and a positive return value indicates the number of bytes read or | |
103 // written. Thus, many functions start off with |if (result < 0) return | |
104 // result;|. That gets the error condition out of the way, and from that point | |
105 // forward the result can be treated as a length. | |
106 | |
107 namespace net { | |
108 | |
109 namespace { | |
110 | |
111 // Pause if we have 2MB of data in flight, resume once we're down below 1MB. | |
112 const unsigned int kWriteSizePauseLimit = 2 * 1024 * 1024; | |
113 const unsigned int kWriteSizeResumeLimit = 1 * 1024 * 1024; | |
114 | |
115 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 | |
116 // When compiled against the Mac OS X 10.5 SDK, define symbolic constants for | |
117 // cipher suites added in Mac OS X 10.6. | |
118 enum { | |
119 // ECC cipher suites from RFC 4492. | |
120 TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001, | |
121 TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002, | |
122 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003, | |
123 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004, | |
124 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005, | |
125 TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006, | |
126 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007, | |
127 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008, | |
128 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009, | |
129 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A, | |
130 TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B, | |
131 TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C, | |
132 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D, | |
133 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E, | |
134 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F, | |
135 TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010, | |
136 TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011, | |
137 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012, | |
138 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, | |
139 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, | |
140 TLS_ECDH_anon_WITH_NULL_SHA = 0xC015, | |
141 TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016, | |
142 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017, | |
143 TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018, | |
144 TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019, | |
145 }; | |
146 #endif | |
147 | |
148 // For an explanation of the Mac OS X error codes, please refer to: | |
149 // http://developer.apple.com/mac/library/documentation/Security/Reference/secur
eTransportRef/Reference/reference.html | |
150 int NetErrorFromOSStatus(OSStatus status) { | |
151 switch (status) { | |
152 case errSSLWouldBlock: | |
153 return ERR_IO_PENDING; | |
154 case paramErr: | |
155 case errSSLBadCipherSuite: | |
156 case errSSLBadConfiguration: | |
157 return ERR_INVALID_ARGUMENT; | |
158 case errSSLClosedNoNotify: | |
159 return ERR_CONNECTION_RESET; | |
160 case errSSLClosedAbort: | |
161 return ERR_CONNECTION_ABORTED; | |
162 case errSSLInternal: | |
163 return ERR_UNEXPECTED; | |
164 case errSSLBadRecordMac: | |
165 case errSSLCrypto: | |
166 case errSSLConnectionRefused: | |
167 case errSSLDecryptionFail: | |
168 case errSSLFatalAlert: | |
169 case errSSLIllegalParam: // Received an illegal_parameter alert. | |
170 case errSSLPeerDecodeError: // Received a decode_error alert. | |
171 case errSSLPeerDecryptError: // Received a decrypt_error alert. | |
172 case errSSLPeerExportRestriction: // Received an export_restriction alert. | |
173 case errSSLPeerHandshakeFail: // Received a handshake_failure alert. | |
174 case errSSLPeerNoRenegotiation: // Received a no_renegotiation alert | |
175 case errSSLPeerUnexpectedMsg: // Received an unexpected_message alert. | |
176 case errSSLProtocol: | |
177 case errSSLRecordOverflow: | |
178 return ERR_SSL_PROTOCOL_ERROR; | |
179 case errSSLHostNameMismatch: | |
180 return ERR_CERT_COMMON_NAME_INVALID; | |
181 case errSSLCertExpired: | |
182 case errSSLCertNotYetValid: | |
183 return ERR_CERT_DATE_INVALID; | |
184 case errSSLNoRootCert: | |
185 case errSSLUnknownRootCert: | |
186 return ERR_CERT_AUTHORITY_INVALID; | |
187 case errSSLXCertChainInvalid: | |
188 case errSSLBadCert: | |
189 return ERR_CERT_INVALID; | |
190 | |
191 case errSSLClosedGraceful: | |
192 case noErr: | |
193 return OK; | |
194 | |
195 // (Note that all errSSLPeer* codes indicate errors reported by the peer, | |
196 // so the cert-related ones refer to my _client_ cert.) | |
197 // TODO(wtc): Add fine-grained error codes for client certificate errors | |
198 // reported by the server using the following SSL/TLS alert messages: | |
199 // access_denied | |
200 // bad_certificate | |
201 // unsupported_certificate | |
202 // certificate_expired | |
203 // certificate_revoked | |
204 // certificate_unknown | |
205 // unknown_ca | |
206 case errSSLPeerCertUnknown...errSSLPeerBadCert: | |
207 case errSSLPeerUnknownCA: | |
208 case errSSLPeerAccessDenied: | |
209 OSSTATUS_LOG(WARNING, status) << "Server rejected client cert"; | |
210 return ERR_BAD_SSL_CLIENT_AUTH_CERT; | |
211 | |
212 case errSSLNegotiation: | |
213 case errSSLPeerInsufficientSecurity: | |
214 case errSSLPeerProtocolVersion: | |
215 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; | |
216 | |
217 case errSSLBufferOverflow: | |
218 case errSSLModuleAttach: | |
219 case errSSLSessionNotFound: | |
220 default: | |
221 OSSTATUS_LOG(WARNING, status) | |
222 << "Unknown error mapped to net::ERR_FAILED"; | |
223 return ERR_FAILED; | |
224 } | |
225 } | |
226 | |
227 OSStatus OSStatusFromNetError(int net_error) { | |
228 switch (net_error) { | |
229 case ERR_IO_PENDING: | |
230 return errSSLWouldBlock; | |
231 case ERR_INTERNET_DISCONNECTED: | |
232 case ERR_TIMED_OUT: | |
233 case ERR_CONNECTION_ABORTED: | |
234 case ERR_CONNECTION_RESET: | |
235 case ERR_CONNECTION_REFUSED: | |
236 case ERR_ADDRESS_UNREACHABLE: | |
237 case ERR_ADDRESS_INVALID: | |
238 return errSSLClosedAbort; | |
239 case ERR_UNEXPECTED: | |
240 return errSSLInternal; | |
241 case ERR_INVALID_ARGUMENT: | |
242 return paramErr; | |
243 case OK: | |
244 return noErr; | |
245 default: | |
246 LOG(WARNING) << "Unknown error " << net_error << " mapped to paramErr"; | |
247 return paramErr; | |
248 } | |
249 } | |
250 | |
251 // Converts from a cipher suite to its key size. If the suite is marked with a | |
252 // **, it's not actually implemented in Secure Transport and won't be returned | |
253 // (but we'll code for it anyway). The reference here is | |
254 // http://www.opensource.apple.com/darwinsource/10.5.5/libsecurity_ssl-32463/lib
/cipherSpecs.c | |
255 // Seriously, though, there has to be an API for this, but I can't find one. | |
256 // Anybody? | |
257 int KeySizeOfCipherSuite(SSLCipherSuite suite) { | |
258 switch (suite) { | |
259 // SSL 2 only | |
260 | |
261 case SSL_RSA_WITH_DES_CBC_MD5: | |
262 return 56; | |
263 case SSL_RSA_WITH_3DES_EDE_CBC_MD5: | |
264 return 112; | |
265 case SSL_RSA_WITH_RC2_CBC_MD5: | |
266 case SSL_RSA_WITH_IDEA_CBC_MD5: // ** | |
267 return 128; | |
268 case SSL_NO_SUCH_CIPHERSUITE: // ** | |
269 return 0; | |
270 | |
271 // SSL 2, 3, TLS | |
272 | |
273 case SSL_NULL_WITH_NULL_NULL: | |
274 case SSL_RSA_WITH_NULL_MD5: | |
275 case SSL_RSA_WITH_NULL_SHA: // ** | |
276 case SSL_FORTEZZA_DMS_WITH_NULL_SHA: // ** | |
277 case TLS_ECDH_ECDSA_WITH_NULL_SHA: | |
278 case TLS_ECDHE_ECDSA_WITH_NULL_SHA: | |
279 case TLS_ECDH_RSA_WITH_NULL_SHA: | |
280 case TLS_ECDHE_RSA_WITH_NULL_SHA: | |
281 case TLS_ECDH_anon_WITH_NULL_SHA: | |
282 return 0; | |
283 case SSL_RSA_EXPORT_WITH_RC4_40_MD5: | |
284 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: | |
285 case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: | |
286 case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: // ** | |
287 case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: // ** | |
288 case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: | |
289 case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: | |
290 case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: | |
291 case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: | |
292 return 40; | |
293 case SSL_RSA_WITH_DES_CBC_SHA: | |
294 case SSL_DH_DSS_WITH_DES_CBC_SHA: // ** | |
295 case SSL_DH_RSA_WITH_DES_CBC_SHA: // ** | |
296 case SSL_DHE_DSS_WITH_DES_CBC_SHA: | |
297 case SSL_DHE_RSA_WITH_DES_CBC_SHA: | |
298 case SSL_DH_anon_WITH_DES_CBC_SHA: | |
299 return 56; | |
300 case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: // ** | |
301 return 80; | |
302 case SSL_RSA_WITH_3DES_EDE_CBC_SHA: | |
303 case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: // ** | |
304 case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: // ** | |
305 case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: | |
306 case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: | |
307 case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: | |
308 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: | |
309 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: | |
310 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: | |
311 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: | |
312 case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: | |
313 return 112; | |
314 case SSL_RSA_WITH_RC4_128_MD5: | |
315 case SSL_RSA_WITH_RC4_128_SHA: | |
316 case SSL_RSA_WITH_IDEA_CBC_SHA: // ** | |
317 case SSL_DH_anon_WITH_RC4_128_MD5: | |
318 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: | |
319 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: | |
320 case TLS_ECDH_RSA_WITH_RC4_128_SHA: | |
321 case TLS_ECDHE_RSA_WITH_RC4_128_SHA: | |
322 case TLS_ECDH_anon_WITH_RC4_128_SHA: | |
323 return 128; | |
324 | |
325 // TLS AES options (see RFC 3268 and RFC 4492) | |
326 | |
327 case TLS_RSA_WITH_AES_128_CBC_SHA: | |
328 case TLS_DH_DSS_WITH_AES_128_CBC_SHA: // ** | |
329 case TLS_DH_RSA_WITH_AES_128_CBC_SHA: // ** | |
330 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: | |
331 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: | |
332 case TLS_DH_anon_WITH_AES_128_CBC_SHA: | |
333 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: | |
334 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: | |
335 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: | |
336 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: | |
337 case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: | |
338 return 128; | |
339 case TLS_RSA_WITH_AES_256_CBC_SHA: | |
340 case TLS_DH_DSS_WITH_AES_256_CBC_SHA: // ** | |
341 case TLS_DH_RSA_WITH_AES_256_CBC_SHA: // ** | |
342 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: | |
343 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: | |
344 case TLS_DH_anon_WITH_AES_256_CBC_SHA: | |
345 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: | |
346 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: | |
347 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: | |
348 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: | |
349 case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: | |
350 return 256; | |
351 | |
352 default: | |
353 return -1; | |
354 } | |
355 } | |
356 | |
357 // Whitelist the cipher suites we want to enable. We disable the following | |
358 // cipher suites. | |
359 // - Null encryption cipher suites. | |
360 // - Weak cipher suites: < 80 bits of security strength. | |
361 // - FORTEZZA cipher suites (obsolete). | |
362 // - IDEA cipher suites (RFC 5469 explains why). | |
363 // - Anonymous cipher suites. | |
364 // | |
365 // Why don't we use a blacklist? A blacklist that isn't updated for a new | |
366 // Mac OS X release is a potential security issue because the new release | |
367 // may have new null encryption or anonymous cipher suites, whereas a | |
368 // whitelist that isn't updated for a new Mac OS X release just means we | |
369 // won't support any new cipher suites in that release. | |
370 bool ShouldEnableCipherSuite(SSLCipherSuite suite) { | |
371 switch (suite) { | |
372 case SSL_RSA_WITH_3DES_EDE_CBC_MD5: | |
373 case SSL_RSA_WITH_RC2_CBC_MD5: | |
374 | |
375 case SSL_RSA_WITH_3DES_EDE_CBC_SHA: | |
376 case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: // ** | |
377 case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: // ** | |
378 case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: | |
379 case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: | |
380 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: | |
381 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: | |
382 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: | |
383 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: | |
384 | |
385 case SSL_RSA_WITH_RC4_128_MD5: | |
386 case SSL_RSA_WITH_RC4_128_SHA: | |
387 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: | |
388 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: | |
389 case TLS_ECDH_RSA_WITH_RC4_128_SHA: | |
390 case TLS_ECDHE_RSA_WITH_RC4_128_SHA: | |
391 | |
392 case TLS_RSA_WITH_AES_128_CBC_SHA: | |
393 case TLS_DH_DSS_WITH_AES_128_CBC_SHA: // ** | |
394 case TLS_DH_RSA_WITH_AES_128_CBC_SHA: // ** | |
395 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: | |
396 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: | |
397 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: | |
398 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: | |
399 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: | |
400 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: | |
401 | |
402 case TLS_RSA_WITH_AES_256_CBC_SHA: | |
403 case TLS_DH_DSS_WITH_AES_256_CBC_SHA: // ** | |
404 case TLS_DH_RSA_WITH_AES_256_CBC_SHA: // ** | |
405 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: | |
406 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: | |
407 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: | |
408 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: | |
409 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: | |
410 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: | |
411 return true; | |
412 | |
413 default: | |
414 return false; | |
415 } | |
416 } | |
417 | |
418 // Returns the server's certificate. The caller must release a reference | |
419 // to the return value when done. Returns NULL on failure. | |
420 X509Certificate* GetServerCert(SSLContextRef ssl_context) { | |
421 CFArrayRef certs; | |
422 OSStatus status = SSLCopyPeerCertificates(ssl_context, &certs); | |
423 // SSLCopyPeerCertificates may succeed but return a null |certs| | |
424 // (if we're using an anonymous cipher suite or if we call it | |
425 // before the certificate message has arrived and been parsed). | |
426 if (status != noErr || !certs) | |
427 return NULL; | |
428 base::mac::ScopedCFTypeRef<CFArrayRef> scoped_certs(certs); | |
429 | |
430 DCHECK_GT(CFArrayGetCount(certs), 0); | |
431 | |
432 // Add each of the intermediate certificates in the server's chain to the | |
433 // server's X509Certificate object. This makes them available to | |
434 // X509Certificate::Verify() for chain building. | |
435 std::vector<SecCertificateRef> intermediate_ca_certs; | |
436 CFIndex certs_length = CFArrayGetCount(certs); | |
437 for (CFIndex i = 1; i < certs_length; ++i) { | |
438 SecCertificateRef cert_ref = reinterpret_cast<SecCertificateRef>( | |
439 const_cast<void*>(CFArrayGetValueAtIndex(certs, i))); | |
440 intermediate_ca_certs.push_back(cert_ref); | |
441 } | |
442 | |
443 SecCertificateRef server_cert = static_cast<SecCertificateRef>( | |
444 const_cast<void*>(CFArrayGetValueAtIndex(certs, 0))); | |
445 return X509Certificate::CreateFromHandle(server_cert, | |
446 intermediate_ca_certs); | |
447 } | |
448 | |
449 // Dynamically look up a pointer to a function exported by a bundle. | |
450 template <typename FNTYPE> | |
451 FNTYPE LookupFunction(CFStringRef bundleName, CFStringRef fnName) { | |
452 CFBundleRef bundle = CFBundleGetBundleWithIdentifier(bundleName); | |
453 if (!bundle) | |
454 return NULL; | |
455 return reinterpret_cast<FNTYPE>( | |
456 CFBundleGetFunctionPointerForName(bundle, fnName)); | |
457 } | |
458 | |
459 struct CipherSuiteIsDisabledFunctor { | |
460 explicit CipherSuiteIsDisabledFunctor( | |
461 const std::vector<uint16>& disabled_cipher_suites) | |
462 : disabled_cipher_suites_(disabled_cipher_suites) {} | |
463 | |
464 // Returns true if the given |cipher_suite| appears within the set of | |
465 // |disabled_cipher_suites|. | |
466 bool operator()(SSLCipherSuite cipher_suite) const { | |
467 return binary_search(disabled_cipher_suites_.begin(), | |
468 disabled_cipher_suites_.end(), | |
469 static_cast<uint16>(cipher_suite)); | |
470 } | |
471 | |
472 const std::vector<uint16>& disabled_cipher_suites_; | |
473 }; | |
474 | |
475 // Class to determine what cipher suites are available and which cipher | |
476 // suites should be enabled, based on the overall security policy. | |
477 class EnabledCipherSuites { | |
478 public: | |
479 const std::vector<SSLCipherSuite>& ciphers() const { return ciphers_; } | |
480 | |
481 private: | |
482 friend struct base::DefaultLazyInstanceTraits<EnabledCipherSuites>; | |
483 EnabledCipherSuites(); | |
484 ~EnabledCipherSuites() {} | |
485 | |
486 std::vector<SSLCipherSuite> ciphers_; | |
487 | |
488 DISALLOW_COPY_AND_ASSIGN(EnabledCipherSuites); | |
489 }; | |
490 | |
491 static base::LazyInstance<EnabledCipherSuites> g_enabled_cipher_suites = | |
492 LAZY_INSTANCE_INITIALIZER; | |
493 | |
494 EnabledCipherSuites::EnabledCipherSuites() { | |
495 SSLContextRef ssl_context; | |
496 OSStatus status = SSLNewContext(false, &ssl_context); | |
497 if (status != noErr) | |
498 return; | |
499 | |
500 size_t num_supported_ciphers; | |
501 status = SSLGetNumberSupportedCiphers(ssl_context, &num_supported_ciphers); | |
502 if (status != noErr) { | |
503 SSLDisposeContext(ssl_context); | |
504 return; | |
505 } | |
506 DCHECK_NE(num_supported_ciphers, 0U); | |
507 | |
508 std::vector<SSLCipherSuite> supported_ciphers(num_supported_ciphers); | |
509 status = SSLGetSupportedCiphers(ssl_context, &supported_ciphers[0], | |
510 &num_supported_ciphers); | |
511 SSLDisposeContext(ssl_context); | |
512 if (status != noErr) | |
513 return; | |
514 | |
515 for (size_t i = 0; i < num_supported_ciphers; ++i) { | |
516 if (ShouldEnableCipherSuite(supported_ciphers[i])) | |
517 ciphers_.push_back(supported_ciphers[i]); | |
518 } | |
519 } | |
520 | |
521 } // namespace | |
522 | |
523 //----------------------------------------------------------------------------- | |
524 | |
525 SSLClientSocketMac::SSLClientSocketMac(ClientSocketHandle* transport_socket, | |
526 const HostPortPair& host_and_port, | |
527 const SSLConfig& ssl_config, | |
528 const SSLClientSocketContext& context) | |
529 : transport_(transport_socket), | |
530 host_and_port_(host_and_port), | |
531 ssl_config_(ssl_config), | |
532 user_read_buf_len_(0), | |
533 user_write_buf_len_(0), | |
534 next_handshake_state_(STATE_NONE), | |
535 cert_verifier_(context.cert_verifier), | |
536 renegotiating_(false), | |
537 client_cert_requested_(false), | |
538 ssl_context_(NULL), | |
539 bytes_read_after_renegotiation_(0), | |
540 pending_send_error_(OK), | |
541 net_log_(transport_socket->socket()->NetLog()) { | |
542 // Sort the list of ciphers to disable, since disabling ciphers on Mac | |
543 // requires subtracting from a list of enabled ciphers while maintaining | |
544 // ordering, as opposed to merely needing to iterate them as with NSS. | |
545 sort(ssl_config_.disabled_cipher_suites.begin(), | |
546 ssl_config_.disabled_cipher_suites.end()); | |
547 } | |
548 | |
549 SSLClientSocketMac::~SSLClientSocketMac() { | |
550 Disconnect(); | |
551 } | |
552 | |
553 int SSLClientSocketMac::Connect(const CompletionCallback& callback) { | |
554 DCHECK(transport_.get()); | |
555 DCHECK(next_handshake_state_ == STATE_NONE); | |
556 DCHECK(user_connect_callback_.is_null()); | |
557 | |
558 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT); | |
559 | |
560 int rv = InitializeSSLContext(); | |
561 if (rv != OK) { | |
562 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | |
563 return rv; | |
564 } | |
565 | |
566 next_handshake_state_ = STATE_HANDSHAKE; | |
567 rv = DoHandshakeLoop(OK); | |
568 if (rv == ERR_IO_PENDING) { | |
569 user_connect_callback_ = callback; | |
570 } else { | |
571 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | |
572 } | |
573 return rv; | |
574 } | |
575 | |
576 void SSLClientSocketMac::Disconnect() { | |
577 next_handshake_state_ = STATE_NONE; | |
578 | |
579 if (ssl_context_) { | |
580 SSLClose(ssl_context_); | |
581 SSLDisposeContext(ssl_context_); | |
582 ssl_context_ = NULL; | |
583 VLOG(1) << "----- Disposed SSLContext"; | |
584 } | |
585 | |
586 // Shut down anything that may call us back. | |
587 verifier_.reset(); | |
588 transport_->socket()->Disconnect(); | |
589 } | |
590 | |
591 bool SSLClientSocketMac::IsConnected() const { | |
592 // Ideally, we should also check if we have received the close_notify alert | |
593 // message from the server, and return false in that case. We're not doing | |
594 // that, so this function may return a false positive. Since the upper | |
595 // layer (HttpNetworkTransaction) needs to handle a persistent connection | |
596 // closed by the server when we send a request anyway, a false positive in | |
597 // exchange for simpler code is a good trade-off. | |
598 return completed_handshake() && transport_->socket()->IsConnected(); | |
599 } | |
600 | |
601 bool SSLClientSocketMac::IsConnectedAndIdle() const { | |
602 // Unlike IsConnected, this method doesn't return a false positive. | |
603 // | |
604 // Strictly speaking, we should check if we have received the close_notify | |
605 // alert message from the server, and return false in that case. Although | |
606 // the close_notify alert message means EOF in the SSL layer, it is just | |
607 // bytes to the transport layer below, so | |
608 // transport_->socket()->IsConnectedAndIdle() returns the desired false | |
609 // when we receive close_notify. | |
610 return completed_handshake() && transport_->socket()->IsConnectedAndIdle(); | |
611 } | |
612 | |
613 int SSLClientSocketMac::GetPeerAddress(IPEndPoint* address) const { | |
614 return transport_->socket()->GetPeerAddress(address); | |
615 } | |
616 | |
617 int SSLClientSocketMac::GetLocalAddress(IPEndPoint* address) const { | |
618 return transport_->socket()->GetLocalAddress(address); | |
619 } | |
620 | |
621 const BoundNetLog& SSLClientSocketMac::NetLog() const { | |
622 return net_log_; | |
623 } | |
624 | |
625 void SSLClientSocketMac::SetSubresourceSpeculation() { | |
626 if (transport_.get() && transport_->socket()) { | |
627 transport_->socket()->SetSubresourceSpeculation(); | |
628 } else { | |
629 NOTREACHED(); | |
630 } | |
631 } | |
632 | |
633 void SSLClientSocketMac::SetOmniboxSpeculation() { | |
634 if (transport_.get() && transport_->socket()) { | |
635 transport_->socket()->SetOmniboxSpeculation(); | |
636 } else { | |
637 NOTREACHED(); | |
638 } | |
639 } | |
640 | |
641 bool SSLClientSocketMac::WasEverUsed() const { | |
642 if (transport_.get() && transport_->socket()) { | |
643 return transport_->socket()->WasEverUsed(); | |
644 } | |
645 NOTREACHED(); | |
646 return false; | |
647 } | |
648 | |
649 bool SSLClientSocketMac::UsingTCPFastOpen() const { | |
650 if (transport_.get() && transport_->socket()) { | |
651 return transport_->socket()->UsingTCPFastOpen(); | |
652 } | |
653 NOTREACHED(); | |
654 return false; | |
655 } | |
656 | |
657 int64 SSLClientSocketMac::NumBytesRead() const { | |
658 if (transport_.get() && transport_->socket()) { | |
659 return transport_->socket()->NumBytesRead(); | |
660 } | |
661 NOTREACHED(); | |
662 return -1; | |
663 } | |
664 | |
665 base::TimeDelta SSLClientSocketMac::GetConnectTimeMicros() const { | |
666 if (transport_.get() && transport_->socket()) { | |
667 return transport_->socket()->GetConnectTimeMicros(); | |
668 } | |
669 NOTREACHED(); | |
670 return base::TimeDelta::FromMicroseconds(-1); | |
671 } | |
672 | |
673 int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len, | |
674 const CompletionCallback& callback) { | |
675 DCHECK(completed_handshake()); | |
676 DCHECK(user_read_callback_.is_null()); | |
677 DCHECK(!user_read_buf_); | |
678 | |
679 user_read_buf_ = buf; | |
680 user_read_buf_len_ = buf_len; | |
681 | |
682 int rv = DoPayloadRead(); | |
683 if (rv == ERR_IO_PENDING) { | |
684 user_read_callback_ = callback; | |
685 } else { | |
686 user_read_buf_ = NULL; | |
687 user_read_buf_len_ = 0; | |
688 } | |
689 return rv; | |
690 } | |
691 | |
692 int SSLClientSocketMac::Write(IOBuffer* buf, int buf_len, | |
693 const CompletionCallback& callback) { | |
694 DCHECK(completed_handshake()); | |
695 DCHECK(user_write_callback_.is_null()); | |
696 DCHECK(!user_write_buf_); | |
697 | |
698 user_write_buf_ = buf; | |
699 user_write_buf_len_ = buf_len; | |
700 | |
701 int rv = DoPayloadWrite(); | |
702 if (rv == ERR_IO_PENDING) { | |
703 user_write_callback_ = callback; | |
704 } else { | |
705 user_write_buf_ = NULL; | |
706 user_write_buf_len_ = 0; | |
707 } | |
708 return rv; | |
709 } | |
710 | |
711 bool SSLClientSocketMac::SetReceiveBufferSize(int32 size) { | |
712 return transport_->socket()->SetReceiveBufferSize(size); | |
713 } | |
714 | |
715 bool SSLClientSocketMac::SetSendBufferSize(int32 size) { | |
716 return transport_->socket()->SetSendBufferSize(size); | |
717 } | |
718 | |
719 bool SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) { | |
720 ssl_info->Reset(); | |
721 if (!server_cert_) | |
722 return false; | |
723 | |
724 ssl_info->cert = server_cert_verify_result_.verified_cert; | |
725 ssl_info->cert_status = server_cert_verify_result_.cert_status; | |
726 ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes; | |
727 ssl_info->is_issued_by_known_root = | |
728 server_cert_verify_result_.is_issued_by_known_root; | |
729 ssl_info->client_cert_sent = | |
730 ssl_config_.send_client_cert && ssl_config_.client_cert; | |
731 ssl_info->channel_id_sent = WasChannelIDSent(); | |
732 | |
733 // security info | |
734 SSLCipherSuite suite; | |
735 OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite); | |
736 if (!status) { | |
737 ssl_info->security_bits = KeySizeOfCipherSuite(suite); | |
738 ssl_info->connection_status |= | |
739 (suite & SSL_CONNECTION_CIPHERSUITE_MASK) << | |
740 SSL_CONNECTION_CIPHERSUITE_SHIFT; | |
741 } | |
742 | |
743 if (ssl_config_.version_fallback) | |
744 ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK; | |
745 | |
746 return true; | |
747 } | |
748 | |
749 void SSLClientSocketMac::GetSSLCertRequestInfo( | |
750 SSLCertRequestInfo* cert_request_info) { | |
751 cert_request_info->host_and_port = host_and_port_.ToString(); | |
752 cert_request_info->cert_authorities.clear(); | |
753 cert_request_info->cert_key_types.clear(); | |
754 cert_request_info->client_certs.clear(); | |
755 | |
756 // Retrieve the cert issuers accepted by the server. This information is | |
757 // currently (temporarily) being saved both in |valid_issuers| and | |
758 // |cert_authorities|, the latter being the target solution. The refactoring | |
759 // effort is being tracked in http://crbug.com/166642. | |
760 std::vector<CertPrincipal> valid_issuers; | |
761 CFArrayRef valid_issuer_names = NULL; | |
762 if (SSLCopyDistinguishedNames(ssl_context_, &valid_issuer_names) == noErr && | |
763 valid_issuer_names != NULL) { | |
764 VLOG(1) << "Server has " << CFArrayGetCount(valid_issuer_names) | |
765 << " valid issuer names"; | |
766 int n = CFArrayGetCount(valid_issuer_names); | |
767 for (int i = 0; i < n; i++) { | |
768 CFDataRef issuer = reinterpret_cast<CFDataRef>( | |
769 CFArrayGetValueAtIndex(valid_issuer_names, i)); | |
770 // Add the DER-encoded issuer DistinguishedName to |cert_authorities|. | |
771 cert_request_info->cert_authorities.push_back(std::string( | |
772 reinterpret_cast<const char*>(CFDataGetBytePtr(issuer)), | |
773 static_cast<size_t>(CFDataGetLength(issuer)))); | |
774 // Add the CertPrincipal object representing the issuer to | |
775 // |valid_issuers|. | |
776 CertPrincipal p; | |
777 if (p.ParseDistinguishedName(CFDataGetBytePtr(issuer), | |
778 CFDataGetLength(issuer))) { | |
779 valid_issuers.push_back(p); | |
780 } | |
781 } | |
782 CFRelease(valid_issuer_names); | |
783 } | |
784 | |
785 // Now get the available client certs whose issuers are allowed by the server. | |
786 // TODO(rch): we should consider passing a host-port pair as the first | |
787 // argument to X509Certificate::GetSSLClientCertificates. | |
788 X509Certificate::GetSSLClientCertificates(host_and_port_.host(), | |
789 valid_issuers, | |
790 &cert_request_info->client_certs); | |
791 std::sort(cert_request_info->client_certs.begin(), | |
792 cert_request_info->client_certs.end(), | |
793 x509_util::ClientCertSorter()); | |
794 | |
795 VLOG(1) << "Asking user to choose between " | |
796 << cert_request_info->client_certs.size() << " client certs..."; | |
797 } | |
798 | |
799 int SSLClientSocketMac::ExportKeyingMaterial(const base::StringPiece& label, | |
800 bool has_context, | |
801 const base::StringPiece& context, | |
802 unsigned char* out, | |
803 unsigned int outlen) { | |
804 return ERR_NOT_IMPLEMENTED; | |
805 } | |
806 | |
807 int SSLClientSocketMac::GetTLSUniqueChannelBinding(std::string* out) { | |
808 return ERR_NOT_IMPLEMENTED; | |
809 } | |
810 | |
811 SSLClientSocket::NextProtoStatus | |
812 SSLClientSocketMac::GetNextProto(std::string* proto, | |
813 std::string* server_protos) { | |
814 proto->clear(); | |
815 server_protos->clear(); | |
816 return kNextProtoUnsupported; | |
817 } | |
818 | |
819 ServerBoundCertService* SSLClientSocketMac::GetServerBoundCertService() const { | |
820 return NULL; | |
821 } | |
822 | |
823 int SSLClientSocketMac::InitializeSSLContext() { | |
824 VLOG(1) << "----- InitializeSSLContext"; | |
825 OSStatus status = noErr; | |
826 | |
827 status = SSLNewContext(false, &ssl_context_); | |
828 if (status) | |
829 return NetErrorFromOSStatus(status); | |
830 | |
831 status = SSLSetProtocolVersionEnabled(ssl_context_, | |
832 kSSLProtocol2, | |
833 false); | |
834 if (status) | |
835 return NetErrorFromOSStatus(status); | |
836 | |
837 // If ssl_config_.version_max > SSL_PROTOCOL_VERSION_TLS1, it means the | |
838 // SSLConfigService::SetDefaultVersionMax(SSL_PROTOCOL_VERSION_TLS1) call | |
839 // in ClientSocketFactory::UseSystemSSL() is not effective. | |
840 DCHECK_LE(ssl_config_.version_max, SSL_PROTOCOL_VERSION_TLS1); | |
841 | |
842 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); | |
843 status = SSLSetProtocolVersionEnabled(ssl_context_, | |
844 kSSLProtocol3, | |
845 ssl3_enabled); | |
846 if (status) | |
847 return NetErrorFromOSStatus(status); | |
848 | |
849 bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 && | |
850 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1); | |
851 status = SSLSetProtocolVersionEnabled(ssl_context_, | |
852 kTLSProtocol1, | |
853 tls1_enabled); | |
854 if (status) | |
855 return NetErrorFromOSStatus(status); | |
856 | |
857 std::vector<SSLCipherSuite> enabled_ciphers = | |
858 g_enabled_cipher_suites.Get().ciphers(); | |
859 | |
860 CipherSuiteIsDisabledFunctor is_disabled_cipher( | |
861 ssl_config_.disabled_cipher_suites); | |
862 std::vector<SSLCipherSuite>::iterator new_end = | |
863 std::remove_if(enabled_ciphers.begin(), enabled_ciphers.end(), | |
864 is_disabled_cipher); | |
865 if (new_end != enabled_ciphers.end()) | |
866 enabled_ciphers.erase(new_end, enabled_ciphers.end()); | |
867 | |
868 status = SSLSetEnabledCiphers( | |
869 ssl_context_, | |
870 enabled_ciphers.empty() ? NULL : &enabled_ciphers[0], | |
871 enabled_ciphers.size()); | |
872 | |
873 if (status) | |
874 return NetErrorFromOSStatus(status); | |
875 | |
876 status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); | |
877 if (status) | |
878 return NetErrorFromOSStatus(status); | |
879 | |
880 status = SSLSetConnection(ssl_context_, this); | |
881 if (status) | |
882 return NetErrorFromOSStatus(status); | |
883 | |
884 // Passing the domain name enables the server_name TLS extension (SNI). | |
885 status = SSLSetPeerDomainName(ssl_context_, | |
886 host_and_port_.host().data(), | |
887 host_and_port_.host().length()); | |
888 if (status) | |
889 return NetErrorFromOSStatus(status); | |
890 | |
891 // Disable certificate verification within Secure Transport; we'll | |
892 // be handling that ourselves. | |
893 status = SSLSetEnableCertVerify(ssl_context_, false); | |
894 if (status) | |
895 return NetErrorFromOSStatus(status); | |
896 | |
897 if (ssl_config_.send_client_cert) { | |
898 status = SetClientCert(); | |
899 if (status) | |
900 return NetErrorFromOSStatus(status); | |
901 return OK; | |
902 } | |
903 | |
904 // Concatenate the hostname and peer address to use as the peer ID. To | |
905 // resume a session, we must connect to the same server on the same port | |
906 // using the same hostname (i.e., localhost and 127.0.0.1 are considered | |
907 // different peers, which puts us through certificate validation again | |
908 // and catches hostname/certificate name mismatches. | |
909 IPEndPoint endpoint; | |
910 int rv = transport_->socket()->GetPeerAddress(&endpoint); | |
911 if (rv != OK) | |
912 return rv; | |
913 std::string peer_id(host_and_port_.ToString()); | |
914 peer_id += std::string(reinterpret_cast<const char*>(&endpoint.address()[0]), | |
915 endpoint.address().size()); | |
916 // SSLSetPeerID() treats peer_id as a binary blob, and makes its | |
917 // own copy. | |
918 status = SSLSetPeerID(ssl_context_, peer_id.data(), peer_id.length()); | |
919 if (status) | |
920 return NetErrorFromOSStatus(status); | |
921 | |
922 return OK; | |
923 } | |
924 | |
925 void SSLClientSocketMac::DoConnectCallback(int rv) { | |
926 DCHECK(rv != ERR_IO_PENDING); | |
927 DCHECK(!user_connect_callback_.is_null()); | |
928 | |
929 CompletionCallback c = user_connect_callback_; | |
930 user_connect_callback_.Reset(); | |
931 c.Run(rv > OK ? OK : rv); | |
932 } | |
933 | |
934 void SSLClientSocketMac::DoReadCallback(int rv) { | |
935 DCHECK(rv != ERR_IO_PENDING); | |
936 DCHECK(!user_read_callback_.is_null()); | |
937 | |
938 // Since Run may result in Read being called, clear user_read_callback_ up | |
939 // front. | |
940 CompletionCallback c = user_read_callback_; | |
941 user_read_callback_.Reset(); | |
942 user_read_buf_ = NULL; | |
943 user_read_buf_len_ = 0; | |
944 c.Run(rv); | |
945 } | |
946 | |
947 void SSLClientSocketMac::DoWriteCallback(int rv) { | |
948 DCHECK(rv != ERR_IO_PENDING); | |
949 DCHECK(!user_write_callback_.is_null()); | |
950 | |
951 // Since Run may result in Write being called, clear user_write_callback_ up | |
952 // front. | |
953 CompletionCallback c = user_write_callback_; | |
954 user_write_callback_.Reset(); | |
955 user_write_buf_ = NULL; | |
956 user_write_buf_len_ = 0; | |
957 c.Run(rv); | |
958 } | |
959 | |
960 void SSLClientSocketMac::OnHandshakeIOComplete(int result) { | |
961 int rv = DoHandshakeLoop(result); | |
962 if (rv != ERR_IO_PENDING) { | |
963 // If there is no connect callback available to call, we are | |
964 // renegotiating (which occurs because we are in the middle of a Read | |
965 // when the renegotiation process starts). So we complete the Read | |
966 // here. | |
967 if (user_connect_callback_.is_null()) { | |
968 DoReadCallback(rv); | |
969 return; | |
970 } | |
971 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | |
972 DoConnectCallback(rv); | |
973 } | |
974 } | |
975 | |
976 void SSLClientSocketMac::OnTransportReadComplete(int result) { | |
977 if (result > 0) { | |
978 recv_buffer_.insert(recv_buffer_.end(), | |
979 read_io_buf_->data(), | |
980 read_io_buf_->data() + result); | |
981 } | |
982 read_io_buf_ = NULL; | |
983 | |
984 if (!completed_handshake()) { | |
985 OnHandshakeIOComplete(result); | |
986 return; | |
987 } | |
988 | |
989 if (user_read_buf_) { | |
990 if (result < 0) { | |
991 DoReadCallback(result); | |
992 return; | |
993 } | |
994 int rv = DoPayloadRead(); | |
995 if (rv != ERR_IO_PENDING) | |
996 DoReadCallback(rv); | |
997 } | |
998 } | |
999 | |
1000 void SSLClientSocketMac::OnTransportWriteComplete(int result) { | |
1001 write_io_buf_ = NULL; | |
1002 | |
1003 if (result < 0) { | |
1004 pending_send_error_ = result; | |
1005 return; | |
1006 } | |
1007 | |
1008 send_buffer_.erase(send_buffer_.begin(), | |
1009 send_buffer_.begin() + result); | |
1010 if (!send_buffer_.empty()) | |
1011 SSLWriteCallback(this, NULL, NULL); | |
1012 | |
1013 if (!completed_handshake()) { | |
1014 OnHandshakeIOComplete(result); | |
1015 return; | |
1016 } | |
1017 | |
1018 // If paused because too much data is in flight, try writing again and make | |
1019 // the promised callback. | |
1020 if (user_write_buf_ && send_buffer_.size() < kWriteSizeResumeLimit) { | |
1021 int rv = DoPayloadWrite(); | |
1022 if (rv != ERR_IO_PENDING) | |
1023 DoWriteCallback(rv); | |
1024 } | |
1025 } | |
1026 | |
1027 int SSLClientSocketMac::DoHandshakeLoop(int last_io_result) { | |
1028 DCHECK(next_handshake_state_ != STATE_NONE); | |
1029 int rv = last_io_result; | |
1030 do { | |
1031 State state = next_handshake_state_; | |
1032 next_handshake_state_ = STATE_NONE; | |
1033 switch (state) { | |
1034 case STATE_HANDSHAKE: | |
1035 // Do the SSL/TLS handshake. | |
1036 rv = DoHandshake(); | |
1037 break; | |
1038 case STATE_VERIFY_CERT: | |
1039 // Kick off server certificate validation. | |
1040 rv = DoVerifyCert(); | |
1041 break; | |
1042 case STATE_VERIFY_CERT_COMPLETE: | |
1043 // Check the results of the server certificate validation. | |
1044 rv = DoVerifyCertComplete(rv); | |
1045 break; | |
1046 case STATE_COMPLETED_RENEGOTIATION: | |
1047 // The renegotiation handshake has completed, and the Read() call | |
1048 // that was interrupted by the renegotiation needs to be resumed in | |
1049 // order to to satisfy the original caller's request. | |
1050 rv = DoCompletedRenegotiation(rv); | |
1051 break; | |
1052 case STATE_COMPLETED_HANDSHAKE: | |
1053 next_handshake_state_ = STATE_COMPLETED_HANDSHAKE; | |
1054 // This is the end of our state machine, so return. | |
1055 return rv; | |
1056 default: | |
1057 rv = ERR_UNEXPECTED; | |
1058 NOTREACHED() << "unexpected state"; | |
1059 break; | |
1060 } | |
1061 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); | |
1062 return rv; | |
1063 } | |
1064 | |
1065 int SSLClientSocketMac::DoHandshake() { | |
1066 client_cert_requested_ = false; | |
1067 | |
1068 OSStatus status; | |
1069 if (!renegotiating_) { | |
1070 status = SSLHandshake(ssl_context_); | |
1071 } else { | |
1072 // Renegotiation can only be detected by a call to DoPayloadRead(), | |
1073 // which means |user_read_buf_| should be valid. | |
1074 DCHECK(user_read_buf_); | |
1075 | |
1076 // On OS X 10.5.x, SSLSetSessionOption with | |
1077 // kSSLSessionOptionBreakOnServerAuth is broken for renegotiation, as | |
1078 // SSLRead() does not internally handle errSSLServerAuthCompleted being | |
1079 // returned during handshake. In order to support certificate validation | |
1080 // after a renegotiation, SSLRead() sets |renegotiating_| to be true and | |
1081 // returns errSSLWouldBlock when it detects an attempt to read the | |
1082 // ServerHello after responding to a HelloRequest. It would be | |
1083 // appropriate to call SSLHandshake() at this point to restart the | |
1084 // handshake state machine, however, on 10.5.x, SSLHandshake() is buggy | |
1085 // and will always return noErr (indicating handshake completion), | |
1086 // without doing any actual work. Because of this, the only way to | |
1087 // advance SecureTransport's internal handshake state machine is to | |
1088 // continuously call SSLRead() until the handshake is marked complete. | |
1089 // Once the handshake is completed, if it completed successfully, the | |
1090 // user read callback is invoked with |bytes_read_after_renegotiation_| | |
1091 // as the callback result. On 10.6.0+, both errSSLServerAuthCompleted | |
1092 // and SSLHandshake() work as expected, so this strange workaround is | |
1093 // only necessary while OS X 10.5.x is still supported. | |
1094 bytes_read_after_renegotiation_ = 0; | |
1095 status = SSLRead(ssl_context_, user_read_buf_->data(), | |
1096 user_read_buf_len_, &bytes_read_after_renegotiation_); | |
1097 if (bytes_read_after_renegotiation_ > 0) { | |
1098 // With SecureTransport, as of 10.6.5, if application data is read, | |
1099 // then the handshake should be completed. This is because | |
1100 // SecureTransport does not (yet) support exchanging application data | |
1101 // in the midst of handshakes. This is permitted in the TLS | |
1102 // specification, as peers may exchange messages using the previous | |
1103 // cipher spec up until they exchange ChangeCipherSpec messages. | |
1104 // However, in addition to SecureTransport not supporting this, we do | |
1105 // not permit callers to enter Read() or Write() when a handshake is | |
1106 // occurring, in part due to the deception that happens in | |
1107 // SSLWriteCallback(). Thus we need to make sure the handshake is | |
1108 // truly completed before processing application data, and if any was | |
1109 // read before the handshake is completed, it will be dropped and the | |
1110 // connection aborted. | |
1111 SSLSessionState session_state = kSSLIdle; | |
1112 status = SSLGetSessionState(ssl_context_, &session_state); | |
1113 if (session_state != kSSLConnected) | |
1114 status = errSSLProtocol; | |
1115 } | |
1116 } | |
1117 | |
1118 SSLClientCertificateState client_cert_state; | |
1119 if (SSLGetClientCertificateState(ssl_context_, &client_cert_state) != noErr) | |
1120 client_cert_state = kSSLClientCertNone; | |
1121 if (client_cert_state > kSSLClientCertNone) | |
1122 client_cert_requested_ = true; | |
1123 | |
1124 int net_error = ERR_FAILED; | |
1125 switch (status) { | |
1126 case noErr: | |
1127 return DidCompleteHandshake(); | |
1128 case errSSLWouldBlock: | |
1129 next_handshake_state_ = STATE_HANDSHAKE; | |
1130 return ERR_IO_PENDING; | |
1131 case errSSLClosedGraceful: | |
1132 // The server unexpectedly closed on us. | |
1133 net_error = ERR_SSL_PROTOCOL_ERROR; | |
1134 break; | |
1135 case errSSLClosedAbort: | |
1136 case errSSLPeerHandshakeFail: | |
1137 if (client_cert_requested_) { | |
1138 if (!ssl_config_.send_client_cert) { | |
1139 // The server aborted, likely due to requiring a client certificate | |
1140 // and one wasn't sent. | |
1141 VLOG(1) << "Server requested SSL cert during handshake"; | |
1142 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | |
1143 } else { | |
1144 // The server aborted, likely due to not liking the client | |
1145 // certificate that was sent. | |
1146 LOG(WARNING) << "Server aborted SSL handshake"; | |
1147 net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT; | |
1148 } | |
1149 // Don't fall through - the error was intentionally remapped. | |
1150 break; | |
1151 } | |
1152 // Fall through if a client cert wasn't requested. | |
1153 default: | |
1154 net_error = NetErrorFromOSStatus(status); | |
1155 DCHECK(!IsCertificateError(net_error)); | |
1156 if (!ssl_config_.send_client_cert && | |
1157 (client_cert_state == kSSLClientCertRejected || | |
1158 net_error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) { | |
1159 // The server unexpectedly sent a peer certificate error alert when no | |
1160 // certificate had been sent. | |
1161 net_error = ERR_SSL_PROTOCOL_ERROR; | |
1162 } | |
1163 break; | |
1164 } | |
1165 | |
1166 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, | |
1167 CreateNetLogSSLErrorCallback(net_error, status)); | |
1168 return net_error; | |
1169 } | |
1170 | |
1171 int SSLClientSocketMac::DoVerifyCert() { | |
1172 next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE; | |
1173 | |
1174 DCHECK(server_cert_); | |
1175 | |
1176 VLOG(1) << "DoVerifyCert..."; | |
1177 CertStatus cert_status; | |
1178 if (ssl_config_.IsAllowedBadCert(server_cert_, &cert_status)) { | |
1179 VLOG(1) << "Received an expected bad cert with status: " << cert_status; | |
1180 server_cert_verify_result_.Reset(); | |
1181 server_cert_verify_result_.cert_status = cert_status; | |
1182 server_cert_verify_result_.verified_cert = server_cert_; | |
1183 return OK; | |
1184 } | |
1185 | |
1186 int flags = 0; | |
1187 if (ssl_config_.rev_checking_enabled) | |
1188 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED; | |
1189 if (ssl_config_.verify_ev_cert) | |
1190 flags |= CertVerifier::VERIFY_EV_CERT; | |
1191 if (ssl_config_.cert_io_enabled) | |
1192 flags |= CertVerifier::VERIFY_CERT_IO_ENABLED; | |
1193 verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); | |
1194 return verifier_->Verify( | |
1195 server_cert_, host_and_port_.host(), flags, | |
1196 NULL /* no CRL set */, | |
1197 &server_cert_verify_result_, | |
1198 base::Bind(&SSLClientSocketMac::OnHandshakeIOComplete, | |
1199 base::Unretained(this)), | |
1200 net_log_); | |
1201 } | |
1202 | |
1203 int SSLClientSocketMac::DoVerifyCertComplete(int result) { | |
1204 DCHECK(verifier_.get()); | |
1205 verifier_.reset(); | |
1206 | |
1207 VLOG(1) << "...DoVerifyCertComplete (result=" << result << ")"; | |
1208 if (result == OK && client_cert_requested_ && | |
1209 !ssl_config_.send_client_cert) { | |
1210 // Caller hasn't specified a client cert, so let it know the server is | |
1211 // asking for one, and abort the connection. | |
1212 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | |
1213 } | |
1214 VLOG(1) << "Handshake finished! (DoVerifyCertComplete)"; | |
1215 | |
1216 if (renegotiating_) { | |
1217 DidCompleteRenegotiation(); | |
1218 return result; | |
1219 } | |
1220 | |
1221 // The initial handshake has completed. | |
1222 next_handshake_state_ = STATE_COMPLETED_HANDSHAKE; | |
1223 | |
1224 return result; | |
1225 } | |
1226 | |
1227 int SSLClientSocketMac::SetClientCert() { | |
1228 if (!ssl_config_.send_client_cert || !ssl_config_.client_cert) | |
1229 return noErr; | |
1230 | |
1231 base::mac::ScopedCFTypeRef<CFArrayRef> cert_refs( | |
1232 ssl_config_.client_cert->CreateClientCertificateChain()); | |
1233 VLOG(1) << "SSLSetCertificate(" << CFArrayGetCount(cert_refs) << " certs)"; | |
1234 OSStatus result = SSLSetCertificate(ssl_context_, cert_refs); | |
1235 if (result) | |
1236 OSSTATUS_LOG(ERROR, result) << "SSLSetCertificate failed"; | |
1237 return result; | |
1238 } | |
1239 | |
1240 int SSLClientSocketMac::DoPayloadRead() { | |
1241 size_t processed = 0; | |
1242 OSStatus status = SSLRead(ssl_context_, user_read_buf_->data(), | |
1243 user_read_buf_len_, &processed); | |
1244 if (status == errSSLWouldBlock && renegotiating_) { | |
1245 CHECK_EQ(static_cast<size_t>(0), processed); | |
1246 next_handshake_state_ = STATE_HANDSHAKE; | |
1247 return DoHandshakeLoop(OK); | |
1248 } | |
1249 // There's a subtle difference here in semantics of the "would block" errors. | |
1250 // In our code, ERR_IO_PENDING means the whole operation is async, while | |
1251 // errSSLWouldBlock means that the stream isn't ending (and is often returned | |
1252 // along with partial data). So even though "would block" is returned, if we | |
1253 // have data, let's just return it. This is further complicated by the fact | |
1254 // that errSSLWouldBlock is also used to short-circuit SSLRead()'s | |
1255 // transparent renegotiation, so that we can update our state machine above, | |
1256 // which otherwise would get out of sync with the SSLContextRef's internal | |
1257 // state machine. | |
1258 if (processed > 0) { | |
1259 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, | |
1260 processed, user_read_buf_->data()); | |
1261 return processed; | |
1262 } | |
1263 | |
1264 switch (status) { | |
1265 case errSSLClosedNoNotify: | |
1266 // TODO(wtc): Unless we have received the close_notify alert, we need to | |
1267 // return an error code indicating that the SSL connection ended | |
1268 // uncleanly, a potential truncation attack. See http://crbug.com/18586. | |
1269 return OK; | |
1270 | |
1271 default: | |
1272 return NetErrorFromOSStatus(status); | |
1273 } | |
1274 } | |
1275 | |
1276 int SSLClientSocketMac::DoPayloadWrite() { | |
1277 // Too much data in flight? | |
1278 if (send_buffer_.size() > kWriteSizePauseLimit) | |
1279 return ERR_IO_PENDING; | |
1280 | |
1281 size_t processed = 0; | |
1282 OSStatus status = SSLWrite(ssl_context_, | |
1283 user_write_buf_->data(), | |
1284 user_write_buf_len_, | |
1285 &processed); | |
1286 | |
1287 if (processed > 0) { | |
1288 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, processed, | |
1289 user_write_buf_->data()); | |
1290 return processed; | |
1291 } | |
1292 | |
1293 return NetErrorFromOSStatus(status); | |
1294 } | |
1295 | |
1296 int SSLClientSocketMac::DoCompletedRenegotiation(int result) { | |
1297 // The user had a read in progress, which was interrupted by the | |
1298 // renegotiation. Return the application data that was processed after the | |
1299 // handshake completed. | |
1300 next_handshake_state_ = STATE_COMPLETED_HANDSHAKE; | |
1301 if (result != OK) | |
1302 return result; | |
1303 return bytes_read_after_renegotiation_; | |
1304 } | |
1305 | |
1306 void SSLClientSocketMac::DidCompleteRenegotiation() { | |
1307 DCHECK(user_connect_callback_.is_null()); | |
1308 renegotiating_ = false; | |
1309 next_handshake_state_ = STATE_COMPLETED_RENEGOTIATION; | |
1310 } | |
1311 | |
1312 int SSLClientSocketMac::DidCompleteHandshake() { | |
1313 DCHECK(!server_cert_ || renegotiating_); | |
1314 VLOG(1) << "Handshake completed, next verify cert"; | |
1315 | |
1316 scoped_refptr<X509Certificate> new_server_cert( | |
1317 GetServerCert(ssl_context_)); | |
1318 if (!new_server_cert) | |
1319 return ERR_UNEXPECTED; | |
1320 net_log_.AddEvent( | |
1321 NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, | |
1322 base::Bind(&NetLogX509CertificateCallback, | |
1323 base::Unretained(new_server_cert.get()))); | |
1324 | |
1325 if (renegotiating_ && | |
1326 X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), | |
1327 new_server_cert->os_cert_handle())) { | |
1328 // We already verified the server certificate. Either it is good or the | |
1329 // user has accepted the certificate error. | |
1330 DidCompleteRenegotiation(); | |
1331 } else { | |
1332 server_cert_ = new_server_cert; | |
1333 next_handshake_state_ = STATE_VERIFY_CERT; | |
1334 } | |
1335 return OK; | |
1336 } | |
1337 | |
1338 // static | |
1339 OSStatus SSLClientSocketMac::SSLReadCallback(SSLConnectionRef connection, | |
1340 void* data, | |
1341 size_t* data_length) { | |
1342 DCHECK(data); | |
1343 DCHECK(data_length); | |
1344 SSLClientSocketMac* us = | |
1345 const_cast<SSLClientSocketMac*>( | |
1346 static_cast<const SSLClientSocketMac*>(connection)); | |
1347 | |
1348 if (us->read_io_buf_) { | |
1349 // We have I/O in flight; promise we'll get back to them and use the | |
1350 // existing callback to do so. | |
1351 *data_length = 0; | |
1352 return errSSLWouldBlock; | |
1353 } | |
1354 if (us->completed_handshake()) { | |
1355 // The state machine for SSLRead, located in libsecurity_ssl's | |
1356 // sslTransport.c, will attempt to fully complete the renegotiation | |
1357 // transparently in SSLRead once it reads the server's HelloRequest | |
1358 // message. In order to make sure that the server certificate is | |
1359 // (re-)verified and that any other parameters are logged (eg: | |
1360 // certificate request state), we try to detect that the | |
1361 // SSLClientSocketMac's state machine is out of sync with the | |
1362 // SSLContext's. When that happens, we break out by faking | |
1363 // errSSLWouldBlock, and set a flag so that DoPayloadRead() knows that | |
1364 // it's not actually blocked. DoPayloadRead() will then restart the | |
1365 // handshake state machine, and finally resume the original Read() | |
1366 // once it successfully completes, similar to the behaviour of | |
1367 // SSLClientSocketWin's DoDecryptPayload() and DoLoop() behave. | |
1368 SSLSessionState state; | |
1369 OSStatus status = SSLGetSessionState(us->ssl_context_, &state); | |
1370 if (status) { | |
1371 *data_length = 0; | |
1372 return status; | |
1373 } | |
1374 if (state == kSSLHandshake) { | |
1375 *data_length = 0; | |
1376 us->renegotiating_ = true; | |
1377 return errSSLWouldBlock; | |
1378 } | |
1379 } | |
1380 | |
1381 size_t total_read = us->recv_buffer_.size(); | |
1382 | |
1383 int rv = 1; // any old value to spin the loop below | |
1384 while (rv > 0 && total_read < *data_length) { | |
1385 us->read_io_buf_ = new IOBuffer(*data_length - total_read); | |
1386 rv = us->transport_->socket()->Read( | |
1387 us->read_io_buf_, | |
1388 *data_length - total_read, | |
1389 base::Bind(&SSLClientSocketMac::OnTransportReadComplete, | |
1390 base::Unretained(us))); | |
1391 | |
1392 if (rv >= 0) { | |
1393 us->recv_buffer_.insert(us->recv_buffer_.end(), | |
1394 us->read_io_buf_->data(), | |
1395 us->read_io_buf_->data() + rv); | |
1396 us->read_io_buf_ = NULL; | |
1397 total_read += rv; | |
1398 } | |
1399 } | |
1400 | |
1401 *data_length = total_read; | |
1402 if (total_read) { | |
1403 memcpy(data, &us->recv_buffer_[0], total_read); | |
1404 us->recv_buffer_.clear(); | |
1405 } | |
1406 | |
1407 if (rv != ERR_IO_PENDING) | |
1408 us->read_io_buf_ = NULL; | |
1409 | |
1410 if (rv < 0) | |
1411 return OSStatusFromNetError(rv); | |
1412 else if (rv == 0) // stream closed | |
1413 return errSSLClosedGraceful; | |
1414 else | |
1415 return noErr; | |
1416 } | |
1417 | |
1418 // static | |
1419 OSStatus SSLClientSocketMac::SSLWriteCallback(SSLConnectionRef connection, | |
1420 const void* data, | |
1421 size_t* data_length) { | |
1422 SSLClientSocketMac* us = | |
1423 const_cast<SSLClientSocketMac*>( | |
1424 static_cast<const SSLClientSocketMac*>(connection)); | |
1425 | |
1426 if (us->pending_send_error_ != OK) { | |
1427 OSStatus status = OSStatusFromNetError(us->pending_send_error_); | |
1428 us->pending_send_error_ = OK; | |
1429 return status; | |
1430 } | |
1431 | |
1432 if (data) | |
1433 us->send_buffer_.insert(us->send_buffer_.end(), | |
1434 static_cast<const char*>(data), | |
1435 static_cast<const char*>(data) + *data_length); | |
1436 | |
1437 if (us->write_io_buf_) { | |
1438 // If we have I/O in flight, just add the data to the end of the buffer and | |
1439 // return to our caller. The existing callback will trigger the write of the | |
1440 // new data when it sees that data remains in the buffer after removing the | |
1441 // sent data. As always, lie to our caller. | |
1442 return noErr; | |
1443 } | |
1444 | |
1445 int rv; | |
1446 do { | |
1447 us->write_io_buf_ = new IOBuffer(us->send_buffer_.size()); | |
1448 memcpy(us->write_io_buf_->data(), &us->send_buffer_[0], | |
1449 us->send_buffer_.size()); | |
1450 rv = us->transport_->socket()->Write( | |
1451 us->write_io_buf_, | |
1452 us->send_buffer_.size(), | |
1453 base::Bind(&SSLClientSocketMac::OnTransportWriteComplete, | |
1454 base::Unretained(us))); | |
1455 if (rv > 0) { | |
1456 us->send_buffer_.erase(us->send_buffer_.begin(), | |
1457 us->send_buffer_.begin() + rv); | |
1458 us->write_io_buf_ = NULL; | |
1459 } | |
1460 } while (rv > 0 && !us->send_buffer_.empty()); | |
1461 | |
1462 if (rv < 0 && rv != ERR_IO_PENDING) { | |
1463 us->write_io_buf_ = NULL; | |
1464 return OSStatusFromNetError(rv); | |
1465 } | |
1466 | |
1467 // always lie to our caller | |
1468 return noErr; | |
1469 } | |
1470 | |
1471 } // namespace net | |
OLD | NEW |