| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_win.h" | 5 #include "net/socket/ssl_client_socket_win.h" |
| 6 | 6 |
| 7 #include <schnlsp.h> | 7 #include <schnlsp.h> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/lock.h" | 10 #include "base/lock.h" |
| 11 #include "base/singleton.h" | 11 #include "base/singleton.h" |
| 12 #include "base/stl_util-inl.h" | 12 #include "base/stl_util-inl.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "net/base/cert_verifier.h" | 14 #include "net/base/cert_verifier.h" |
| 15 #include "net/base/connection_type_histograms.h" | 15 #include "net/base/connection_type_histograms.h" |
| 16 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
| 17 #include "net/base/net_log.h" | 17 #include "net/base/net_log.h" |
| 18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 19 #include "net/base/ssl_cert_request_info.h" | 19 #include "net/base/ssl_cert_request_info.h" |
| 20 #include "net/base/ssl_info.h" | 20 #include "net/base/ssl_info.h" |
| 21 #include "net/socket/client_socket_handle.h" |
| 21 | 22 |
| 22 #pragma comment(lib, "secur32.lib") | 23 #pragma comment(lib, "secur32.lib") |
| 23 | 24 |
| 24 namespace net { | 25 namespace net { |
| 25 | 26 |
| 26 //----------------------------------------------------------------------------- | 27 //----------------------------------------------------------------------------- |
| 27 | 28 |
| 28 // TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx | 29 // TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx |
| 29 // for the other error codes we may need to map. | 30 // for the other error codes we may need to map. |
| 30 static int MapSecurityError(SECURITY_STATUS err) { | 31 static int MapSecurityError(SECURITY_STATUS err) { |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 // Size of recv_buffer_ | 286 // Size of recv_buffer_ |
| 286 // | 287 // |
| 287 // Ciphertext is decrypted one SSL record at a time, so recv_buffer_ needs to | 288 // Ciphertext is decrypted one SSL record at a time, so recv_buffer_ needs to |
| 288 // have room for a full SSL record, with the header and trailer. Here is the | 289 // have room for a full SSL record, with the header and trailer. Here is the |
| 289 // breakdown of the size: | 290 // breakdown of the size: |
| 290 // 5: SSL record header | 291 // 5: SSL record header |
| 291 // 16K: SSL record maximum size | 292 // 16K: SSL record maximum size |
| 292 // 64: >= SSL record trailer (16 or 20 have been observed) | 293 // 64: >= SSL record trailer (16 or 20 have been observed) |
| 293 static const int kRecvBufferSize = (5 + 16*1024 + 64); | 294 static const int kRecvBufferSize = (5 + 16*1024 + 64); |
| 294 | 295 |
| 295 SSLClientSocketWin::SSLClientSocketWin(ClientSocket* transport_socket, | 296 SSLClientSocketWin::SSLClientSocketWin(ClientSocketHandle* transport_socket, |
| 296 const std::string& hostname, | 297 const std::string& hostname, |
| 297 const SSLConfig& ssl_config) | 298 const SSLConfig& ssl_config) |
| 298 : ALLOW_THIS_IN_INITIALIZER_LIST( | 299 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 299 handshake_io_callback_(this, | 300 handshake_io_callback_(this, |
| 300 &SSLClientSocketWin::OnHandshakeIOComplete)), | 301 &SSLClientSocketWin::OnHandshakeIOComplete)), |
| 301 ALLOW_THIS_IN_INITIALIZER_LIST( | 302 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 302 read_callback_(this, &SSLClientSocketWin::OnReadComplete)), | 303 read_callback_(this, &SSLClientSocketWin::OnReadComplete)), |
| 303 ALLOW_THIS_IN_INITIALIZER_LIST( | 304 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 304 write_callback_(this, &SSLClientSocketWin::OnWriteComplete)), | 305 write_callback_(this, &SSLClientSocketWin::OnWriteComplete)), |
| 305 transport_(transport_socket), | 306 transport_(transport_socket), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 316 payload_send_buffer_len_(0), | 317 payload_send_buffer_len_(0), |
| 317 bytes_sent_(0), | 318 bytes_sent_(0), |
| 318 decrypted_ptr_(NULL), | 319 decrypted_ptr_(NULL), |
| 319 bytes_decrypted_(0), | 320 bytes_decrypted_(0), |
| 320 received_ptr_(NULL), | 321 received_ptr_(NULL), |
| 321 bytes_received_(0), | 322 bytes_received_(0), |
| 322 writing_first_token_(false), | 323 writing_first_token_(false), |
| 323 ignore_ok_result_(false), | 324 ignore_ok_result_(false), |
| 324 renegotiating_(false), | 325 renegotiating_(false), |
| 325 need_more_data_(false), | 326 need_more_data_(false), |
| 326 net_log_(transport_socket->NetLog()) { | 327 net_log_(transport_socket->socket()->NetLog()) { |
| 327 memset(&stream_sizes_, 0, sizeof(stream_sizes_)); | 328 memset(&stream_sizes_, 0, sizeof(stream_sizes_)); |
| 328 memset(in_buffers_, 0, sizeof(in_buffers_)); | 329 memset(in_buffers_, 0, sizeof(in_buffers_)); |
| 329 memset(&send_buffer_, 0, sizeof(send_buffer_)); | 330 memset(&send_buffer_, 0, sizeof(send_buffer_)); |
| 330 memset(&ctxt_, 0, sizeof(ctxt_)); | 331 memset(&ctxt_, 0, sizeof(ctxt_)); |
| 331 } | 332 } |
| 332 | 333 |
| 333 SSLClientSocketWin::~SSLClientSocketWin() { | 334 SSLClientSocketWin::~SSLClientSocketWin() { |
| 334 Disconnect(); | 335 Disconnect(); |
| 335 } | 336 } |
| 336 | 337 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 return OK; | 517 return OK; |
| 517 } | 518 } |
| 518 | 519 |
| 519 | 520 |
| 520 void SSLClientSocketWin::Disconnect() { | 521 void SSLClientSocketWin::Disconnect() { |
| 521 // TODO(wtc): Send SSL close_notify alert. | 522 // TODO(wtc): Send SSL close_notify alert. |
| 522 next_state_ = STATE_NONE; | 523 next_state_ = STATE_NONE; |
| 523 | 524 |
| 524 // Shut down anything that may call us back. | 525 // Shut down anything that may call us back. |
| 525 verifier_.reset(); | 526 verifier_.reset(); |
| 526 transport_->Disconnect(); | 527 transport_->socket()->Disconnect(); |
| 527 | 528 |
| 528 if (send_buffer_.pvBuffer) | 529 if (send_buffer_.pvBuffer) |
| 529 FreeSendBuffer(); | 530 FreeSendBuffer(); |
| 530 if (ctxt_.dwLower || ctxt_.dwUpper) { | 531 if (ctxt_.dwLower || ctxt_.dwUpper) { |
| 531 DeleteSecurityContext(&ctxt_); | 532 DeleteSecurityContext(&ctxt_); |
| 532 memset(&ctxt_, 0, sizeof(ctxt_)); | 533 memset(&ctxt_, 0, sizeof(ctxt_)); |
| 533 } | 534 } |
| 534 if (server_cert_) | 535 if (server_cert_) |
| 535 server_cert_ = NULL; | 536 server_cert_ = NULL; |
| 536 | 537 |
| 537 // TODO(wtc): reset more members? | 538 // TODO(wtc): reset more members? |
| 538 bytes_decrypted_ = 0; | 539 bytes_decrypted_ = 0; |
| 539 bytes_received_ = 0; | 540 bytes_received_ = 0; |
| 540 writing_first_token_ = false; | 541 writing_first_token_ = false; |
| 541 renegotiating_ = false; | 542 renegotiating_ = false; |
| 542 need_more_data_ = false; | 543 need_more_data_ = false; |
| 543 } | 544 } |
| 544 | 545 |
| 545 bool SSLClientSocketWin::IsConnected() const { | 546 bool SSLClientSocketWin::IsConnected() const { |
| 546 // Ideally, we should also check if we have received the close_notify alert | 547 // Ideally, we should also check if we have received the close_notify alert |
| 547 // message from the server, and return false in that case. We're not doing | 548 // message from the server, and return false in that case. We're not doing |
| 548 // that, so this function may return a false positive. Since the upper | 549 // that, so this function may return a false positive. Since the upper |
| 549 // layer (HttpNetworkTransaction) needs to handle a persistent connection | 550 // layer (HttpNetworkTransaction) needs to handle a persistent connection |
| 550 // closed by the server when we send a request anyway, a false positive in | 551 // closed by the server when we send a request anyway, a false positive in |
| 551 // exchange for simpler code is a good trade-off. | 552 // exchange for simpler code is a good trade-off. |
| 552 return completed_handshake() && transport_->IsConnected(); | 553 return completed_handshake() && transport_->socket()->IsConnected(); |
| 553 } | 554 } |
| 554 | 555 |
| 555 bool SSLClientSocketWin::IsConnectedAndIdle() const { | 556 bool SSLClientSocketWin::IsConnectedAndIdle() const { |
| 556 // Unlike IsConnected, this method doesn't return a false positive. | 557 // Unlike IsConnected, this method doesn't return a false positive. |
| 557 // | 558 // |
| 558 // Strictly speaking, we should check if we have received the close_notify | 559 // Strictly speaking, we should check if we have received the close_notify |
| 559 // alert message from the server, and return false in that case. Although | 560 // alert message from the server, and return false in that case. Although |
| 560 // the close_notify alert message means EOF in the SSL layer, it is just | 561 // the close_notify alert message means EOF in the SSL layer, it is just |
| 561 // bytes to the transport layer below, so transport_->IsConnectedAndIdle() | 562 // bytes to the transport layer below, so |
| 562 // returns the desired false when we receive close_notify. | 563 // transport_->socket()->IsConnectedAndIdle() returns the desired false |
| 563 return completed_handshake() && transport_->IsConnectedAndIdle(); | 564 // when we receive close_notify. |
| 565 return completed_handshake() && transport_->socket()->IsConnectedAndIdle(); |
| 564 } | 566 } |
| 565 | 567 |
| 566 int SSLClientSocketWin::GetPeerAddress(AddressList* address) const { | 568 int SSLClientSocketWin::GetPeerAddress(AddressList* address) const { |
| 567 return transport_->GetPeerAddress(address); | 569 return transport_->socket()->GetPeerAddress(address); |
| 568 } | 570 } |
| 569 | 571 |
| 570 int SSLClientSocketWin::Read(IOBuffer* buf, int buf_len, | 572 int SSLClientSocketWin::Read(IOBuffer* buf, int buf_len, |
| 571 CompletionCallback* callback) { | 573 CompletionCallback* callback) { |
| 572 DCHECK(completed_handshake()); | 574 DCHECK(completed_handshake()); |
| 573 DCHECK(!user_read_callback_); | 575 DCHECK(!user_read_callback_); |
| 574 | 576 |
| 575 // If we have surplus decrypted plaintext, satisfy the Read with it without | 577 // If we have surplus decrypted plaintext, satisfy the Read with it without |
| 576 // reading more ciphertext from the transport socket. | 578 // reading more ciphertext from the transport socket. |
| 577 if (bytes_decrypted_ != 0) { | 579 if (bytes_decrypted_ != 0) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 if (rv == ERR_IO_PENDING) { | 626 if (rv == ERR_IO_PENDING) { |
| 625 user_write_callback_ = callback; | 627 user_write_callback_ = callback; |
| 626 } else { | 628 } else { |
| 627 user_write_buf_ = NULL; | 629 user_write_buf_ = NULL; |
| 628 user_write_buf_len_ = 0; | 630 user_write_buf_len_ = 0; |
| 629 } | 631 } |
| 630 return rv; | 632 return rv; |
| 631 } | 633 } |
| 632 | 634 |
| 633 bool SSLClientSocketWin::SetReceiveBufferSize(int32 size) { | 635 bool SSLClientSocketWin::SetReceiveBufferSize(int32 size) { |
| 634 return transport_->SetReceiveBufferSize(size); | 636 return transport_->socket()->SetReceiveBufferSize(size); |
| 635 } | 637 } |
| 636 | 638 |
| 637 bool SSLClientSocketWin::SetSendBufferSize(int32 size) { | 639 bool SSLClientSocketWin::SetSendBufferSize(int32 size) { |
| 638 return transport_->SetSendBufferSize(size); | 640 return transport_->socket()->SetSendBufferSize(size); |
| 639 } | 641 } |
| 640 | 642 |
| 641 void SSLClientSocketWin::OnHandshakeIOComplete(int result) { | 643 void SSLClientSocketWin::OnHandshakeIOComplete(int result) { |
| 642 int rv = DoLoop(result); | 644 int rv = DoLoop(result); |
| 643 | 645 |
| 644 // The SSL handshake has some round trips. We need to notify the caller of | 646 // The SSL handshake has some round trips. We need to notify the caller of |
| 645 // success or any error, other than waiting for IO. | 647 // success or any error, other than waiting for IO. |
| 646 if (rv != ERR_IO_PENDING) { | 648 if (rv != ERR_IO_PENDING) { |
| 647 // If there is no connect callback available to call, we are renegotiating | 649 // If there is no connect callback available to call, we are renegotiating |
| 648 // (which occurs because we are in the middle of a Read when the | 650 // (which occurs because we are in the middle of a Read when the |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 int buf_len = kRecvBufferSize - bytes_received_; | 745 int buf_len = kRecvBufferSize - bytes_received_; |
| 744 | 746 |
| 745 if (buf_len <= 0) { | 747 if (buf_len <= 0) { |
| 746 NOTREACHED() << "Receive buffer is too small!"; | 748 NOTREACHED() << "Receive buffer is too small!"; |
| 747 return ERR_UNEXPECTED; | 749 return ERR_UNEXPECTED; |
| 748 } | 750 } |
| 749 | 751 |
| 750 DCHECK(!transport_read_buf_); | 752 DCHECK(!transport_read_buf_); |
| 751 transport_read_buf_ = new IOBuffer(buf_len); | 753 transport_read_buf_ = new IOBuffer(buf_len); |
| 752 | 754 |
| 753 return transport_->Read(transport_read_buf_, buf_len, | 755 return transport_->socket()->Read(transport_read_buf_, buf_len, |
| 754 &handshake_io_callback_); | 756 &handshake_io_callback_); |
| 755 } | 757 } |
| 756 | 758 |
| 757 int SSLClientSocketWin::DoHandshakeReadComplete(int result) { | 759 int SSLClientSocketWin::DoHandshakeReadComplete(int result) { |
| 758 if (result < 0) { | 760 if (result < 0) { |
| 759 transport_read_buf_ = NULL; | 761 transport_read_buf_ = NULL; |
| 760 return result; | 762 return result; |
| 761 } | 763 } |
| 762 | 764 |
| 763 if (transport_read_buf_) { | 765 if (transport_read_buf_) { |
| 764 // A transition to STATE_HANDSHAKE_READ_COMPLETE is set in multiple places, | 766 // A transition to STATE_HANDSHAKE_READ_COMPLETE is set in multiple places, |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 // We should have something to send. | 912 // We should have something to send. |
| 911 DCHECK(send_buffer_.pvBuffer); | 913 DCHECK(send_buffer_.pvBuffer); |
| 912 DCHECK(send_buffer_.cbBuffer > 0); | 914 DCHECK(send_buffer_.cbBuffer > 0); |
| 913 DCHECK(!transport_write_buf_); | 915 DCHECK(!transport_write_buf_); |
| 914 | 916 |
| 915 const char* buf = static_cast<char*>(send_buffer_.pvBuffer) + bytes_sent_; | 917 const char* buf = static_cast<char*>(send_buffer_.pvBuffer) + bytes_sent_; |
| 916 int buf_len = send_buffer_.cbBuffer - bytes_sent_; | 918 int buf_len = send_buffer_.cbBuffer - bytes_sent_; |
| 917 transport_write_buf_ = new IOBuffer(buf_len); | 919 transport_write_buf_ = new IOBuffer(buf_len); |
| 918 memcpy(transport_write_buf_->data(), buf, buf_len); | 920 memcpy(transport_write_buf_->data(), buf, buf_len); |
| 919 | 921 |
| 920 return transport_->Write(transport_write_buf_, buf_len, | 922 return transport_->socket()->Write(transport_write_buf_, buf_len, |
| 921 &handshake_io_callback_); | 923 &handshake_io_callback_); |
| 922 } | 924 } |
| 923 | 925 |
| 924 int SSLClientSocketWin::DoHandshakeWriteComplete(int result) { | 926 int SSLClientSocketWin::DoHandshakeWriteComplete(int result) { |
| 925 DCHECK(transport_write_buf_); | 927 DCHECK(transport_write_buf_); |
| 926 transport_write_buf_ = NULL; | 928 transport_write_buf_ = NULL; |
| 927 if (result < 0) | 929 if (result < 0) |
| 928 return result; | 930 return result; |
| 929 | 931 |
| 930 DCHECK(result != 0); | 932 DCHECK(result != 0); |
| 931 | 933 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 return ERR_FAILED; | 1007 return ERR_FAILED; |
| 1006 } | 1008 } |
| 1007 | 1009 |
| 1008 int rv; | 1010 int rv; |
| 1009 // If bytes_received_, we have some data from a previous read still ready | 1011 // If bytes_received_, we have some data from a previous read still ready |
| 1010 // for decoding. Otherwise, we need to issue a real read. | 1012 // for decoding. Otherwise, we need to issue a real read. |
| 1011 if (!bytes_received_ || need_more_data_) { | 1013 if (!bytes_received_ || need_more_data_) { |
| 1012 DCHECK(!transport_read_buf_); | 1014 DCHECK(!transport_read_buf_); |
| 1013 transport_read_buf_ = new IOBuffer(buf_len); | 1015 transport_read_buf_ = new IOBuffer(buf_len); |
| 1014 | 1016 |
| 1015 rv = transport_->Read(transport_read_buf_, buf_len, &read_callback_); | 1017 rv = transport_->socket()->Read(transport_read_buf_, buf_len, |
| 1018 &read_callback_); |
| 1016 if (rv != ERR_IO_PENDING) | 1019 if (rv != ERR_IO_PENDING) |
| 1017 rv = DoPayloadReadComplete(rv); | 1020 rv = DoPayloadReadComplete(rv); |
| 1018 if (rv <= 0) | 1021 if (rv <= 0) |
| 1019 return rv; | 1022 return rv; |
| 1020 } | 1023 } |
| 1021 | 1024 |
| 1022 // Decode what we've read. If there is not enough data to decode yet, | 1025 // Decode what we've read. If there is not enough data to decode yet, |
| 1023 // this may return ERR_IO_PENDING still. | 1026 // this may return ERR_IO_PENDING still. |
| 1024 return DoPayloadDecrypt(); | 1027 return DoPayloadDecrypt(); |
| 1025 } | 1028 } |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 // We should have something to send. | 1243 // We should have something to send. |
| 1241 DCHECK(payload_send_buffer_.get()); | 1244 DCHECK(payload_send_buffer_.get()); |
| 1242 DCHECK(payload_send_buffer_len_ > 0); | 1245 DCHECK(payload_send_buffer_len_ > 0); |
| 1243 DCHECK(!transport_write_buf_); | 1246 DCHECK(!transport_write_buf_); |
| 1244 | 1247 |
| 1245 const char* buf = payload_send_buffer_.get() + bytes_sent_; | 1248 const char* buf = payload_send_buffer_.get() + bytes_sent_; |
| 1246 int buf_len = payload_send_buffer_len_ - bytes_sent_; | 1249 int buf_len = payload_send_buffer_len_ - bytes_sent_; |
| 1247 transport_write_buf_ = new IOBuffer(buf_len); | 1250 transport_write_buf_ = new IOBuffer(buf_len); |
| 1248 memcpy(transport_write_buf_->data(), buf, buf_len); | 1251 memcpy(transport_write_buf_->data(), buf, buf_len); |
| 1249 | 1252 |
| 1250 int rv = transport_->Write(transport_write_buf_, buf_len, &write_callback_); | 1253 int rv = transport_->socket()->Write(transport_write_buf_, buf_len, |
| 1254 &write_callback_); |
| 1251 if (rv != ERR_IO_PENDING) | 1255 if (rv != ERR_IO_PENDING) |
| 1252 rv = DoPayloadWriteComplete(rv); | 1256 rv = DoPayloadWriteComplete(rv); |
| 1253 return rv; | 1257 return rv; |
| 1254 } | 1258 } |
| 1255 | 1259 |
| 1256 int SSLClientSocketWin::DoPayloadWriteComplete(int result) { | 1260 int SSLClientSocketWin::DoPayloadWriteComplete(int result) { |
| 1257 DCHECK(transport_write_buf_); | 1261 DCHECK(transport_write_buf_); |
| 1258 transport_write_buf_ = NULL; | 1262 transport_write_buf_ = NULL; |
| 1259 if (result < 0) | 1263 if (result < 0) |
| 1260 return result; | 1264 return result; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); | 1347 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); |
| 1344 } | 1348 } |
| 1345 | 1349 |
| 1346 void SSLClientSocketWin::FreeSendBuffer() { | 1350 void SSLClientSocketWin::FreeSendBuffer() { |
| 1347 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); | 1351 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); |
| 1348 DCHECK(status == SEC_E_OK); | 1352 DCHECK(status == SEC_E_OK); |
| 1349 memset(&send_buffer_, 0, sizeof(send_buffer_)); | 1353 memset(&send_buffer_, 0, sizeof(send_buffer_)); |
| 1350 } | 1354 } |
| 1351 | 1355 |
| 1352 } // namespace net | 1356 } // namespace net |
| OLD | NEW |