Chromium Code Reviews| 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/scoped_cftyperef.h" | 7 #include "base/scoped_cftyperef.h" |
| 8 #include "base/singleton.h" | 8 #include "base/singleton.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "net/base/cert_verifier.h" | 10 #include "net/base/cert_verifier.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 // we wrote before we would have blocked. But with the asynchronous I/O, the | 61 // we wrote before we would have blocked. But with the asynchronous I/O, the |
| 62 // transport underneath us can tell us that it'll let us know sometime "later" | 62 // transport underneath us can tell us that it'll let us know sometime "later" |
| 63 // whether or not things succeeded, and how many bytes were written. What do we | 63 // whether or not things succeeded, and how many bytes were written. What do we |
| 64 // return to Secure Transport? We can't return a byte count, but we can't return | 64 // return to Secure Transport? We can't return a byte count, but we can't return |
| 65 // "later" as we're not guaranteed to be called in the future with the same data | 65 // "later" as we're not guaranteed to be called in the future with the same data |
| 66 // to write. | 66 // to write. |
| 67 // | 67 // |
| 68 // So, like in any good relationship, we're forced to lie. Whenever Secure | 68 // So, like in any good relationship, we're forced to lie. Whenever Secure |
| 69 // Transport asks for data to be written, we take it all and lie about it always | 69 // Transport asks for data to be written, we take it all and lie about it always |
| 70 // being written. We spin in a loop (see SSLWriteCallback() and | 70 // being written. We spin in a loop (see SSLWriteCallback() and |
| 71 // OnWriteComplete()) independent of the main state machine writing the data to | 71 // OnTransportWriteComplete()) independent of the main state machine writing |
| 72 // the network, and get the data out. The main consequence of this independence | 72 // the data to he network, and get the data out. The main consequence of this |
| 73 // from the state machine is that we require a full-duplex transport underneath | 73 // independence from the state machine is that we require a full-duplex |
| 74 // us since we can't use it to keep our reading and writing | 74 // transport underneath us since we can't use it to keep our reading and |
| 75 // straight. Fortunately, the NSS implementation also has this issue to deal | 75 // writing straight. Fortunately, the NSS implementation also has this issue |
| 76 // with, so we share the same Libevent-based full-duplex TCP socket. | 76 // to deal with, so we share the same Libevent-based full-duplex TCP socket. |
| 77 // | 77 // |
| 78 // A side comment on return values might be in order. Those who haven't taken | 78 // A side comment on return values might be in order. Those who haven't taken |
| 79 // the time to read the documentation (ahem, header comments) in our various | 79 // the time to read the documentation (ahem, header comments) in our various |
| 80 // files might be a bit surprised to see result values being treated as both | 80 // files might be a bit surprised to see result values being treated as both |
| 81 // lengths and errors. Like Shimmer, they are both. In both the case of | 81 // lengths and errors. Like Shimmer, they are both. In both the case of |
| 82 // immediate results as well as results returned in callbacks, a negative return | 82 // immediate results as well as results returned in callbacks, a negative return |
| 83 // value indicates an error, a zero return value indicates end-of-stream (for | 83 // value indicates an error, a zero return value indicates end-of-stream (for |
| 84 // reads), and a positive return value indicates the number of bytes read or | 84 // reads), and a positive return value indicates the number of bytes read or |
| 85 // written. Thus, many functions start off with |if (result < 0) return | 85 // written. Thus, many functions start off with |if (result < 0) return |
| 86 // result;|. That gets the error condition out of the way, and from that point | 86 // result;|. That gets the error condition out of the way, and from that point |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 return x509_cert; | 290 return x509_cert; |
| 291 } | 291 } |
| 292 | 292 |
| 293 } // namespace | 293 } // namespace |
| 294 | 294 |
| 295 //----------------------------------------------------------------------------- | 295 //----------------------------------------------------------------------------- |
| 296 | 296 |
| 297 SSLClientSocketMac::SSLClientSocketMac(ClientSocket* transport_socket, | 297 SSLClientSocketMac::SSLClientSocketMac(ClientSocket* transport_socket, |
| 298 const std::string& hostname, | 298 const std::string& hostname, |
| 299 const SSLConfig& ssl_config) | 299 const SSLConfig& ssl_config) |
| 300 : io_callback_(this, &SSLClientSocketMac::OnIOComplete), | 300 : handshake_io_callback_(this, &SSLClientSocketMac::OnHandshakeIOComplete), |
| 301 write_callback_(this, &SSLClientSocketMac::OnWriteComplete), | 301 transport_read_callback_(this, |
| 302 &SSLClientSocketMac::OnTransportReadComplete), | |
| 303 transport_write_callback_(this, | |
| 304 &SSLClientSocketMac::OnTransportWriteComplete), | |
| 302 transport_(transport_socket), | 305 transport_(transport_socket), |
| 303 hostname_(hostname), | 306 hostname_(hostname), |
| 304 ssl_config_(ssl_config), | 307 ssl_config_(ssl_config), |
| 305 user_callback_(NULL), | 308 user_connect_callback_(NULL), |
| 306 next_state_(STATE_NONE), | 309 user_read_callback_(NULL), |
| 307 next_io_state_(STATE_NONE), | 310 user_write_callback_(NULL), |
| 311 user_read_buf_len_(0), | |
| 312 user_write_buf_len_(0), | |
| 313 next_handshake_state_(STATE_NONE), | |
| 308 completed_handshake_(false), | 314 completed_handshake_(false), |
| 309 handshake_interrupted_(false), | 315 handshake_interrupted_(false), |
| 310 ssl_context_(NULL), | 316 ssl_context_(NULL), |
| 311 pending_send_error_(OK), | 317 pending_send_error_(OK), |
| 312 recv_buffer_head_slop_(0), | 318 recv_buffer_head_slop_(0), |
| 313 recv_buffer_tail_slop_(0) { | 319 recv_buffer_tail_slop_(0) { |
| 314 } | 320 } |
| 315 | 321 |
| 316 SSLClientSocketMac::~SSLClientSocketMac() { | 322 SSLClientSocketMac::~SSLClientSocketMac() { |
| 317 Disconnect(); | 323 Disconnect(); |
| 318 } | 324 } |
| 319 | 325 |
| 320 int SSLClientSocketMac::Connect(CompletionCallback* callback) { | 326 int SSLClientSocketMac::Connect(CompletionCallback* callback) { |
| 321 DCHECK(transport_.get()); | 327 DCHECK(transport_.get()); |
| 322 DCHECK(next_state_ == STATE_NONE); | 328 DCHECK(next_handshake_state_ == STATE_NONE); |
| 323 DCHECK(!user_callback_); | 329 DCHECK(!user_connect_callback_); |
| 324 | 330 |
| 325 OSStatus status = noErr; | 331 OSStatus status = noErr; |
| 326 | 332 |
| 327 status = SSLNewContext(false, &ssl_context_); | 333 status = SSLNewContext(false, &ssl_context_); |
| 328 if (status) | 334 if (status) |
| 329 return NetErrorFromOSStatus(status); | 335 return NetErrorFromOSStatus(status); |
| 330 | 336 |
| 331 status = SSLSetProtocolVersionEnabled(ssl_context_, | 337 status = SSLSetProtocolVersionEnabled(ssl_context_, |
| 332 kSSLProtocol2, | 338 kSSLProtocol2, |
| 333 ssl_config_.ssl2_enabled); | 339 ssl_config_.ssl2_enabled); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 | 414 |
| 409 // SSLSetPeerID() treats peer_id as a binary blob, and makes its | 415 // SSLSetPeerID() treats peer_id as a binary blob, and makes its |
| 410 // own copy. | 416 // own copy. |
| 411 status = SSLSetPeerID(ssl_context_, &peer_id[0], peer_id.size()); | 417 status = SSLSetPeerID(ssl_context_, &peer_id[0], peer_id.size()); |
| 412 if (status) | 418 if (status) |
| 413 return NetErrorFromOSStatus(status); | 419 return NetErrorFromOSStatus(status); |
| 414 } | 420 } |
| 415 } | 421 } |
| 416 } | 422 } |
| 417 | 423 |
| 418 next_state_ = STATE_HANDSHAKE_START; | 424 next_handshake_state_ = STATE_HANDSHAKE_START; |
| 419 int rv = DoLoop(OK); | 425 int rv = DoHandshakeLoop(OK); |
| 420 if (rv == ERR_IO_PENDING) | 426 if (rv == ERR_IO_PENDING) |
| 421 user_callback_ = callback; | 427 user_connect_callback_ = callback; |
| 422 return rv; | 428 return rv; |
| 423 } | 429 } |
| 424 | 430 |
| 425 void SSLClientSocketMac::Disconnect() { | 431 void SSLClientSocketMac::Disconnect() { |
| 426 completed_handshake_ = false; | 432 completed_handshake_ = false; |
| 427 | 433 |
| 428 if (ssl_context_) { | 434 if (ssl_context_) { |
| 429 SSLClose(ssl_context_); | 435 SSLClose(ssl_context_); |
| 430 SSLDisposeContext(ssl_context_); | 436 SSLDisposeContext(ssl_context_); |
| 431 ssl_context_ = NULL; | 437 ssl_context_ = NULL; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 453 // alert message from the server, and return false in that case. Although | 459 // alert message from the server, and return false in that case. Although |
| 454 // the close_notify alert message means EOF in the SSL layer, it is just | 460 // the close_notify alert message means EOF in the SSL layer, it is just |
| 455 // bytes to the transport layer below, so transport_->IsConnectedAndIdle() | 461 // bytes to the transport layer below, so transport_->IsConnectedAndIdle() |
| 456 // returns the desired false when we receive close_notify. | 462 // returns the desired false when we receive close_notify. |
| 457 return completed_handshake_ && transport_->IsConnectedAndIdle(); | 463 return completed_handshake_ && transport_->IsConnectedAndIdle(); |
| 458 } | 464 } |
| 459 | 465 |
| 460 int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len, | 466 int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len, |
| 461 CompletionCallback* callback) { | 467 CompletionCallback* callback) { |
| 462 DCHECK(completed_handshake_); | 468 DCHECK(completed_handshake_); |
| 463 DCHECK(next_state_ == STATE_NONE); | 469 DCHECK(!user_read_callback_); |
| 464 DCHECK(!user_callback_); | 470 DCHECK(!user_read_buf_); |
| 465 DCHECK(!user_buf_); | |
| 466 | 471 |
| 467 user_buf_ = buf; | 472 user_read_buf_ = buf; |
| 468 user_buf_len_ = buf_len; | 473 user_read_buf_len_ = buf_len; |
| 469 | 474 |
| 470 next_state_ = STATE_PAYLOAD_READ; | 475 int rv = DoPayloadRead(); |
| 471 int rv = DoLoop(OK); | |
| 472 if (rv == ERR_IO_PENDING) { | 476 if (rv == ERR_IO_PENDING) { |
| 473 user_callback_ = callback; | 477 user_read_callback_ = callback; |
| 474 } else { | 478 } else { |
| 475 user_buf_ = NULL; | 479 user_read_buf_ = NULL; |
| 480 user_read_buf_len_ = 0; | |
| 476 } | 481 } |
| 477 return rv; | 482 return rv; |
| 478 } | 483 } |
| 479 | 484 |
| 480 int SSLClientSocketMac::Write(IOBuffer* buf, int buf_len, | 485 int SSLClientSocketMac::Write(IOBuffer* buf, int buf_len, |
| 481 CompletionCallback* callback) { | 486 CompletionCallback* callback) { |
| 482 DCHECK(completed_handshake_); | 487 DCHECK(completed_handshake_); |
| 483 DCHECK(next_state_ == STATE_NONE); | 488 DCHECK(!user_write_callback_); |
| 484 DCHECK(!user_callback_); | 489 DCHECK(!user_write_buf_); |
| 485 DCHECK(!user_buf_); | |
| 486 | 490 |
| 487 user_buf_ = buf; | 491 user_write_buf_ = buf; |
| 488 user_buf_len_ = buf_len; | 492 user_write_buf_len_ = buf_len; |
| 489 | 493 |
| 490 next_state_ = STATE_PAYLOAD_WRITE; | 494 int rv = DoPayloadWrite(); |
| 491 int rv = DoLoop(OK); | |
| 492 if (rv == ERR_IO_PENDING) { | 495 if (rv == ERR_IO_PENDING) { |
| 493 user_callback_ = callback; | 496 user_write_callback_ = callback; |
| 494 } else { | 497 } else { |
| 495 user_buf_ = NULL; | 498 user_write_buf_ = NULL; |
| 499 user_write_buf_len_ = 0; | |
| 496 } | 500 } |
| 497 return rv; | 501 return rv; |
| 498 } | 502 } |
| 499 | 503 |
| 500 bool SSLClientSocketMac::SetReceiveBufferSize(int32 size) { | 504 bool SSLClientSocketMac::SetReceiveBufferSize(int32 size) { |
| 501 return transport_->SetReceiveBufferSize(size); | 505 return transport_->SetReceiveBufferSize(size); |
| 502 } | 506 } |
| 503 | 507 |
| 504 bool SSLClientSocketMac::SetSendBufferSize(int32 size) { | 508 bool SSLClientSocketMac::SetSendBufferSize(int32 size) { |
| 505 return transport_->SetSendBufferSize(size); | 509 return transport_->SetSendBufferSize(size); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 521 OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite); | 525 OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite); |
| 522 if (!status) | 526 if (!status) |
| 523 ssl_info->security_bits = KeySizeOfCipherSuite(suite); | 527 ssl_info->security_bits = KeySizeOfCipherSuite(suite); |
| 524 } | 528 } |
| 525 | 529 |
| 526 void SSLClientSocketMac::GetSSLCertRequestInfo( | 530 void SSLClientSocketMac::GetSSLCertRequestInfo( |
| 527 SSLCertRequestInfo* cert_request_info) { | 531 SSLCertRequestInfo* cert_request_info) { |
| 528 // TODO(wtc): implement this. | 532 // TODO(wtc): implement this. |
| 529 } | 533 } |
| 530 | 534 |
| 531 void SSLClientSocketMac::DoCallback(int rv) { | 535 void SSLClientSocketMac::DoConnectCallback(int rv) { |
| 532 DCHECK(rv != ERR_IO_PENDING); | 536 DCHECK(rv != ERR_IO_PENDING); |
| 533 DCHECK(user_callback_); | 537 DCHECK(user_connect_callback_); |
| 538 DCHECK(next_handshake_state_ == STATE_NONE); | |
| 534 | 539 |
| 535 // since Run may result in Read being called, clear user_callback_ up front. | 540 CompletionCallback* c = user_connect_callback_; |
| 536 CompletionCallback* c = user_callback_; | 541 user_connect_callback_ = NULL; |
| 537 user_callback_ = NULL; | 542 c->Run(rv > OK ? OK : rv); |
| 538 user_buf_ = NULL; | 543 } |
| 544 | |
| 545 void SSLClientSocketMac::DoReadCallback(int rv) { | |
| 546 DCHECK(rv != ERR_IO_PENDING); | |
| 547 DCHECK(user_read_callback_); | |
| 548 | |
| 549 // Since Run may result in Read being called, clear user_read_callback_ up | |
| 550 // front. | |
| 551 CompletionCallback* c = user_read_callback_; | |
| 552 user_read_callback_ = NULL; | |
| 553 user_read_buf_ = NULL; | |
| 554 user_read_buf_len_ = 0; | |
| 539 c->Run(rv); | 555 c->Run(rv); |
| 540 } | 556 } |
| 541 | 557 |
| 542 void SSLClientSocketMac::OnIOComplete(int result) { | 558 void SSLClientSocketMac::DoWriteCallback(int rv) { |
| 543 if (next_io_state_ != STATE_NONE) { | 559 DCHECK(rv != ERR_IO_PENDING); |
| 544 State next_state = next_state_; | 560 DCHECK(user_write_callback_); |
| 545 next_state_ = next_io_state_; | 561 |
| 546 next_io_state_ = STATE_NONE; | 562 // Since Run may result in Write being called, clear user_write_callback_ up |
| 547 result = DoLoop(result); | 563 // front. |
| 548 next_state_ = next_state; | 564 CompletionCallback* c = user_write_callback_; |
| 565 user_write_callback_ = NULL; | |
| 566 user_write_buf_ = NULL; | |
| 567 user_write_buf_len_ = 0; | |
| 568 c->Run(rv); | |
| 569 } | |
| 570 | |
| 571 void SSLClientSocketMac::OnHandshakeIOComplete(int result) { | |
| 572 DCHECK(next_handshake_state_ != STATE_NONE); | |
| 573 int rv = DoHandshakeLoop(result); | |
| 574 if (rv != ERR_IO_PENDING) | |
| 575 DoConnectCallback(rv); | |
| 576 } | |
| 577 | |
| 578 void SSLClientSocketMac::OnTransportReadComplete(int result) { | |
| 579 if (result > 0) { | |
| 580 char* buffer = | |
| 581 » &recv_buffer_[recv_buffer_.size() - recv_buffer_tail_slop_]; | |
| 582 memcpy(buffer, read_io_buf_->data(), result); | |
| 583 recv_buffer_tail_slop_ -= result; | |
| 549 } | 584 } |
| 550 if (next_state_ != STATE_NONE) { | 585 read_io_buf_ = NULL; |
| 551 int rv = DoLoop(result); | 586 |
| 587 if (next_handshake_state_ != STATE_NONE) { | |
| 588 int rv = DoHandshakeLoop(result); | |
| 552 if (rv != ERR_IO_PENDING) | 589 if (rv != ERR_IO_PENDING) |
| 553 DoCallback(rv); | 590 DoConnectCallback(rv); |
| 591 return; | |
| 554 } | 592 } |
| 593 if (user_read_buf_) { | |
| 594 if (result < 0) { | |
| 595 DoReadCallback(result); | |
| 596 return; | |
| 597 } | |
| 598 int rv = DoPayloadRead(); | |
| 599 if (rv != ERR_IO_PENDING) | |
| 600 DoReadCallback(rv); | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 void SSLClientSocketMac::OnTransportWriteComplete(int result) { | |
| 605 if (result < 0) { | |
| 606 pending_send_error_ = result; | |
| 607 return; | |
| 608 } | |
| 609 send_buffer_.erase(send_buffer_.begin(), | |
| 610 send_buffer_.begin() + result); | |
| 611 if (!send_buffer_.empty()) | |
| 612 SSLWriteCallback(this, NULL, NULL); | |
| 613 | |
| 614 // Since SSLWriteCallback() lies to return noErr even if transport_->Write() | |
| 615 // returns ERR_IO_PENDING, we don't need to any callbacks here. | |
|
wtc
2009/10/22 22:06:44
Nit: add "call" or "do" after "need to".
| |
| 555 } | 616 } |
| 556 | 617 |
| 557 // This is the main loop driving the state machine. Most calls coming from the | 618 // This is the main loop driving the state machine. Most calls coming from the |
| 558 // outside just set up a few variables and jump into here. | 619 // outside just set up a few variables and jump into here. |
| 559 int SSLClientSocketMac::DoLoop(int last_io_result) { | 620 int SSLClientSocketMac::DoHandshakeLoop(int last_io_result) { |
| 560 DCHECK(next_state_ != STATE_NONE); | 621 DCHECK(next_handshake_state_ != STATE_NONE); |
| 561 int rv = last_io_result; | 622 int rv = last_io_result; |
| 562 do { | 623 do { |
| 563 State state = next_state_; | 624 State state = next_handshake_state_; |
| 564 next_state_ = STATE_NONE; | 625 next_handshake_state_ = STATE_NONE; |
| 565 switch (state) { | 626 switch (state) { |
| 566 case STATE_HANDSHAKE_START: | 627 case STATE_HANDSHAKE_START: |
| 567 // Do the SSL/TLS handshake, up to the server certificate message. | 628 // Do the SSL/TLS handshake, up to the server certificate message. |
| 568 rv = DoHandshakeStart(); | 629 rv = DoHandshakeStart(); |
| 569 break; | 630 break; |
| 570 case STATE_VERIFY_CERT: | 631 case STATE_VERIFY_CERT: |
| 571 // Kick off server certificate validation. | 632 // Kick off server certificate validation. |
| 572 rv = DoVerifyCert(); | 633 rv = DoVerifyCert(); |
| 573 break; | 634 break; |
| 574 case STATE_VERIFY_CERT_COMPLETE: | 635 case STATE_VERIFY_CERT_COMPLETE: |
| 575 // Check the results of the server certificate validation. | 636 // Check the results of the server certificate validation. |
| 576 rv = DoVerifyCertComplete(rv); | 637 rv = DoVerifyCertComplete(rv); |
| 577 break; | 638 break; |
| 578 case STATE_HANDSHAKE_FINISH: | 639 case STATE_HANDSHAKE_FINISH: |
| 579 // Do the SSL/TLS handshake, after the server certificate message. | 640 // Do the SSL/TLS handshake, after the server certificate message. |
| 580 rv = DoHandshakeFinish(); | 641 rv = DoHandshakeFinish(); |
| 581 break; | 642 break; |
| 582 case STATE_READ_COMPLETE: | |
| 583 // A read off the network is complete; do the paperwork. | |
| 584 rv = DoReadComplete(rv); | |
| 585 break; | |
| 586 case STATE_PAYLOAD_READ: | |
| 587 // Do a read of data from the network. | |
| 588 rv = DoPayloadRead(); | |
| 589 break; | |
| 590 case STATE_PAYLOAD_WRITE: | |
| 591 // Do a write of data to the network. | |
| 592 rv = DoPayloadWrite(); | |
| 593 break; | |
| 594 default: | 643 default: |
| 595 rv = ERR_UNEXPECTED; | 644 rv = ERR_UNEXPECTED; |
| 596 NOTREACHED() << "unexpected state"; | 645 NOTREACHED() << "unexpected state"; |
| 597 break; | 646 break; |
| 598 } | 647 } |
| 599 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 648 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); |
| 600 return rv; | 649 return rv; |
| 601 } | 650 } |
| 602 | 651 |
| 603 int SSLClientSocketMac::DoHandshakeStart() { | 652 int SSLClientSocketMac::DoHandshakeStart() { |
| 604 OSStatus status = SSLHandshake(ssl_context_); | 653 OSStatus status = SSLHandshake(ssl_context_); |
| 605 | |
| 606 if (status == errSSLWouldBlock) | 654 if (status == errSSLWouldBlock) |
| 607 next_state_ = STATE_HANDSHAKE_START; | 655 next_handshake_state_ = STATE_HANDSHAKE_START; |
| 608 | 656 |
| 609 server_cert_ = GetServerCert(ssl_context_); | 657 server_cert_ = GetServerCert(ssl_context_); |
| 610 | 658 |
| 611 if (status == noErr || status == errSSLServerAuthCompletedFlag) { | 659 if (status == noErr || status == errSSLServerAuthCompletedFlag) { |
| 612 if (!server_cert_) | 660 if (!server_cert_) |
| 613 return ERR_UNEXPECTED; | 661 return ERR_UNEXPECTED; |
| 614 | 662 |
| 615 // TODO(hawk): we verify the certificate chain even on resumed sessions | 663 // TODO(hawk): we verify the certificate chain even on resumed sessions |
| 616 // so that we have the certificate status (valid, expired but overridden | 664 // so that we have the certificate status (valid, expired but overridden |
| 617 // by the user, EV, etc.) available. Eliminate this step once we have | 665 // by the user, EV, etc.) available. Eliminate this step once we have |
| 618 // a certificate validation result cache. | 666 // a certificate validation result cache. |
| 619 next_state_ = STATE_VERIFY_CERT; | 667 next_handshake_state_ = STATE_VERIFY_CERT; |
| 620 if (status == errSSLServerAuthCompletedFlag) { | 668 if (status == errSSLServerAuthCompletedFlag) { |
| 621 // Override errSSLServerAuthCompletedFlag as it's not actually an error, | 669 // Override errSSLServerAuthCompletedFlag as it's not actually an error, |
| 622 // but rather an indication that we're only half way through the | 670 // but rather an indication that we're only half way through the |
| 623 // handshake. | 671 // handshake. |
| 624 handshake_interrupted_ = true; | 672 handshake_interrupted_ = true; |
| 625 status = noErr; | 673 status = noErr; |
| 626 } | 674 } |
| 627 } | 675 } |
| 628 | 676 |
| 629 return NetErrorFromOSStatus(status); | 677 return NetErrorFromOSStatus(status); |
| 630 } | 678 } |
| 631 | 679 |
| 632 int SSLClientSocketMac::DoVerifyCert() { | 680 int SSLClientSocketMac::DoVerifyCert() { |
| 633 next_state_ = STATE_VERIFY_CERT_COMPLETE; | 681 next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE; |
| 634 | 682 |
| 635 if (!server_cert_) | 683 if (!server_cert_) |
| 636 return ERR_UNEXPECTED; | 684 return ERR_UNEXPECTED; |
| 637 | 685 |
| 638 int flags = 0; | 686 int flags = 0; |
| 639 if (ssl_config_.rev_checking_enabled) | 687 if (ssl_config_.rev_checking_enabled) |
| 640 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 688 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
| 641 if (ssl_config_.verify_ev_cert) | 689 if (ssl_config_.verify_ev_cert) |
| 642 flags |= X509Certificate::VERIFY_EV_CERT; | 690 flags |= X509Certificate::VERIFY_EV_CERT; |
| 643 verifier_.reset(new CertVerifier); | 691 verifier_.reset(new CertVerifier); |
| 644 return verifier_->Verify(server_cert_, hostname_, flags, | 692 return verifier_->Verify(server_cert_, hostname_, flags, |
| 645 &server_cert_verify_result_, &io_callback_); | 693 &server_cert_verify_result_, |
| 694 &handshake_io_callback_); | |
| 646 } | 695 } |
| 647 | 696 |
| 648 int SSLClientSocketMac::DoVerifyCertComplete(int result) { | 697 int SSLClientSocketMac::DoVerifyCertComplete(int result) { |
| 649 DCHECK(verifier_.get()); | 698 DCHECK(verifier_.get()); |
| 650 verifier_.reset(); | 699 verifier_.reset(); |
| 651 | 700 |
| 652 if (IsCertificateError(result) && ssl_config_.IsAllowedBadCert(server_cert_)) | 701 if (IsCertificateError(result) && ssl_config_.IsAllowedBadCert(server_cert_)) |
| 653 result = OK; | 702 result = OK; |
| 654 | 703 |
| 655 if (handshake_interrupted_) { | 704 if (handshake_interrupted_) { |
| 656 // With session resumption enabled the full handshake (i.e., the handshake | 705 // With session resumption enabled the full handshake (i.e., the handshake |
| 657 // in a non-resumed session) occurs in two steps. Continue on to the second | 706 // in a non-resumed session) occurs in two steps. Continue on to the second |
| 658 // step if the certificate is OK. | 707 // step if the certificate is OK. |
| 659 if (result == OK) | 708 if (result == OK) |
| 660 next_state_ = STATE_HANDSHAKE_FINISH; | 709 next_handshake_state_ = STATE_HANDSHAKE_FINISH; |
| 661 } else { | 710 } else { |
| 662 // If the session was resumed or session resumption was disabled, we're | 711 // If the session was resumed or session resumption was disabled, we're |
| 663 // done with the handshake. | 712 // done with the handshake. |
| 664 completed_handshake_ = true; | 713 completed_handshake_ = true; |
| 665 DCHECK(next_state_ == STATE_NONE); | 714 DCHECK(next_handshake_state_ == STATE_NONE); |
| 666 } | 715 } |
| 667 | 716 |
| 668 return result; | 717 return result; |
| 669 } | 718 } |
| 670 | 719 |
| 671 int SSLClientSocketMac::DoHandshakeFinish() { | 720 int SSLClientSocketMac::DoHandshakeFinish() { |
| 672 OSStatus status = SSLHandshake(ssl_context_); | 721 OSStatus status = SSLHandshake(ssl_context_); |
| 673 | 722 |
| 674 if (status == errSSLWouldBlock) | 723 if (status == errSSLWouldBlock) |
| 675 next_state_ = STATE_HANDSHAKE_FINISH; | 724 next_handshake_state_ = STATE_HANDSHAKE_FINISH; |
| 676 | 725 |
| 677 if (status == noErr) | 726 if (status == noErr) { |
| 678 completed_handshake_ = true; | 727 completed_handshake_ = true; |
| 728 DCHECK(next_handshake_state_ == STATE_NONE); | |
| 729 } | |
| 679 | 730 |
| 680 return NetErrorFromOSStatus(status); | 731 return NetErrorFromOSStatus(status); |
| 681 } | 732 } |
| 682 | 733 |
| 683 int SSLClientSocketMac::DoReadComplete(int result) { | |
| 684 if (result < 0) { | |
| 685 read_io_buf_ = NULL; | |
| 686 return result; | |
| 687 } | |
| 688 | |
| 689 char* buffer = &recv_buffer_[recv_buffer_.size() - recv_buffer_tail_slop_]; | |
| 690 memcpy(buffer, read_io_buf_->data(), result); | |
| 691 read_io_buf_ = NULL; | |
| 692 | |
| 693 recv_buffer_tail_slop_ -= result; | |
| 694 | |
| 695 return result; | |
| 696 } | |
| 697 | |
| 698 void SSLClientSocketMac::OnWriteComplete(int result) { | |
| 699 if (result < 0) { | |
| 700 pending_send_error_ = result; | |
| 701 return; | |
| 702 } | |
| 703 | |
| 704 send_buffer_.erase(send_buffer_.begin(), | |
| 705 send_buffer_.begin() + result); | |
| 706 | |
| 707 if (!send_buffer_.empty()) | |
| 708 SSLWriteCallback(this, NULL, NULL); | |
| 709 } | |
| 710 | |
| 711 int SSLClientSocketMac::DoPayloadRead() { | 734 int SSLClientSocketMac::DoPayloadRead() { |
| 712 size_t processed = 0; | 735 size_t processed = 0; |
| 713 OSStatus status = SSLRead(ssl_context_, | 736 OSStatus status = SSLRead(ssl_context_, |
| 714 user_buf_->data(), | 737 user_read_buf_->data(), |
| 715 user_buf_len_, | 738 user_read_buf_len_, |
| 716 &processed); | 739 &processed); |
| 717 | 740 |
| 718 // There's a subtle difference here in semantics of the "would block" errors. | 741 // There's a subtle difference here in semantics of the "would block" errors. |
| 719 // In our code, ERR_IO_PENDING means the whole operation is async, while | 742 // In our code, ERR_IO_PENDING means the whole operation is async, while |
| 720 // errSSLWouldBlock means that the stream isn't ending (and is often returned | 743 // errSSLWouldBlock means that the stream isn't ending (and is often returned |
| 721 // along with partial data). So even though "would block" is returned, if we | 744 // along with partial data). So even though "would block" is returned, if we |
| 722 // have data, let's just return it. | 745 // have data, let's just return it. |
| 723 | 746 |
| 724 if (processed > 0) | 747 if (processed > 0) |
| 725 return processed; | 748 return processed; |
| 726 | 749 |
| 727 if (status == errSSLClosedNoNotify) { | 750 if (status == errSSLClosedNoNotify) { |
| 728 // TODO(wtc): Unless we have received the close_notify alert, we need to | 751 // TODO(wtc): Unless we have received the close_notify alert, we need to |
| 729 // return an error code indicating that the SSL connection ended | 752 // return an error code indicating that the SSL connection ended |
| 730 // uncleanly, a potential truncation attack. See http://crbug.com/18586. | 753 // uncleanly, a potential truncation attack. See http://crbug.com/18586. |
| 731 return OK; | 754 return OK; |
| 732 } | 755 } |
| 733 | 756 |
| 734 if (status == errSSLWouldBlock) | |
| 735 next_state_ = STATE_PAYLOAD_READ; | |
| 736 | |
| 737 return NetErrorFromOSStatus(status); | 757 return NetErrorFromOSStatus(status); |
| 738 } | 758 } |
| 739 | 759 |
| 740 int SSLClientSocketMac::DoPayloadWrite() { | 760 int SSLClientSocketMac::DoPayloadWrite() { |
| 741 size_t processed = 0; | 761 size_t processed = 0; |
| 742 OSStatus status = SSLWrite(ssl_context_, | 762 OSStatus status = SSLWrite(ssl_context_, |
| 743 user_buf_->data(), | 763 user_write_buf_->data(), |
| 744 user_buf_len_, | 764 user_write_buf_len_, |
| 745 &processed); | 765 &processed); |
| 746 | 766 |
| 747 if (processed > 0) | 767 if (processed > 0) |
| 748 return processed; | 768 return processed; |
| 749 | 769 |
| 750 return NetErrorFromOSStatus(status); | 770 return NetErrorFromOSStatus(status); |
| 751 } | 771 } |
| 752 | 772 |
| 753 // Handling the reading from the network is one of those things that should be | 773 // Handling the reading from the network is one of those things that should be |
| 754 // simpler than it is. Ideally, we'd have some kind of ring buffer. For now, a | 774 // simpler than it is. Ideally, we'd have some kind of ring buffer. For now, a |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 776 // extra space at the end as "tail slop." Slop is just space at the ends of the | 796 // extra space at the end as "tail slop." Slop is just space at the ends of the |
| 777 // buffer that's going to be used for data but isn't (yet). A diagram: | 797 // buffer that's going to be used for data but isn't (yet). A diagram: |
| 778 // | 798 // |
| 779 // +--------------------------------------+--------------------------------+ | 799 // +--------------------------------------+--------------------------------+ |
| 780 // | existing good data ~~~~~~~~~~~~~~~~~ | tail slop area ~~~~~~~~~~~~~~~ | | 800 // | existing good data ~~~~~~~~~~~~~~~~~ | tail slop area ~~~~~~~~~~~~~~~ | |
| 781 // +--------------------------------------+--------------------------------+ | 801 // +--------------------------------------+--------------------------------+ |
| 782 // | 802 // |
| 783 // When executing a read, we pass a pointer to the beginning of the tail slop | 803 // When executing a read, we pass a pointer to the beginning of the tail slop |
| 784 // area (guaranteed to be contiguous space because it's a vector, unlike, say, a | 804 // area (guaranteed to be contiguous space because it's a vector, unlike, say, a |
| 785 // deque (sigh)) and the size of the tail slop. When we get data (either here in | 805 // deque (sigh)) and the size of the tail slop. When we get data (either here in |
| 786 // SSLReadCallback() or above in DoReadComplete()) we subtract the number of | 806 // SSLReadCallback() or above in OnTransportReadComplete()) we subtract the |
| 787 // bytes received from the tail slop value. That moves those bytes | 807 // number of bytes received from the tail slop value. That moves those bytes |
| 788 // (conceptually, not physically) from the tail slop area to the area containing | 808 // (conceptually, not physically) from the tail slop area to the area containing |
| 789 // real data. | 809 // real data. |
| 790 // | 810 // |
| 791 // The idea is still pretty simple. We enlarge the tail slop, call our | 811 // The idea is still pretty simple. We enlarge the tail slop, call our |
| 792 // underlying network, get data, shrink the slop area to match, copy requested | 812 // underlying network, get data, shrink the slop area to match, copy requested |
| 793 // data back into our caller's buffer, and delete the data from the head of the | 813 // data back into our caller's buffer, and delete the data from the head of the |
| 794 // vector. | 814 // vector. |
| 795 // | 815 // |
| 796 // Except for a nasty little problem. Asynchronous I/O calls keep the buffer | 816 // Except for a nasty little problem. Asynchronous I/O calls keep the buffer |
| 797 // pointer. | 817 // pointer. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 827 size_t* data_length) { | 847 size_t* data_length) { |
| 828 DCHECK(data); | 848 DCHECK(data); |
| 829 DCHECK(data_length); | 849 DCHECK(data_length); |
| 830 SSLClientSocketMac* us = | 850 SSLClientSocketMac* us = |
| 831 const_cast<SSLClientSocketMac*>( | 851 const_cast<SSLClientSocketMac*>( |
| 832 static_cast<const SSLClientSocketMac*>(connection)); | 852 static_cast<const SSLClientSocketMac*>(connection)); |
| 833 | 853 |
| 834 // If we have I/O in flight, promise we'll get back to them and use the | 854 // If we have I/O in flight, promise we'll get back to them and use the |
| 835 // existing callback to do so | 855 // existing callback to do so |
| 836 | 856 |
| 837 if (us->next_io_state_ == STATE_READ_COMPLETE) { | 857 if (us->read_io_buf_) { |
| 838 *data_length = 0; | 858 *data_length = 0; |
| 839 return errSSLWouldBlock; | 859 return errSSLWouldBlock; |
| 840 } | 860 } |
| 841 | 861 |
| 842 // Start with what's in the buffer | 862 // Start with what's in the buffer |
| 843 | 863 |
| 844 size_t total_read = us->recv_buffer_.size() - us->recv_buffer_head_slop_ - | 864 size_t total_read = us->recv_buffer_.size() - us->recv_buffer_head_slop_ - |
| 845 us->recv_buffer_tail_slop_; | 865 us->recv_buffer_tail_slop_; |
| 846 | 866 |
| 847 // Resize the buffer if needed | 867 // Resize the buffer if needed |
| 848 | 868 |
| 849 if (us->recv_buffer_.size() - us->recv_buffer_head_slop_ < *data_length) { | 869 if (us->recv_buffer_.size() - us->recv_buffer_head_slop_ < *data_length) { |
| 850 us->recv_buffer_.resize(us->recv_buffer_head_slop_ + *data_length); | 870 us->recv_buffer_.resize(us->recv_buffer_head_slop_ + *data_length); |
| 851 us->recv_buffer_tail_slop_ = *data_length - total_read; | 871 us->recv_buffer_tail_slop_ = *data_length - total_read; |
| 852 } | 872 } |
| 853 | 873 |
| 854 int rv = 1; // any old value to spin the loop below | 874 int rv = 1; // any old value to spin the loop below |
| 855 while (rv > 0 && total_read < *data_length) { | 875 while (rv > 0 && total_read < *data_length) { |
| 856 char* buffer = &us->recv_buffer_[us->recv_buffer_head_slop_ + total_read]; | 876 char* buffer = &us->recv_buffer_[us->recv_buffer_head_slop_ + total_read]; |
| 857 us->read_io_buf_ = new IOBuffer(*data_length - total_read); | 877 us->read_io_buf_ = new IOBuffer(*data_length - total_read); |
| 858 rv = us->transport_->Read(us->read_io_buf_, | 878 rv = us->transport_->Read(us->read_io_buf_, |
| 859 *data_length - total_read, | 879 *data_length - total_read, |
| 860 &us->io_callback_); | 880 &us->transport_read_callback_); |
| 861 | 881 |
| 862 if (rv >= 0) { | 882 if (rv >= 0) { |
| 863 memcpy(buffer, us->read_io_buf_->data(), rv); | 883 memcpy(buffer, us->read_io_buf_->data(), rv); |
| 864 us->read_io_buf_ = NULL; | 884 us->read_io_buf_ = NULL; |
| 865 total_read += rv; | 885 total_read += rv; |
| 866 us->recv_buffer_tail_slop_ -= rv; | 886 us->recv_buffer_tail_slop_ -= rv; |
| 867 } | 887 } |
| 868 } | 888 } |
| 869 | 889 |
| 870 *data_length = total_read; | 890 *data_length = total_read; |
| 871 if (total_read) { | 891 if (total_read) { |
| 872 memcpy(data, &us->recv_buffer_[us->recv_buffer_head_slop_], total_read); | 892 memcpy(data, &us->recv_buffer_[us->recv_buffer_head_slop_], total_read); |
| 873 if (rv == ERR_IO_PENDING) { | 893 if (rv == ERR_IO_PENDING) { |
| 874 // We have I/O in flight which is going to land in our buffer. We can't | 894 // We have I/O in flight which is going to land in our buffer. We can't |
| 875 // shuffle things around, so we need to just fiddle with pointers. | 895 // shuffle things around, so we need to just fiddle with pointers. |
| 876 us->recv_buffer_head_slop_ += total_read; | 896 us->recv_buffer_head_slop_ += total_read; |
| 877 } else { | 897 } else { |
| 878 us->recv_buffer_.erase(us->recv_buffer_.begin(), | 898 us->recv_buffer_.erase(us->recv_buffer_.begin(), |
| 879 us->recv_buffer_.begin() + | 899 us->recv_buffer_.begin() + |
| 880 total_read + | 900 total_read + |
| 881 us->recv_buffer_head_slop_); | 901 us->recv_buffer_head_slop_); |
| 882 us->recv_buffer_head_slop_ = 0; | 902 us->recv_buffer_head_slop_ = 0; |
| 883 } | 903 } |
| 884 } | 904 } |
| 885 | 905 |
| 886 if (rv == ERR_IO_PENDING) { | 906 if (rv != ERR_IO_PENDING) |
| 887 us->next_io_state_ = STATE_READ_COMPLETE; | |
| 888 } else { | |
| 889 us->read_io_buf_ = NULL; | 907 us->read_io_buf_ = NULL; |
| 890 } | |
| 891 | 908 |
| 892 if (rv < 0) | 909 if (rv < 0) |
| 893 return OSStatusFromNetError(rv); | 910 return OSStatusFromNetError(rv); |
| 894 else if (rv == 0) // stream closed | 911 else if (rv == 0) // stream closed |
| 895 return errSSLClosedGraceful; | 912 return errSSLClosedGraceful; |
| 896 else | 913 else |
| 897 return noErr; | 914 return noErr; |
| 898 } | 915 } |
| 899 | 916 |
| 900 // static | 917 // static |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 925 // sent data. As always, lie to our caller. | 942 // sent data. As always, lie to our caller. |
| 926 return noErr; | 943 return noErr; |
| 927 } | 944 } |
| 928 | 945 |
| 929 int rv; | 946 int rv; |
| 930 do { | 947 do { |
| 931 scoped_refptr<IOBuffer> buffer = new IOBuffer(us->send_buffer_.size()); | 948 scoped_refptr<IOBuffer> buffer = new IOBuffer(us->send_buffer_.size()); |
| 932 memcpy(buffer->data(), &us->send_buffer_[0], us->send_buffer_.size()); | 949 memcpy(buffer->data(), &us->send_buffer_[0], us->send_buffer_.size()); |
| 933 rv = us->transport_->Write(buffer, | 950 rv = us->transport_->Write(buffer, |
| 934 us->send_buffer_.size(), | 951 us->send_buffer_.size(), |
| 935 &us->write_callback_); | 952 &us->transport_write_callback_); |
| 936 if (rv > 0) { | 953 if (rv > 0) { |
| 937 us->send_buffer_.erase(us->send_buffer_.begin(), | 954 us->send_buffer_.erase(us->send_buffer_.begin(), |
| 938 us->send_buffer_.begin() + rv); | 955 us->send_buffer_.begin() + rv); |
| 939 } | 956 } |
| 940 } while (rv > 0 && !us->send_buffer_.empty()); | 957 } while (rv > 0 && !us->send_buffer_.empty()); |
| 941 | 958 |
| 942 if (rv < 0 && rv != ERR_IO_PENDING) { | 959 if (rv < 0 && rv != ERR_IO_PENDING) { |
| 943 return OSStatusFromNetError(rv); | 960 return OSStatusFromNetError(rv); |
| 944 } | 961 } |
| 945 | 962 |
| 946 // always lie to our caller | 963 // always lie to our caller |
| 947 return noErr; | 964 return noErr; |
| 948 } | 965 } |
| 949 | 966 |
| 950 } // namespace net | 967 } // namespace net |
| OLD | NEW |