| OLD | NEW |
| 1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/socket/ssl_client_socket_mac.h" | 5 #include "net/socket/ssl_client_socket_mac.h" |
| 6 | 6 |
| 7 #include "base/singleton.h" | 7 #include "base/singleton.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
| 10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: | 234 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: |
| 235 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: | 235 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: |
| 236 case TLS_DH_anon_WITH_AES_256_CBC_SHA: | 236 case TLS_DH_anon_WITH_AES_256_CBC_SHA: |
| 237 return 256; | 237 return 256; |
| 238 | 238 |
| 239 default: | 239 default: |
| 240 return -1; | 240 return -1; |
| 241 } | 241 } |
| 242 } | 242 } |
| 243 | 243 |
| 244 // Returns the server's certificate. The caller must release a reference |
| 245 // to the return value when done. Returns NULL on failure. |
| 246 X509Certificate* GetServerCert(SSLContextRef ssl_context) { |
| 247 CFArrayRef certs; |
| 248 OSStatus status = SSLCopyPeerCertificates(ssl_context, &certs); |
| 249 if (status != noErr) |
| 250 return NULL; |
| 251 |
| 252 DCHECK_GT(CFArrayGetCount(certs), 0); |
| 253 |
| 254 SecCertificateRef server_cert = static_cast<SecCertificateRef>( |
| 255 const_cast<void*>(CFArrayGetValueAtIndex(certs, 0))); |
| 256 CFRetain(server_cert); |
| 257 CFRelease(certs); |
| 258 return X509Certificate::CreateFromHandle( |
| 259 server_cert, X509Certificate::SOURCE_FROM_NETWORK); |
| 260 } |
| 261 |
| 244 } // namespace | 262 } // namespace |
| 245 | 263 |
| 246 //----------------------------------------------------------------------------- | 264 //----------------------------------------------------------------------------- |
| 247 | 265 |
| 248 SSLClientSocketMac::SSLClientSocketMac(ClientSocket* transport_socket, | 266 SSLClientSocketMac::SSLClientSocketMac(ClientSocket* transport_socket, |
| 249 const std::string& hostname, | 267 const std::string& hostname, |
| 250 const SSLConfig& ssl_config) | 268 const SSLConfig& ssl_config) |
| 251 : io_callback_(this, &SSLClientSocketMac::OnIOComplete), | 269 : io_callback_(this, &SSLClientSocketMac::OnIOComplete), |
| 252 write_callback_(this, &SSLClientSocketMac::OnWriteComplete), | 270 write_callback_(this, &SSLClientSocketMac::OnWriteComplete), |
| 253 transport_(transport_socket), | 271 transport_(transport_socket), |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 return NetErrorFromOSStatus(status); | 316 return NetErrorFromOSStatus(status); |
| 299 | 317 |
| 300 status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); | 318 status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); |
| 301 if (status) | 319 if (status) |
| 302 return NetErrorFromOSStatus(status); | 320 return NetErrorFromOSStatus(status); |
| 303 | 321 |
| 304 status = SSLSetConnection(ssl_context_, this); | 322 status = SSLSetConnection(ssl_context_, this); |
| 305 if (status) | 323 if (status) |
| 306 return NetErrorFromOSStatus(status); | 324 return NetErrorFromOSStatus(status); |
| 307 | 325 |
| 308 status = SSLSetPeerDomainName(ssl_context_, hostname_.c_str(), | 326 if (ssl_config_.allowed_bad_certs.empty()) { |
| 309 hostname_.length()); | 327 // We're going to use the default certificate verification that the system |
| 310 if (status) | 328 // does, and accept its answer for the cert status. |
| 311 return NetErrorFromOSStatus(status); | 329 status = SSLSetPeerDomainName(ssl_context_, hostname_.data(), |
| 330 hostname_.length()); |
| 331 if (status) |
| 332 return NetErrorFromOSStatus(status); |
| 333 |
| 334 // TODO(wtc): for now, always check revocation. |
| 335 server_cert_status_ = CERT_STATUS_REV_CHECKING_ENABLED; |
| 336 } else { |
| 337 // Disable certificate chain validation. We will only allow the certs in |
| 338 // ssl_config_.allowed_bad_certs. |
| 339 status = SSLSetEnableCertVerify(ssl_context_, false); |
| 340 if (status) |
| 341 return NetErrorFromOSStatus(status); |
| 342 } |
| 312 | 343 |
| 313 next_state_ = STATE_HANDSHAKE; | 344 next_state_ = STATE_HANDSHAKE; |
| 314 int rv = DoLoop(OK); | 345 int rv = DoLoop(OK); |
| 315 if (rv == ERR_IO_PENDING) | 346 if (rv == ERR_IO_PENDING) |
| 316 user_callback_ = callback; | 347 user_callback_ = callback; |
| 317 return rv; | 348 return rv; |
| 318 } | 349 } |
| 319 | 350 |
| 320 void SSLClientSocketMac::Disconnect() { | 351 void SSLClientSocketMac::Disconnect() { |
| 321 completed_handshake_ = false; | 352 completed_handshake_ = false; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } else { | 418 } else { |
| 388 user_buf_ = NULL; | 419 user_buf_ = NULL; |
| 389 } | 420 } |
| 390 return rv; | 421 return rv; |
| 391 } | 422 } |
| 392 | 423 |
| 393 void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) { | 424 void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) { |
| 394 ssl_info->Reset(); | 425 ssl_info->Reset(); |
| 395 | 426 |
| 396 // set cert | 427 // set cert |
| 397 CFArrayRef certs; | 428 ssl_info->cert = server_cert_; |
| 398 OSStatus status = SSLCopyPeerCertificates(ssl_context_, &certs); | |
| 399 if (!status) { | |
| 400 DCHECK(CFArrayGetCount(certs) > 0); | |
| 401 | |
| 402 SecCertificateRef client_cert = | |
| 403 static_cast<SecCertificateRef>( | |
| 404 const_cast<void*>(CFArrayGetValueAtIndex(certs, 0))); | |
| 405 CFRetain(client_cert); | |
| 406 ssl_info->cert = X509Certificate::CreateFromHandle( | |
| 407 client_cert, X509Certificate::SOURCE_FROM_NETWORK); | |
| 408 CFRelease(certs); | |
| 409 } | |
| 410 | 429 |
| 411 // update status | 430 // update status |
| 412 ssl_info->cert_status = server_cert_status_; | 431 ssl_info->cert_status = server_cert_status_; |
| 413 | 432 |
| 414 // security info | 433 // security info |
| 415 SSLCipherSuite suite; | 434 SSLCipherSuite suite; |
| 416 status = SSLGetNegotiatedCipher(ssl_context_, &suite); | 435 OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite); |
| 417 if (!status) | 436 if (!status) |
| 418 ssl_info->security_bits = KeySizeOfCipherSuite(suite); | 437 ssl_info->security_bits = KeySizeOfCipherSuite(suite); |
| 419 } | 438 } |
| 420 | 439 |
| 421 void SSLClientSocketMac::GetSSLCertRequestInfo( | 440 void SSLClientSocketMac::GetSSLCertRequestInfo( |
| 422 SSLCertRequestInfo* cert_request_info) { | 441 SSLCertRequestInfo* cert_request_info) { |
| 423 // TODO(wtc): implement this. | 442 // TODO(wtc): implement this. |
| 424 } | 443 } |
| 425 | 444 |
| 426 void SSLClientSocketMac::DoCallback(int rv) { | 445 void SSLClientSocketMac::DoCallback(int rv) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 rv = ERR_UNEXPECTED; | 497 rv = ERR_UNEXPECTED; |
| 479 NOTREACHED() << "unexpected state"; | 498 NOTREACHED() << "unexpected state"; |
| 480 break; | 499 break; |
| 481 } | 500 } |
| 482 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 501 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| 483 return rv; | 502 return rv; |
| 484 } | 503 } |
| 485 | 504 |
| 486 int SSLClientSocketMac::DoHandshake() { | 505 int SSLClientSocketMac::DoHandshake() { |
| 487 OSStatus status = SSLHandshake(ssl_context_); | 506 OSStatus status = SSLHandshake(ssl_context_); |
| 488 | |
| 489 if (status == errSSLWouldBlock) | |
| 490 next_state_ = STATE_HANDSHAKE; | |
| 491 | |
| 492 if (status == noErr) | |
| 493 completed_handshake_ = true; | |
| 494 | |
| 495 int net_error = NetErrorFromOSStatus(status); | 507 int net_error = NetErrorFromOSStatus(status); |
| 496 | 508 |
| 497 // At this point we have a connection. For now, we're going to use the default | 509 if (status == errSSLWouldBlock) { |
| 498 // certificate verification that the system does, and accept its answer for | 510 next_state_ = STATE_HANDSHAKE; |
| 499 // the cert status. In the future, we'll need to call SSLSetEnableCertVerify | 511 } else if (status == noErr) { |
| 500 // to disable cert verification and do the verification ourselves. This allows | 512 completed_handshake_ = true; // We have a connection. |
| 501 // very fine-grained control over what we'll accept for certification. | |
| 502 // TODO(avi): ditto | |
| 503 | 513 |
| 504 // TODO(wtc): for now, always check revocation. | 514 server_cert_ = GetServerCert(ssl_context_); |
| 505 server_cert_status_ = CERT_STATUS_REV_CHECKING_ENABLED; | 515 DCHECK(server_cert_); |
| 506 if (net_error) | 516 if (!ssl_config_.allowed_bad_certs.empty()) { |
| 517 // Check server_cert_ because SecureTransport didn't verify it. |
| 518 // TODO(wtc): If server_cert_ is not one of the allowed bad certificates, |
| 519 // we should verify server_cert_ ourselves. Since we don't know how to |
| 520 // do that yet, treat it as an invalid certificate. |
| 521 net_error = ERR_CERT_INVALID; |
| 522 server_cert_status_ |= CERT_STATUS_INVALID; |
| 523 |
| 524 for (size_t i = 0; i < ssl_config_.allowed_bad_certs.size(); ++i) { |
| 525 if (server_cert_ == ssl_config_.allowed_bad_certs[i].cert) { |
| 526 net_error = OK; |
| 527 server_cert_status_ = ssl_config_.allowed_bad_certs[i].cert_status; |
| 528 break; |
| 529 } |
| 530 } |
| 531 } |
| 532 } else if (IsCertStatusError(net_error)) { |
| 533 server_cert_ = GetServerCert(ssl_context_); |
| 534 DCHECK(server_cert_); |
| 507 server_cert_status_ |= MapNetErrorToCertStatus(net_error); | 535 server_cert_status_ |= MapNetErrorToCertStatus(net_error); |
| 536 } |
| 508 | 537 |
| 509 return net_error; | 538 return net_error; |
| 510 } | 539 } |
| 511 | 540 |
| 512 int SSLClientSocketMac::DoReadComplete(int result) { | 541 int SSLClientSocketMac::DoReadComplete(int result) { |
| 513 if (result < 0) { | 542 if (result < 0) { |
| 514 read_io_buf_ = NULL; | 543 read_io_buf_ = NULL; |
| 515 return result; | 544 return result; |
| 516 } | 545 } |
| 517 | 546 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 | 799 |
| 771 if (rv < 0 && rv != ERR_IO_PENDING) { | 800 if (rv < 0 && rv != ERR_IO_PENDING) { |
| 772 return OSStatusFromNetError(rv); | 801 return OSStatusFromNetError(rv); |
| 773 } | 802 } |
| 774 | 803 |
| 775 // always lie to our caller | 804 // always lie to our caller |
| 776 return noErr; | 805 return noErr; |
| 777 } | 806 } |
| 778 | 807 |
| 779 } // namespace net | 808 } // namespace net |
| OLD | NEW |