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 |