| 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 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived | 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived |
| 6 // from AuthCertificateCallback() in | 6 // from AuthCertificateCallback() in |
| 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. |
| 8 | 8 |
| 9 /* ***** BEGIN LICENSE BLOCK ***** | 9 /* ***** BEGIN LICENSE BLOCK ***** |
| 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 #include "base/string_util.h" | 66 #include "base/string_util.h" |
| 67 #include "net/base/address_list.h" | 67 #include "net/base/address_list.h" |
| 68 #include "net/base/cert_verifier.h" | 68 #include "net/base/cert_verifier.h" |
| 69 #include "net/base/io_buffer.h" | 69 #include "net/base/io_buffer.h" |
| 70 #include "net/base/net_log.h" | 70 #include "net/base/net_log.h" |
| 71 #include "net/base/net_errors.h" | 71 #include "net/base/net_errors.h" |
| 72 #include "net/base/ssl_cert_request_info.h" | 72 #include "net/base/ssl_cert_request_info.h" |
| 73 #include "net/base/ssl_info.h" | 73 #include "net/base/ssl_info.h" |
| 74 #include "net/base/sys_addrinfo.h" | 74 #include "net/base/sys_addrinfo.h" |
| 75 #include "net/ocsp/nss_ocsp.h" | 75 #include "net/ocsp/nss_ocsp.h" |
| 76 #include "net/socket/client_socket_handle.h" |
| 76 | 77 |
| 77 static const int kRecvBufferSize = 4096; | 78 static const int kRecvBufferSize = 4096; |
| 78 | 79 |
| 79 namespace net { | 80 namespace net { |
| 80 | 81 |
| 81 // State machines are easier to debug if you log state transitions. | 82 // State machines are easier to debug if you log state transitions. |
| 82 // Enable these if you want to see what's going on. | 83 // Enable these if you want to see what's going on. |
| 83 #if 1 | 84 #if 1 |
| 84 #define EnterFunction(x) | 85 #define EnterFunction(x) |
| 85 #define LeaveFunction(x) | 86 #define LeaveFunction(x) |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 | 271 |
| 271 #endif | 272 #endif |
| 272 | 273 |
| 273 } // namespace | 274 } // namespace |
| 274 | 275 |
| 275 #if defined(OS_WIN) | 276 #if defined(OS_WIN) |
| 276 // static | 277 // static |
| 277 HCERTSTORE SSLClientSocketNSS::cert_store_ = NULL; | 278 HCERTSTORE SSLClientSocketNSS::cert_store_ = NULL; |
| 278 #endif | 279 #endif |
| 279 | 280 |
| 280 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, | 281 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, |
| 281 const std::string& hostname, | 282 const std::string& hostname, |
| 282 const SSLConfig& ssl_config) | 283 const SSLConfig& ssl_config) |
| 283 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( | 284 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( |
| 284 this, &SSLClientSocketNSS::BufferSendComplete)), | 285 this, &SSLClientSocketNSS::BufferSendComplete)), |
| 285 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_( | 286 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_( |
| 286 this, &SSLClientSocketNSS::BufferRecvComplete)), | 287 this, &SSLClientSocketNSS::BufferRecvComplete)), |
| 287 transport_send_busy_(false), | 288 transport_send_busy_(false), |
| 288 transport_recv_busy_(false), | 289 transport_recv_busy_(false), |
| 289 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( | 290 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( |
| 290 this, &SSLClientSocketNSS::OnHandshakeIOComplete)), | 291 this, &SSLClientSocketNSS::OnHandshakeIOComplete)), |
| 291 transport_(transport_socket), | 292 transport_(transport_socket), |
| 292 hostname_(hostname), | 293 hostname_(hostname), |
| 293 ssl_config_(ssl_config), | 294 ssl_config_(ssl_config), |
| 294 user_connect_callback_(NULL), | 295 user_connect_callback_(NULL), |
| 295 user_read_callback_(NULL), | 296 user_read_callback_(NULL), |
| 296 user_write_callback_(NULL), | 297 user_write_callback_(NULL), |
| 297 user_read_buf_len_(0), | 298 user_read_buf_len_(0), |
| 298 user_write_buf_len_(0), | 299 user_write_buf_len_(0), |
| 299 server_cert_nss_(NULL), | 300 server_cert_nss_(NULL), |
| 300 client_auth_cert_needed_(false), | 301 client_auth_cert_needed_(false), |
| 301 handshake_callback_called_(false), | 302 handshake_callback_called_(false), |
| 302 completed_handshake_(false), | 303 completed_handshake_(false), |
| 303 next_handshake_state_(STATE_NONE), | 304 next_handshake_state_(STATE_NONE), |
| 304 nss_fd_(NULL), | 305 nss_fd_(NULL), |
| 305 nss_bufs_(NULL), | 306 nss_bufs_(NULL), |
| 306 net_log_(transport_socket->NetLog()) { | 307 net_log_(transport_socket->socket()->NetLog()) { |
| 307 EnterFunction(""); | 308 EnterFunction(""); |
| 308 } | 309 } |
| 309 | 310 |
| 310 SSLClientSocketNSS::~SSLClientSocketNSS() { | 311 SSLClientSocketNSS::~SSLClientSocketNSS() { |
| 311 EnterFunction(""); | 312 EnterFunction(""); |
| 312 Disconnect(); | 313 Disconnect(); |
| 313 LeaveFunction(""); | 314 LeaveFunction(""); |
| 314 } | 315 } |
| 315 | 316 |
| 316 int SSLClientSocketNSS::Init() { | 317 int SSLClientSocketNSS::Init() { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 int SSLClientSocketNSS::InitializeSSLOptions() { | 371 int SSLClientSocketNSS::InitializeSSLOptions() { |
| 371 // Transport connected, now hook it up to nss | 372 // Transport connected, now hook it up to nss |
| 372 // TODO(port): specify rx and tx buffer sizes separately | 373 // TODO(port): specify rx and tx buffer sizes separately |
| 373 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); | 374 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); |
| 374 if (nss_fd_ == NULL) { | 375 if (nss_fd_ == NULL) { |
| 375 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. | 376 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. |
| 376 } | 377 } |
| 377 | 378 |
| 378 // Tell NSS who we're connected to | 379 // Tell NSS who we're connected to |
| 379 AddressList peer_address; | 380 AddressList peer_address; |
| 380 int err = transport_->GetPeerAddress(&peer_address); | 381 int err = transport_->socket()->GetPeerAddress(&peer_address); |
| 381 if (err != OK) | 382 if (err != OK) |
| 382 return err; | 383 return err; |
| 383 | 384 |
| 384 const struct addrinfo* ai = peer_address.head(); | 385 const struct addrinfo* ai = peer_address.head(); |
| 385 | 386 |
| 386 PRNetAddr peername; | 387 PRNetAddr peername; |
| 387 memset(&peername, 0, sizeof(peername)); | 388 memset(&peername, 0, sizeof(peername)); |
| 388 DCHECK_LE(ai->ai_addrlen, sizeof(peername)); | 389 DCHECK_LE(ai->ai_addrlen, sizeof(peername)); |
| 389 size_t len = std::min(static_cast<size_t>(ai->ai_addrlen), sizeof(peername)); | 390 size_t len = std::min(static_cast<size_t>(ai->ai_addrlen), sizeof(peername)); |
| 390 memcpy(&peername, ai->ai_addr, len); | 391 memcpy(&peername, ai->ai_addr, len); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 // TODO(wtc): Send SSL close_notify alert. | 542 // TODO(wtc): Send SSL close_notify alert. |
| 542 if (nss_fd_ != NULL) { | 543 if (nss_fd_ != NULL) { |
| 543 InvalidateSessionIfBadCertificate(); | 544 InvalidateSessionIfBadCertificate(); |
| 544 PR_Close(nss_fd_); | 545 PR_Close(nss_fd_); |
| 545 nss_fd_ = NULL; | 546 nss_fd_ = NULL; |
| 546 } | 547 } |
| 547 | 548 |
| 548 // Shut down anything that may call us back (through buffer_send_callback_, | 549 // Shut down anything that may call us back (through buffer_send_callback_, |
| 549 // buffer_recv_callback, or handshake_io_callback_). | 550 // buffer_recv_callback, or handshake_io_callback_). |
| 550 verifier_.reset(); | 551 verifier_.reset(); |
| 551 transport_->Disconnect(); | 552 transport_->socket()->Disconnect(); |
| 552 | 553 |
| 553 // Reset object state | 554 // Reset object state |
| 554 transport_send_busy_ = false; | 555 transport_send_busy_ = false; |
| 555 transport_recv_busy_ = false; | 556 transport_recv_busy_ = false; |
| 556 user_connect_callback_ = NULL; | 557 user_connect_callback_ = NULL; |
| 557 user_read_callback_ = NULL; | 558 user_read_callback_ = NULL; |
| 558 user_write_callback_ = NULL; | 559 user_write_callback_ = NULL; |
| 559 user_read_buf_ = NULL; | 560 user_read_buf_ = NULL; |
| 560 user_read_buf_len_ = 0; | 561 user_read_buf_len_ = 0; |
| 561 user_write_buf_ = NULL; | 562 user_write_buf_ = NULL; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 575 } | 576 } |
| 576 | 577 |
| 577 bool SSLClientSocketNSS::IsConnected() const { | 578 bool SSLClientSocketNSS::IsConnected() const { |
| 578 // Ideally, we should also check if we have received the close_notify alert | 579 // Ideally, we should also check if we have received the close_notify alert |
| 579 // message from the server, and return false in that case. We're not doing | 580 // message from the server, and return false in that case. We're not doing |
| 580 // that, so this function may return a false positive. Since the upper | 581 // that, so this function may return a false positive. Since the upper |
| 581 // layer (HttpNetworkTransaction) needs to handle a persistent connection | 582 // layer (HttpNetworkTransaction) needs to handle a persistent connection |
| 582 // closed by the server when we send a request anyway, a false positive in | 583 // closed by the server when we send a request anyway, a false positive in |
| 583 // exchange for simpler code is a good trade-off. | 584 // exchange for simpler code is a good trade-off. |
| 584 EnterFunction(""); | 585 EnterFunction(""); |
| 585 bool ret = completed_handshake_ && transport_->IsConnected(); | 586 bool ret = completed_handshake_ && transport_->socket()->IsConnected(); |
| 586 LeaveFunction(""); | 587 LeaveFunction(""); |
| 587 return ret; | 588 return ret; |
| 588 } | 589 } |
| 589 | 590 |
| 590 bool SSLClientSocketNSS::IsConnectedAndIdle() const { | 591 bool SSLClientSocketNSS::IsConnectedAndIdle() const { |
| 591 // Unlike IsConnected, this method doesn't return a false positive. | 592 // Unlike IsConnected, this method doesn't return a false positive. |
| 592 // | 593 // |
| 593 // Strictly speaking, we should check if we have received the close_notify | 594 // Strictly speaking, we should check if we have received the close_notify |
| 594 // alert message from the server, and return false in that case. Although | 595 // alert message from the server, and return false in that case. Although |
| 595 // the close_notify alert message means EOF in the SSL layer, it is just | 596 // the close_notify alert message means EOF in the SSL layer, it is just |
| 596 // bytes to the transport layer below, so transport_->IsConnectedAndIdle() | 597 // bytes to the transport layer below, so |
| 597 // returns the desired false when we receive close_notify. | 598 // transport_->socket()->IsConnectedAndIdle() returns the desired false |
| 599 // when we receive close_notify. |
| 598 EnterFunction(""); | 600 EnterFunction(""); |
| 599 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle(); | 601 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle(); |
| 600 LeaveFunction(""); | 602 LeaveFunction(""); |
| 601 return ret; | 603 return ret; |
| 602 } | 604 } |
| 603 | 605 |
| 604 int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const { | 606 int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const { |
| 605 return transport_->GetPeerAddress(address); | 607 return transport_->socket()->GetPeerAddress(address); |
| 606 } | 608 } |
| 607 | 609 |
| 608 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, | 610 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, |
| 609 CompletionCallback* callback) { | 611 CompletionCallback* callback) { |
| 610 EnterFunction(buf_len); | 612 EnterFunction(buf_len); |
| 611 DCHECK(completed_handshake_); | 613 DCHECK(completed_handshake_); |
| 612 DCHECK(next_handshake_state_ == STATE_NONE); | 614 DCHECK(next_handshake_state_ == STATE_NONE); |
| 613 DCHECK(!user_read_callback_); | 615 DCHECK(!user_read_callback_); |
| 614 DCHECK(!user_connect_callback_); | 616 DCHECK(!user_connect_callback_); |
| 615 DCHECK(!user_read_buf_); | 617 DCHECK(!user_read_buf_); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 user_write_callback_ = callback; | 651 user_write_callback_ = callback; |
| 650 } else { | 652 } else { |
| 651 user_write_buf_ = NULL; | 653 user_write_buf_ = NULL; |
| 652 user_write_buf_len_ = 0; | 654 user_write_buf_len_ = 0; |
| 653 } | 655 } |
| 654 LeaveFunction(rv); | 656 LeaveFunction(rv); |
| 655 return rv; | 657 return rv; |
| 656 } | 658 } |
| 657 | 659 |
| 658 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { | 660 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { |
| 659 return transport_->SetReceiveBufferSize(size); | 661 return transport_->socket()->SetReceiveBufferSize(size); |
| 660 } | 662 } |
| 661 | 663 |
| 662 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { | 664 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { |
| 663 return transport_->SetSendBufferSize(size); | 665 return transport_->socket()->SetSendBufferSize(size); |
| 664 } | 666 } |
| 665 | 667 |
| 666 #if defined(OS_WIN) | 668 #if defined(OS_WIN) |
| 667 // static | 669 // static |
| 668 X509Certificate::OSCertHandle SSLClientSocketNSS::CreateOSCert( | 670 X509Certificate::OSCertHandle SSLClientSocketNSS::CreateOSCert( |
| 669 const SECItem& der_cert) { | 671 const SECItem& der_cert) { |
| 670 // TODO(wtc): close cert_store_ at shutdown. | 672 // TODO(wtc): close cert_store_ at shutdown. |
| 671 if (!cert_store_) | 673 if (!cert_store_) |
| 672 cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); | 674 cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); |
| 673 | 675 |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 // nss_bufs_ is a circular buffer. It may have two contiguous parts | 1012 // nss_bufs_ is a circular buffer. It may have two contiguous parts |
| 1011 // (before and after the wrap). So this for loop needs two iterations. | 1013 // (before and after the wrap). So this for loop needs two iterations. |
| 1012 for (int i = 0; i < 2; ++i) { | 1014 for (int i = 0; i < 2; ++i) { |
| 1013 const char* buf; | 1015 const char* buf; |
| 1014 int nb = memio_GetWriteParams(nss_bufs_, &buf); | 1016 int nb = memio_GetWriteParams(nss_bufs_, &buf); |
| 1015 if (!nb) | 1017 if (!nb) |
| 1016 break; | 1018 break; |
| 1017 | 1019 |
| 1018 scoped_refptr<IOBuffer> send_buffer = new IOBuffer(nb); | 1020 scoped_refptr<IOBuffer> send_buffer = new IOBuffer(nb); |
| 1019 memcpy(send_buffer->data(), buf, nb); | 1021 memcpy(send_buffer->data(), buf, nb); |
| 1020 int rv = transport_->Write(send_buffer, nb, &buffer_send_callback_); | 1022 int rv = transport_->socket()->Write(send_buffer, nb, |
| 1023 &buffer_send_callback_); |
| 1021 if (rv == ERR_IO_PENDING) { | 1024 if (rv == ERR_IO_PENDING) { |
| 1022 transport_send_busy_ = true; | 1025 transport_send_busy_ = true; |
| 1023 break; | 1026 break; |
| 1024 } else { | 1027 } else { |
| 1025 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv)); | 1028 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv)); |
| 1026 if (rv < 0) { | 1029 if (rv < 0) { |
| 1027 // Return the error even if the previous Write succeeded. | 1030 // Return the error even if the previous Write succeeded. |
| 1028 nsent = rv; | 1031 nsent = rv; |
| 1029 break; | 1032 break; |
| 1030 } | 1033 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1050 | 1053 |
| 1051 char *buf; | 1054 char *buf; |
| 1052 int nb = memio_GetReadParams(nss_bufs_, &buf); | 1055 int nb = memio_GetReadParams(nss_bufs_, &buf); |
| 1053 EnterFunction(nb); | 1056 EnterFunction(nb); |
| 1054 int rv; | 1057 int rv; |
| 1055 if (!nb) { | 1058 if (!nb) { |
| 1056 // buffer too full to read into, so no I/O possible at moment | 1059 // buffer too full to read into, so no I/O possible at moment |
| 1057 rv = ERR_IO_PENDING; | 1060 rv = ERR_IO_PENDING; |
| 1058 } else { | 1061 } else { |
| 1059 recv_buffer_ = new IOBuffer(nb); | 1062 recv_buffer_ = new IOBuffer(nb); |
| 1060 rv = transport_->Read(recv_buffer_, nb, &buffer_recv_callback_); | 1063 rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_); |
| 1061 if (rv == ERR_IO_PENDING) { | 1064 if (rv == ERR_IO_PENDING) { |
| 1062 transport_recv_busy_ = true; | 1065 transport_recv_busy_ = true; |
| 1063 } else { | 1066 } else { |
| 1064 if (rv > 0) | 1067 if (rv > 0) |
| 1065 memcpy(buf, recv_buffer_->data(), rv); | 1068 memcpy(buf, recv_buffer_->data(), rv); |
| 1066 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv)); | 1069 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv)); |
| 1067 recv_buffer_ = NULL; | 1070 recv_buffer_ = NULL; |
| 1068 } | 1071 } |
| 1069 } | 1072 } |
| 1070 LeaveFunction(rv); | 1073 LeaveFunction(rv); |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 PRErrorCode prerr = PR_GetError(); | 1555 PRErrorCode prerr = PR_GetError(); |
| 1553 if (prerr == PR_WOULD_BLOCK_ERROR) { | 1556 if (prerr == PR_WOULD_BLOCK_ERROR) { |
| 1554 LeaveFunction(""); | 1557 LeaveFunction(""); |
| 1555 return ERR_IO_PENDING; | 1558 return ERR_IO_PENDING; |
| 1556 } | 1559 } |
| 1557 LeaveFunction(""); | 1560 LeaveFunction(""); |
| 1558 return MapNSPRError(prerr); | 1561 return MapNSPRError(prerr); |
| 1559 } | 1562 } |
| 1560 | 1563 |
| 1561 } // namespace net | 1564 } // namespace net |
| OLD | NEW |