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

Side by Side Diff: net/socket/ssl_client_socket_mac.cc

Issue 11876044: Remove support for 'system' SSL on Mac (SecureTransport) and Win (SChannel) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review feedback Created 7 years, 11 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 | Annotate | Revision Log
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698