| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/base/ssl_client_socket_win.h" | 5 #include "net/base/ssl_client_socket_win.h" |
| 6 | 6 |
| 7 #include <schnlsp.h> | 7 #include <schnlsp.h> |
| 8 | 8 |
| 9 #include "base/lock.h" | 9 #include "base/lock.h" |
| 10 #include "base/singleton.h" | 10 #include "base/singleton.h" |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 #pragma warning(suppress: 4355) | 209 #pragma warning(suppress: 4355) |
| 210 : io_callback_(this, &SSLClientSocketWin::OnIOComplete), | 210 : io_callback_(this, &SSLClientSocketWin::OnIOComplete), |
| 211 transport_(transport_socket), | 211 transport_(transport_socket), |
| 212 hostname_(hostname), | 212 hostname_(hostname), |
| 213 ssl_config_(ssl_config), | 213 ssl_config_(ssl_config), |
| 214 user_callback_(NULL), | 214 user_callback_(NULL), |
| 215 user_buf_(NULL), | 215 user_buf_(NULL), |
| 216 user_buf_len_(0), | 216 user_buf_len_(0), |
| 217 next_state_(STATE_NONE), | 217 next_state_(STATE_NONE), |
| 218 creds_(NULL), | 218 creds_(NULL), |
| 219 isc_status_(SEC_E_OK), |
| 219 payload_send_buffer_len_(0), | 220 payload_send_buffer_len_(0), |
| 220 bytes_sent_(0), | 221 bytes_sent_(0), |
| 221 decrypted_ptr_(NULL), | 222 decrypted_ptr_(NULL), |
| 222 bytes_decrypted_(0), | 223 bytes_decrypted_(0), |
| 223 received_ptr_(NULL), | 224 received_ptr_(NULL), |
| 224 bytes_received_(0), | 225 bytes_received_(0), |
| 226 writing_first_token_(false), |
| 225 completed_handshake_(false), | 227 completed_handshake_(false), |
| 226 complete_handshake_on_write_complete_(false), | |
| 227 ignore_ok_result_(false), | 228 ignore_ok_result_(false), |
| 228 no_client_cert_(false) { | 229 no_client_cert_(false), |
| 230 renegotiating_(false) { |
| 229 memset(&stream_sizes_, 0, sizeof(stream_sizes_)); | 231 memset(&stream_sizes_, 0, sizeof(stream_sizes_)); |
| 232 memset(in_buffers_, 0, sizeof(in_buffers_)); |
| 230 memset(&send_buffer_, 0, sizeof(send_buffer_)); | 233 memset(&send_buffer_, 0, sizeof(send_buffer_)); |
| 231 memset(&ctxt_, 0, sizeof(ctxt_)); | 234 memset(&ctxt_, 0, sizeof(ctxt_)); |
| 232 } | 235 } |
| 233 | 236 |
| 234 SSLClientSocketWin::~SSLClientSocketWin() { | 237 SSLClientSocketWin::~SSLClientSocketWin() { |
| 235 Disconnect(); | 238 Disconnect(); |
| 236 } | 239 } |
| 237 | 240 |
| 238 void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { | 241 void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { |
| 239 if (!server_cert_) | 242 if (!server_cert_) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 CompletionCallback* callback) { | 284 CompletionCallback* callback) { |
| 282 // TODO(darin): implement me! | 285 // TODO(darin): implement me! |
| 283 return ERR_FAILED; | 286 return ERR_FAILED; |
| 284 } | 287 } |
| 285 | 288 |
| 286 void SSLClientSocketWin::Disconnect() { | 289 void SSLClientSocketWin::Disconnect() { |
| 287 // TODO(wtc): Send SSL close_notify alert. | 290 // TODO(wtc): Send SSL close_notify alert. |
| 288 completed_handshake_ = false; | 291 completed_handshake_ = false; |
| 289 transport_->Disconnect(); | 292 transport_->Disconnect(); |
| 290 | 293 |
| 291 if (send_buffer_.pvBuffer) { | 294 if (send_buffer_.pvBuffer) |
| 292 FreeContextBuffer(send_buffer_.pvBuffer); | 295 FreeSendBuffer(); |
| 293 memset(&send_buffer_, 0, sizeof(send_buffer_)); | |
| 294 } | |
| 295 if (ctxt_.dwLower || ctxt_.dwUpper) { | 296 if (ctxt_.dwLower || ctxt_.dwUpper) { |
| 296 DeleteSecurityContext(&ctxt_); | 297 DeleteSecurityContext(&ctxt_); |
| 297 memset(&ctxt_, 0, sizeof(ctxt_)); | 298 memset(&ctxt_, 0, sizeof(ctxt_)); |
| 298 } | 299 } |
| 299 if (server_cert_) | 300 if (server_cert_) |
| 300 server_cert_ = NULL; | 301 server_cert_ = NULL; |
| 301 | 302 |
| 302 // TODO(wtc): reset more members? | 303 // TODO(wtc): reset more members? |
| 303 bytes_decrypted_ = 0; | 304 bytes_decrypted_ = 0; |
| 304 bytes_received_ = 0; | 305 bytes_received_ = 0; |
| 306 writing_first_token_ = false; |
| 307 renegotiating_ = false; |
| 305 } | 308 } |
| 306 | 309 |
| 307 bool SSLClientSocketWin::IsConnected() const { | 310 bool SSLClientSocketWin::IsConnected() const { |
| 308 // Ideally, we should also check if we have received the close_notify alert | 311 // Ideally, we should also check if we have received the close_notify alert |
| 309 // message from the server, and return false in that case. We're not doing | 312 // message from the server, and return false in that case. We're not doing |
| 310 // that, so this function may return a false positive. Since the upper | 313 // that, so this function may return a false positive. Since the upper |
| 311 // layer (HttpNetworkTransaction) needs to handle a persistent connection | 314 // layer (HttpNetworkTransaction) needs to handle a persistent connection |
| 312 // closed by the server when we send a request anyway, a false positive in | 315 // closed by the server when we send a request anyway, a false positive in |
| 313 // exchange for simpler code is a good trade-off. | 316 // exchange for simpler code is a good trade-off. |
| 314 return completed_handshake_ && transport_->IsConnected(); | 317 return completed_handshake_ && transport_->IsConnected(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 344 memmove(recv_buffer_.get(), received_ptr_, bytes_received_); | 347 memmove(recv_buffer_.get(), received_ptr_, bytes_received_); |
| 345 received_ptr_ = recv_buffer_.get(); | 348 received_ptr_ = recv_buffer_.get(); |
| 346 } | 349 } |
| 347 } | 350 } |
| 348 return len; | 351 return len; |
| 349 } | 352 } |
| 350 | 353 |
| 351 user_buf_ = buf; | 354 user_buf_ = buf; |
| 352 user_buf_len_ = buf_len; | 355 user_buf_len_ = buf_len; |
| 353 | 356 |
| 354 if (bytes_received_ == 0) { | 357 SetNextStateForRead(); |
| 355 next_state_ = STATE_PAYLOAD_READ; | |
| 356 } else { | |
| 357 next_state_ = STATE_PAYLOAD_READ_COMPLETE; | |
| 358 ignore_ok_result_ = true; // OK doesn't mean EOF. | |
| 359 } | |
| 360 int rv = DoLoop(OK); | 358 int rv = DoLoop(OK); |
| 361 if (rv == ERR_IO_PENDING) | 359 if (rv == ERR_IO_PENDING) |
| 362 user_callback_ = callback; | 360 user_callback_ = callback; |
| 363 return rv; | 361 return rv; |
| 364 } | 362 } |
| 365 | 363 |
| 366 int SSLClientSocketWin::Write(const char* buf, int buf_len, | 364 int SSLClientSocketWin::Write(const char* buf, int buf_len, |
| 367 CompletionCallback* callback) { | 365 CompletionCallback* callback) { |
| 368 DCHECK(completed_handshake_); | 366 DCHECK(completed_handshake_); |
| 369 DCHECK(next_state_ == STATE_NONE); | 367 DCHECK(next_state_ == STATE_NONE); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 0, // Reserved | 490 0, // Reserved |
| 493 &ctxt_, // Receives the new context handle | 491 &ctxt_, // Receives the new context handle |
| 494 &buffer_desc, | 492 &buffer_desc, |
| 495 &out_flags, | 493 &out_flags, |
| 496 &expiry); | 494 &expiry); |
| 497 if (status != SEC_I_CONTINUE_NEEDED) { | 495 if (status != SEC_I_CONTINUE_NEEDED) { |
| 498 DLOG(ERROR) << "InitializeSecurityContext failed: " << status; | 496 DLOG(ERROR) << "InitializeSecurityContext failed: " << status; |
| 499 return MapSecurityError(status); | 497 return MapSecurityError(status); |
| 500 } | 498 } |
| 501 | 499 |
| 500 writing_first_token_ = true; |
| 502 next_state_ = STATE_HANDSHAKE_WRITE; | 501 next_state_ = STATE_HANDSHAKE_WRITE; |
| 503 return OK; | 502 return OK; |
| 504 } | 503 } |
| 505 | 504 |
| 506 int SSLClientSocketWin::DoHandshakeRead() { | 505 int SSLClientSocketWin::DoHandshakeRead() { |
| 507 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 506 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
| 508 | 507 |
| 509 if (!recv_buffer_.get()) | 508 if (!recv_buffer_.get()) |
| 510 recv_buffer_.reset(new char[kRecvBufferSize]); | 509 recv_buffer_.reset(new char[kRecvBufferSize]); |
| 511 | 510 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 524 if (result < 0) | 523 if (result < 0) |
| 525 return result; | 524 return result; |
| 526 if (result == 0 && !ignore_ok_result_) | 525 if (result == 0 && !ignore_ok_result_) |
| 527 return ERR_SSL_PROTOCOL_ERROR; // Incomplete response :( | 526 return ERR_SSL_PROTOCOL_ERROR; // Incomplete response :( |
| 528 | 527 |
| 529 ignore_ok_result_ = false; | 528 ignore_ok_result_ = false; |
| 530 | 529 |
| 531 bytes_received_ += result; | 530 bytes_received_ += result; |
| 532 | 531 |
| 533 // Process the contents of recv_buffer_. | 532 // Process the contents of recv_buffer_. |
| 534 SECURITY_STATUS status; | |
| 535 TimeStamp expiry; | 533 TimeStamp expiry; |
| 536 DWORD out_flags; | 534 DWORD out_flags; |
| 537 | 535 |
| 538 DWORD flags = ISC_REQ_SEQUENCE_DETECT | | 536 DWORD flags = ISC_REQ_SEQUENCE_DETECT | |
| 539 ISC_REQ_REPLAY_DETECT | | 537 ISC_REQ_REPLAY_DETECT | |
| 540 ISC_REQ_CONFIDENTIALITY | | 538 ISC_REQ_CONFIDENTIALITY | |
| 541 ISC_RET_EXTENDED_ERROR | | 539 ISC_RET_EXTENDED_ERROR | |
| 542 ISC_REQ_ALLOCATE_MEMORY | | 540 ISC_REQ_ALLOCATE_MEMORY | |
| 543 ISC_REQ_STREAM; | 541 ISC_REQ_STREAM; |
| 544 | 542 |
| 545 // When InitializeSecurityContext returns SEC_I_INCOMPLETE_CREDENTIALS, | 543 // When InitializeSecurityContext returns SEC_I_INCOMPLETE_CREDENTIALS, |
| 546 // John Banes (a Microsoft security developer) said we need to pass in the | 544 // John Banes (a Microsoft security developer) said we need to pass in the |
| 547 // ISC_REQ_USE_SUPPLIED_CREDS flag if we skip finding a client certificate | 545 // ISC_REQ_USE_SUPPLIED_CREDS flag if we skip finding a client certificate |
| 548 // and just call InitializeSecurityContext again. (See | 546 // and just call InitializeSecurityContext again. (See |
| 549 // (http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/
2004-08/0187.html.) | 547 // (http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/
2004-08/0187.html.) |
| 550 // My testing on XP SP2 and Vista SP1 shows that it still works without | 548 // My testing on XP SP2 and Vista SP1 shows that it still works without |
| 551 // passing in this flag, but I pass it in to be safe. | 549 // passing in this flag, but I pass it in to be safe. |
| 552 if (no_client_cert_) | 550 if (no_client_cert_) |
| 553 flags |= ISC_REQ_USE_SUPPLIED_CREDS; | 551 flags |= ISC_REQ_USE_SUPPLIED_CREDS; |
| 554 | 552 |
| 555 SecBufferDesc in_buffer_desc, out_buffer_desc; | 553 SecBufferDesc in_buffer_desc, out_buffer_desc; |
| 556 SecBuffer in_buffers[2]; | |
| 557 | 554 |
| 558 in_buffer_desc.cBuffers = 2; | 555 in_buffer_desc.cBuffers = 2; |
| 559 in_buffer_desc.pBuffers = in_buffers; | 556 in_buffer_desc.pBuffers = in_buffers_; |
| 560 in_buffer_desc.ulVersion = SECBUFFER_VERSION; | 557 in_buffer_desc.ulVersion = SECBUFFER_VERSION; |
| 561 | 558 |
| 562 in_buffers[0].pvBuffer = &recv_buffer_[0]; | 559 in_buffers_[0].pvBuffer = recv_buffer_.get(); |
| 563 in_buffers[0].cbBuffer = bytes_received_; | 560 in_buffers_[0].cbBuffer = bytes_received_; |
| 564 in_buffers[0].BufferType = SECBUFFER_TOKEN; | 561 in_buffers_[0].BufferType = SECBUFFER_TOKEN; |
| 565 | 562 |
| 566 in_buffers[1].pvBuffer = NULL; | 563 in_buffers_[1].pvBuffer = NULL; |
| 567 in_buffers[1].cbBuffer = 0; | 564 in_buffers_[1].cbBuffer = 0; |
| 568 in_buffers[1].BufferType = SECBUFFER_EMPTY; | 565 in_buffers_[1].BufferType = SECBUFFER_EMPTY; |
| 569 | 566 |
| 570 out_buffer_desc.cBuffers = 1; | 567 out_buffer_desc.cBuffers = 1; |
| 571 out_buffer_desc.pBuffers = &send_buffer_; | 568 out_buffer_desc.pBuffers = &send_buffer_; |
| 572 out_buffer_desc.ulVersion = SECBUFFER_VERSION; | 569 out_buffer_desc.ulVersion = SECBUFFER_VERSION; |
| 573 | 570 |
| 574 send_buffer_.pvBuffer = NULL; | 571 send_buffer_.pvBuffer = NULL; |
| 575 send_buffer_.BufferType = SECBUFFER_TOKEN; | 572 send_buffer_.BufferType = SECBUFFER_TOKEN; |
| 576 send_buffer_.cbBuffer = 0; | 573 send_buffer_.cbBuffer = 0; |
| 577 | 574 |
| 578 status = InitializeSecurityContext( | 575 isc_status_ = InitializeSecurityContext( |
| 579 creds_, | 576 creds_, |
| 580 &ctxt_, | 577 &ctxt_, |
| 581 NULL, | 578 NULL, |
| 582 flags, | 579 flags, |
| 583 0, | 580 0, |
| 584 SECURITY_NATIVE_DREP, | 581 SECURITY_NATIVE_DREP, |
| 585 &in_buffer_desc, | 582 &in_buffer_desc, |
| 586 0, | 583 0, |
| 587 NULL, | 584 NULL, |
| 588 &out_buffer_desc, | 585 &out_buffer_desc, |
| 589 &out_flags, | 586 &out_flags, |
| 590 &expiry); | 587 &expiry); |
| 591 | 588 |
| 592 if (status == SEC_E_INCOMPLETE_MESSAGE) { | 589 if (send_buffer_.cbBuffer != 0 && |
| 593 DCHECK(FAILED(status)); | 590 (isc_status_ == SEC_E_OK || |
| 594 DCHECK(send_buffer_.cbBuffer == 0 || | 591 isc_status_ == SEC_I_CONTINUE_NEEDED || |
| 595 !(out_flags & ISC_RET_EXTENDED_ERROR)); | 592 (FAILED(isc_status_) && (out_flags & ISC_RET_EXTENDED_ERROR)))) { |
| 593 next_state_ = STATE_HANDSHAKE_WRITE; |
| 594 return OK; |
| 595 } |
| 596 return DidCallInitializeSecurityContext(); |
| 597 } |
| 598 |
| 599 int SSLClientSocketWin::DidCallInitializeSecurityContext() { |
| 600 if (isc_status_ == SEC_E_INCOMPLETE_MESSAGE) { |
| 596 next_state_ = STATE_HANDSHAKE_READ; | 601 next_state_ = STATE_HANDSHAKE_READ; |
| 597 return OK; | 602 return OK; |
| 598 } | 603 } |
| 599 | 604 |
| 600 if (send_buffer_.cbBuffer != 0 && | 605 if (isc_status_ == SEC_E_OK) { |
| 601 (status == SEC_E_OK || | 606 if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) { |
| 602 status == SEC_I_CONTINUE_NEEDED || | 607 // Save this data for later. |
| 603 FAILED(status) && (out_flags & ISC_RET_EXTENDED_ERROR))) { | 608 memmove(recv_buffer_.get(), |
| 604 // If FAILED(status) is true, we should terminate the connection after | 609 recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer), |
| 605 // sending send_buffer_. | 610 in_buffers_[1].cbBuffer); |
| 606 if (status == SEC_E_OK) | 611 bytes_received_ = in_buffers_[1].cbBuffer; |
| 607 complete_handshake_on_write_complete_ = true; | 612 } else { |
| 608 // We only handle these cases correctly. | 613 bytes_received_ = 0; |
| 609 DCHECK(status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED); | |
| 610 next_state_ = STATE_HANDSHAKE_WRITE; | |
| 611 bytes_received_ = 0; | |
| 612 return OK; | |
| 613 } | |
| 614 | |
| 615 if (status == SEC_E_OK) { | |
| 616 if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { | |
| 617 // TODO(darin) need to save this data for later. | |
| 618 NOTREACHED() << "should not occur for HTTPS traffic"; | |
| 619 return ERR_FAILED; | |
| 620 } | 614 } |
| 621 bytes_received_ = 0; | |
| 622 return DidCompleteHandshake(); | 615 return DidCompleteHandshake(); |
| 623 } | 616 } |
| 624 | 617 |
| 625 if (FAILED(status)) | 618 if (FAILED(isc_status_)) |
| 626 return MapSecurityError(status); | 619 return MapSecurityError(isc_status_); |
| 627 | 620 |
| 628 if (status == SEC_I_INCOMPLETE_CREDENTIALS) { | 621 if (isc_status_ == SEC_I_INCOMPLETE_CREDENTIALS) { |
| 629 // We don't support SSL client authentication yet. For now we just set | 622 // We don't support SSL client authentication yet. For now we just set |
| 630 // no_client_cert_ to true and call InitializeSecurityContext again. | 623 // no_client_cert_ to true and call InitializeSecurityContext again. |
| 631 no_client_cert_ = true; | 624 no_client_cert_ = true; |
| 632 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 625 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
| 633 ignore_ok_result_ = true; // OK doesn't mean EOF. | 626 ignore_ok_result_ = true; // OK doesn't mean EOF. |
| 634 return OK; | 627 return OK; |
| 635 } | 628 } |
| 636 | 629 |
| 637 DCHECK(status == SEC_I_CONTINUE_NEEDED); | 630 DCHECK(isc_status_ == SEC_I_CONTINUE_NEEDED); |
| 638 if (in_buffers[1].BufferType == SECBUFFER_EXTRA) { | 631 if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) { |
| 639 memmove(&recv_buffer_[0], | 632 memmove(recv_buffer_.get(), |
| 640 &recv_buffer_[0] + (bytes_received_ - in_buffers[1].cbBuffer), | 633 recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer), |
| 641 in_buffers[1].cbBuffer); | 634 in_buffers_[1].cbBuffer); |
| 642 bytes_received_ = in_buffers[1].cbBuffer; | 635 bytes_received_ = in_buffers_[1].cbBuffer; |
| 643 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 636 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
| 644 ignore_ok_result_ = true; // OK doesn't mean EOF. | 637 ignore_ok_result_ = true; // OK doesn't mean EOF. |
| 645 return OK; | 638 return OK; |
| 646 } | 639 } |
| 647 | 640 |
| 648 bytes_received_ = 0; | 641 bytes_received_ = 0; |
| 649 next_state_ = STATE_HANDSHAKE_READ; | 642 next_state_ = STATE_HANDSHAKE_READ; |
| 650 return OK; | 643 return OK; |
| 651 } | 644 } |
| 652 | 645 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 667 if (result < 0) | 660 if (result < 0) |
| 668 return result; | 661 return result; |
| 669 | 662 |
| 670 DCHECK(result != 0); | 663 DCHECK(result != 0); |
| 671 | 664 |
| 672 bytes_sent_ += result; | 665 bytes_sent_ += result; |
| 673 DCHECK(bytes_sent_ <= static_cast<int>(send_buffer_.cbBuffer)); | 666 DCHECK(bytes_sent_ <= static_cast<int>(send_buffer_.cbBuffer)); |
| 674 | 667 |
| 675 if (bytes_sent_ >= static_cast<int>(send_buffer_.cbBuffer)) { | 668 if (bytes_sent_ >= static_cast<int>(send_buffer_.cbBuffer)) { |
| 676 bool overflow = (bytes_sent_ > static_cast<int>(send_buffer_.cbBuffer)); | 669 bool overflow = (bytes_sent_ > static_cast<int>(send_buffer_.cbBuffer)); |
| 677 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); | 670 FreeSendBuffer(); |
| 678 DCHECK(status == SEC_E_OK); | |
| 679 memset(&send_buffer_, 0, sizeof(send_buffer_)); | |
| 680 bytes_sent_ = 0; | 671 bytes_sent_ = 0; |
| 681 if (overflow) // Bug! | 672 if (overflow) // Bug! |
| 682 return ERR_UNEXPECTED; | 673 return ERR_UNEXPECTED; |
| 683 if (complete_handshake_on_write_complete_) | 674 if (writing_first_token_) { |
| 684 return DidCompleteHandshake(); | 675 writing_first_token_ = false; |
| 685 next_state_ = STATE_HANDSHAKE_READ; | 676 DCHECK(bytes_received_ == 0); |
| 686 } else { | 677 next_state_ = STATE_HANDSHAKE_READ; |
| 687 // Send the remaining bytes. | 678 return OK; |
| 688 next_state_ = STATE_HANDSHAKE_WRITE; | 679 } |
| 680 return DidCallInitializeSecurityContext(); |
| 689 } | 681 } |
| 690 | 682 |
| 683 // Send the remaining bytes. |
| 684 next_state_ = STATE_HANDSHAKE_WRITE; |
| 691 return OK; | 685 return OK; |
| 692 } | 686 } |
| 693 | 687 |
| 694 // Set server_cert_status_ and return OK or a network error. | 688 // Set server_cert_status_ and return OK or a network error. |
| 695 int SSLClientSocketWin::DoVerifyCert() { | 689 int SSLClientSocketWin::DoVerifyCert() { |
| 696 next_state_ = STATE_VERIFY_CERT_COMPLETE; | 690 next_state_ = STATE_VERIFY_CERT_COMPLETE; |
| 697 | 691 |
| 698 DCHECK(server_cert_); | 692 DCHECK(server_cert_); |
| 699 return verifier_.Verify(server_cert_, hostname_, | 693 return verifier_.Verify(server_cert_, hostname_, |
| 700 ssl_config_.rev_checking_enabled, | 694 ssl_config_.rev_checking_enabled, |
| 701 &server_cert_verify_result_, &io_callback_); | 695 &server_cert_verify_result_, &io_callback_); |
| 702 } | 696 } |
| 703 | 697 |
| 704 int SSLClientSocketWin::DoVerifyCertComplete(int result) { | 698 int SSLClientSocketWin::DoVerifyCertComplete(int result) { |
| 705 LogConnectionTypeMetrics(); | 699 LogConnectionTypeMetrics(); |
| 700 if (renegotiating_) { |
| 701 renegotiating_ = false; |
| 702 // Pick up where we left off. Go back to reading data. |
| 703 if (result == OK) |
| 704 SetNextStateForRead(); |
| 705 } |
| 706 return result; | 706 return result; |
| 707 } | 707 } |
| 708 | 708 |
| 709 int SSLClientSocketWin::DoPayloadRead() { | 709 int SSLClientSocketWin::DoPayloadRead() { |
| 710 next_state_ = STATE_PAYLOAD_READ_COMPLETE; | 710 next_state_ = STATE_PAYLOAD_READ_COMPLETE; |
| 711 | 711 |
| 712 DCHECK(recv_buffer_.get()); | 712 DCHECK(recv_buffer_.get()); |
| 713 | 713 |
| 714 char* buf = recv_buffer_.get() + bytes_received_; | 714 char* buf = recv_buffer_.get() + bytes_received_; |
| 715 int buf_len = kRecvBufferSize - bytes_received_; | 715 int buf_len = kRecvBufferSize - bytes_received_; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 } | 799 } |
| 800 if (bytes_decrypted_ == 0) { | 800 if (bytes_decrypted_ == 0) { |
| 801 decrypted_ptr_ = NULL; | 801 decrypted_ptr_ = NULL; |
| 802 if (bytes_received_ != 0) { | 802 if (bytes_received_ != 0) { |
| 803 memmove(recv_buffer_.get(), received_ptr_, bytes_received_); | 803 memmove(recv_buffer_.get(), received_ptr_, bytes_received_); |
| 804 received_ptr_ = recv_buffer_.get(); | 804 received_ptr_ = recv_buffer_.get(); |
| 805 } | 805 } |
| 806 } | 806 } |
| 807 | 807 |
| 808 if (status == SEC_I_RENEGOTIATE) { | 808 if (status == SEC_I_RENEGOTIATE) { |
| 809 // TODO(wtc): support renegotiation. | 809 if (bytes_received_ != 0) { |
| 810 // Should ideally send a no_renegotiation alert to the server. | 810 // The server requested renegotiation, but there are some data yet to |
| 811 return ERR_SSL_RENEGOTIATION_REQUESTED; | 811 // be decrypted. The Platform SDK WebClient.c sample doesn't handle |
| 812 // this, so we don't know how to handle this. Assume this cannot |
| 813 // happen. |
| 814 LOG(ERROR) << "DecryptMessage returned SEC_I_RENEGOTIATE with a buffer " |
| 815 << "of type SECBUFFER_EXTRA."; |
| 816 return ERR_SSL_RENEGOTIATION_REQUESTED; |
| 817 } |
| 818 if (len != 0) { |
| 819 // The server requested renegotiation, but there are some decrypted |
| 820 // data. We can't start renegotiation until we have returned all |
| 821 // decrypted data to the caller. |
| 822 // |
| 823 // This hasn't happened during testing. Assume this cannot happen even |
| 824 // though we know how to handle this. |
| 825 LOG(ERROR) << "DecryptMessage returned SEC_I_RENEGOTIATE with a buffer " |
| 826 << "of type SECBUFFER_DATA."; |
| 827 return ERR_SSL_RENEGOTIATION_REQUESTED; |
| 828 } |
| 829 // Jump to the handshake sequence. Will come back when the rehandshake is |
| 830 // done. |
| 831 renegotiating_ = true; |
| 832 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
| 833 ignore_ok_result_ = true; // OK doesn't mean EOF. |
| 834 return len; |
| 812 } | 835 } |
| 813 | 836 |
| 814 // If we decrypted 0 bytes, don't report 0 bytes read, which would be | 837 // If we decrypted 0 bytes, don't report 0 bytes read, which would be |
| 815 // mistaken for EOF. Continue decrypting or read more. | 838 // mistaken for EOF. Continue decrypting or read more. |
| 816 if (len == 0) { | 839 if (len == 0) |
| 817 if (bytes_received_ == 0) { | 840 SetNextStateForRead(); |
| 818 next_state_ = STATE_PAYLOAD_READ; | |
| 819 } else { | |
| 820 next_state_ = STATE_PAYLOAD_READ_COMPLETE; | |
| 821 ignore_ok_result_ = true; // OK doesn't mean EOF. | |
| 822 } | |
| 823 } | |
| 824 return len; | 841 return len; |
| 825 } | 842 } |
| 826 | 843 |
| 827 int SSLClientSocketWin::DoPayloadEncrypt() { | 844 int SSLClientSocketWin::DoPayloadEncrypt() { |
| 828 DCHECK(user_buf_); | 845 DCHECK(user_buf_); |
| 829 DCHECK(user_buf_len_ > 0); | 846 DCHECK(user_buf_len_ > 0); |
| 830 | 847 |
| 831 ULONG message_len = std::min( | 848 ULONG message_len = std::min( |
| 832 stream_sizes_.cbMaximumMessage, static_cast<ULONG>(user_buf_len_)); | 849 stream_sizes_.cbMaximumMessage, static_cast<ULONG>(user_buf_len_)); |
| 833 ULONG alloc_len = | 850 ULONG alloc_len = |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 return OK; | 928 return OK; |
| 912 } | 929 } |
| 913 | 930 |
| 914 int SSLClientSocketWin::DidCompleteHandshake() { | 931 int SSLClientSocketWin::DidCompleteHandshake() { |
| 915 SECURITY_STATUS status = QueryContextAttributes( | 932 SECURITY_STATUS status = QueryContextAttributes( |
| 916 &ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_); | 933 &ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_); |
| 917 if (status != SEC_E_OK) { | 934 if (status != SEC_E_OK) { |
| 918 DLOG(ERROR) << "QueryContextAttributes failed: " << status; | 935 DLOG(ERROR) << "QueryContextAttributes failed: " << status; |
| 919 return MapSecurityError(status); | 936 return MapSecurityError(status); |
| 920 } | 937 } |
| 921 DCHECK(!server_cert_); | 938 DCHECK(!server_cert_ || renegotiating_); |
| 922 PCCERT_CONTEXT server_cert_handle = NULL; | 939 PCCERT_CONTEXT server_cert_handle = NULL; |
| 923 status = QueryContextAttributes( | 940 status = QueryContextAttributes( |
| 924 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle); | 941 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle); |
| 925 if (status != SEC_E_OK) { | 942 if (status != SEC_E_OK) { |
| 926 DLOG(ERROR) << "QueryContextAttributes failed: " << status; | 943 DLOG(ERROR) << "QueryContextAttributes failed: " << status; |
| 927 return MapSecurityError(status); | 944 return MapSecurityError(status); |
| 928 } | 945 } |
| 929 server_cert_ = X509Certificate::CreateFromHandle( | 946 server_cert_ = X509Certificate::CreateFromHandle( |
| 930 server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK); | 947 server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK); |
| 931 | 948 |
| 932 completed_handshake_ = true; | 949 completed_handshake_ = true; |
| 933 next_state_ = STATE_VERIFY_CERT; | 950 next_state_ = STATE_VERIFY_CERT; |
| 934 return OK; | 951 return OK; |
| 935 } | 952 } |
| 936 | 953 |
| 937 void SSLClientSocketWin::LogConnectionTypeMetrics() const { | 954 void SSLClientSocketWin::LogConnectionTypeMetrics() const { |
| 938 UpdateConnectionTypeHistograms(CONNECTION_SSL); | 955 UpdateConnectionTypeHistograms(CONNECTION_SSL); |
| 939 if (server_cert_verify_result_.has_md5) | 956 if (server_cert_verify_result_.has_md5) |
| 940 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); | 957 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); |
| 941 if (server_cert_verify_result_.has_md2) | 958 if (server_cert_verify_result_.has_md2) |
| 942 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); | 959 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); |
| 943 if (server_cert_verify_result_.has_md4) | 960 if (server_cert_verify_result_.has_md4) |
| 944 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); | 961 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); |
| 945 if (server_cert_verify_result_.has_md5_ca) | 962 if (server_cert_verify_result_.has_md5_ca) |
| 946 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); | 963 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); |
| 947 if (server_cert_verify_result_.has_md2_ca) | 964 if (server_cert_verify_result_.has_md2_ca) |
| 948 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); | 965 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); |
| 949 } | 966 } |
| 950 | 967 |
| 968 void SSLClientSocketWin::SetNextStateForRead() { |
| 969 if (bytes_received_ == 0) { |
| 970 next_state_ = STATE_PAYLOAD_READ; |
| 971 } else { |
| 972 next_state_ = STATE_PAYLOAD_READ_COMPLETE; |
| 973 ignore_ok_result_ = true; // OK doesn't mean EOF. |
| 974 } |
| 975 } |
| 976 |
| 977 void SSLClientSocketWin::FreeSendBuffer() { |
| 978 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); |
| 979 DCHECK(status == SEC_E_OK); |
| 980 memset(&send_buffer_, 0, sizeof(send_buffer_)); |
| 981 } |
| 982 |
| 951 } // namespace net | 983 } // namespace net |
| OLD | NEW |