Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Unified Diff: net/socket/ssl_server_socket_nss.cc

Issue 1882433002: Removing NSS files and USE_OPENSSL flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/ssl_server_socket_nss.h ('k') | net/socket/ssl_server_socket_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_server_socket_nss.cc
diff --git a/net/socket/ssl_server_socket_nss.cc b/net/socket/ssl_server_socket_nss.cc
deleted file mode 100644
index 17f7d62fc97e126f787e567cd4df0125e5b3f98f..0000000000000000000000000000000000000000
--- a/net/socket/ssl_server_socket_nss.cc
+++ /dev/null
@@ -1,982 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/socket/ssl_server_socket_nss.h"
-
-#include <utility>
-
-#if defined(OS_WIN)
-#include <winsock2.h>
-#endif
-
-#if defined(USE_SYSTEM_SSL)
-#include <dlfcn.h>
-#endif
-#if defined(OS_MACOSX)
-#include <Security/Security.h>
-#endif
-#include <certdb.h>
-#include <cryptohi.h>
-#include <hasht.h>
-#include <keyhi.h>
-#include <nspr.h>
-#include <nss.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-#include <ssl.h>
-#include <sslerr.h>
-#include <sslproto.h>
-
-#include <limits>
-
-#include "base/callback_helpers.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/rsa_private_key.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log.h"
-#include "net/socket/nss_ssl_util.h"
-
-// SSL plaintext fragments are shorter than 16KB. Although the record layer
-// overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
-// smaller than 1KB. So a 17KB buffer should be large enough to hold an
-// entire SSL record.
-static const int kRecvBufferSize = 17 * 1024;
-static const int kSendBufferSize = 17 * 1024;
-
-#define GotoState(s) next_handshake_state_ = s
-
-namespace net {
-
-namespace {
-
-bool g_nss_server_sockets_init = false;
-
-class NSSSSLServerInitSingleton {
- public:
- NSSSSLServerInitSingleton() {
- EnsureNSSSSLInit();
-
- SSL_ConfigServerSessionIDCache(64, 28800, 28800, NULL);
- g_nss_server_sockets_init = true;
- }
-
- ~NSSSSLServerInitSingleton() {
- SSL_ShutdownServerSessionIDCache();
- g_nss_server_sockets_init = false;
- }
-};
-
-static base::LazyInstance<NSSSSLServerInitSingleton>::Leaky
- g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
-
-class SSLServerSocketNSS : public SSLServerSocket {
- public:
- // See comments on CreateSSLServerSocket for details of how these
- // parameters are used.
- SSLServerSocketNSS(std::unique_ptr<StreamSocket> socket,
- X509Certificate* certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_server_config);
- ~SSLServerSocketNSS() override;
-
- // SSLServerSocket interface.
- int Handshake(const CompletionCallback& callback) override;
-
- // SSLSocket interface.
- int ExportKeyingMaterial(const base::StringPiece& label,
- bool has_context,
- const base::StringPiece& context,
- unsigned char* out,
- unsigned int outlen) override;
-
- // Socket interface (via StreamSocket).
- int Read(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) override;
- int Write(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) override;
- int SetReceiveBufferSize(int32_t size) override;
- int SetSendBufferSize(int32_t size) override;
-
- // StreamSocket implementation.
- int Connect(const CompletionCallback& callback) override;
- void Disconnect() override;
- bool IsConnected() const override;
- bool IsConnectedAndIdle() const override;
- int GetPeerAddress(IPEndPoint* address) const override;
- int GetLocalAddress(IPEndPoint* address) const override;
- const BoundNetLog& NetLog() const override;
- void SetSubresourceSpeculation() override;
- void SetOmniboxSpeculation() override;
- bool WasEverUsed() const override;
- bool WasNpnNegotiated() const override;
- NextProto GetNegotiatedProtocol() const override;
- bool GetSSLInfo(SSLInfo* ssl_info) override;
- void GetConnectionAttempts(ConnectionAttempts* out) const override;
- void ClearConnectionAttempts() override {}
- void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
- int64_t GetTotalReceivedBytes() const override;
-
- private:
- enum State {
- STATE_NONE,
- STATE_HANDSHAKE,
- };
-
- int InitializeSSLOptions();
-
- void OnSendComplete(int result);
- void OnRecvComplete(int result);
- void OnHandshakeIOComplete(int result);
-
- int BufferSend();
- void BufferSendComplete(int result);
- int BufferRecv();
- void BufferRecvComplete(int result);
- bool DoTransportIO();
- int DoPayloadRead();
- int DoPayloadWrite();
-
- int DoHandshakeLoop(int last_io_result);
- int DoReadLoop(int result);
- int DoWriteLoop(int result);
- int DoHandshake();
- void DoHandshakeCallback(int result);
- void DoReadCallback(int result);
- void DoWriteCallback(int result);
-
- static SECStatus OwnAuthCertHandler(void* arg,
- PRFileDesc* socket,
- PRBool checksig,
- PRBool is_server);
- static void HandshakeCallback(PRFileDesc* socket, void* arg);
-
- int Init();
-
- // Members used to send and receive buffer.
- bool transport_send_busy_;
- bool transport_recv_busy_;
-
- scoped_refptr<IOBuffer> recv_buffer_;
-
- BoundNetLog net_log_;
-
- CompletionCallback user_handshake_callback_;
- CompletionCallback user_read_callback_;
- CompletionCallback user_write_callback_;
-
- // Used by Read function.
- scoped_refptr<IOBuffer> user_read_buf_;
- int user_read_buf_len_;
-
- // Used by Write function.
- scoped_refptr<IOBuffer> user_write_buf_;
- int user_write_buf_len_;
-
- // The NSS SSL state machine
- PRFileDesc* nss_fd_;
-
- // Buffers for the network end of the SSL state machine
- memio_Private* nss_bufs_;
-
- // StreamSocket for sending and receiving data.
- std::unique_ptr<StreamSocket> transport_socket_;
-
- // Options for the SSL socket.
- SSLServerConfig ssl_server_config_;
-
- // Certificate for the server.
- scoped_refptr<X509Certificate> cert_;
-
- // Private key used by the server.
- std::unique_ptr<crypto::RSAPrivateKey> key_;
-
- State next_handshake_state_;
- bool completed_handshake_;
-
- DISALLOW_COPY_AND_ASSIGN(SSLServerSocketNSS);
-};
-
-SSLServerSocketNSS::SSLServerSocketNSS(
- std::unique_ptr<StreamSocket> transport_socket,
- X509Certificate* cert,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_server_config)
- : transport_send_busy_(false),
- transport_recv_busy_(false),
- user_read_buf_len_(0),
- user_write_buf_len_(0),
- nss_fd_(NULL),
- nss_bufs_(NULL),
- transport_socket_(std::move(transport_socket)),
- ssl_server_config_(ssl_server_config),
- cert_(cert),
- key_(key.Copy()),
- next_handshake_state_(STATE_NONE),
- completed_handshake_(false) {
- CHECK(key_);
-}
-
-SSLServerSocketNSS::~SSLServerSocketNSS() {
- if (nss_fd_ != NULL) {
- PR_Close(nss_fd_);
- nss_fd_ = NULL;
- }
-}
-
-int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
- net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
-
- int rv = Init();
- if (rv != OK) {
- LOG(ERROR) << "Failed to initialize NSS";
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
- return rv;
- }
-
- rv = InitializeSSLOptions();
- if (rv != OK) {
- LOG(ERROR) << "Failed to initialize SSL options";
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
- return rv;
- }
-
- // Set peer address. TODO(hclam): This should be in a separate method.
- PRNetAddr peername;
- memset(&peername, 0, sizeof(peername));
- peername.raw.family = AF_INET;
- memio_SetPeerName(nss_fd_, &peername);
-
- GotoState(STATE_HANDSHAKE);
- rv = DoHandshakeLoop(OK);
- if (rv == ERR_IO_PENDING) {
- user_handshake_callback_ = callback;
- } else {
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
- }
-
- return rv > OK ? OK : rv;
-}
-
-int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
- bool has_context,
- const base::StringPiece& context,
- unsigned char* out,
- unsigned int outlen) {
- if (!IsConnected())
- return ERR_SOCKET_NOT_CONNECTED;
- SECStatus result = SSL_ExportKeyingMaterial(
- nss_fd_, label.data(), label.size(), has_context,
- reinterpret_cast<const unsigned char*>(context.data()),
- context.length(), out, outlen);
- if (result != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
- return MapNSSError(PORT_GetError());
- }
- return OK;
-}
-
-int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
- NOTIMPLEMENTED();
- return ERR_NOT_IMPLEMENTED;
-}
-
-int SSLServerSocketNSS::Read(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) {
- DCHECK(user_read_callback_.is_null());
- DCHECK(user_handshake_callback_.is_null());
- DCHECK(!user_read_buf_);
- DCHECK(nss_bufs_);
- DCHECK(!callback.is_null());
-
- user_read_buf_ = buf;
- user_read_buf_len_ = buf_len;
-
- DCHECK(completed_handshake_);
-
- int rv = DoReadLoop(OK);
-
- if (rv == ERR_IO_PENDING) {
- user_read_callback_ = callback;
- } else {
- user_read_buf_ = NULL;
- user_read_buf_len_ = 0;
- }
- return rv;
-}
-
-int SSLServerSocketNSS::Write(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) {
- DCHECK(user_write_callback_.is_null());
- DCHECK(!user_write_buf_);
- DCHECK(nss_bufs_);
- DCHECK(!callback.is_null());
-
- user_write_buf_ = buf;
- user_write_buf_len_ = buf_len;
-
- int rv = DoWriteLoop(OK);
-
- if (rv == ERR_IO_PENDING) {
- user_write_callback_ = callback;
- } else {
- user_write_buf_ = NULL;
- user_write_buf_len_ = 0;
- }
- return rv;
-}
-
-int SSLServerSocketNSS::SetReceiveBufferSize(int32_t size) {
- return transport_socket_->SetReceiveBufferSize(size);
-}
-
-int SSLServerSocketNSS::SetSendBufferSize(int32_t size) {
- return transport_socket_->SetSendBufferSize(size);
-}
-
-bool SSLServerSocketNSS::IsConnected() const {
- // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
- // as well.
- return completed_handshake_;
-}
-
-void SSLServerSocketNSS::Disconnect() {
- transport_socket_->Disconnect();
-}
-
-bool SSLServerSocketNSS::IsConnectedAndIdle() const {
- return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
-}
-
-int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
- if (!IsConnected())
- return ERR_SOCKET_NOT_CONNECTED;
- return transport_socket_->GetPeerAddress(address);
-}
-
-int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
- if (!IsConnected())
- return ERR_SOCKET_NOT_CONNECTED;
- return transport_socket_->GetLocalAddress(address);
-}
-
-const BoundNetLog& SSLServerSocketNSS::NetLog() const {
- return net_log_;
-}
-
-void SSLServerSocketNSS::SetSubresourceSpeculation() {
- transport_socket_->SetSubresourceSpeculation();
-}
-
-void SSLServerSocketNSS::SetOmniboxSpeculation() {
- transport_socket_->SetOmniboxSpeculation();
-}
-
-bool SSLServerSocketNSS::WasEverUsed() const {
- return transport_socket_->WasEverUsed();
-}
-
-bool SSLServerSocketNSS::WasNpnNegotiated() const {
- NOTIMPLEMENTED();
- return false;
-}
-
-NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
- // NPN is not supported by this class.
- return kProtoUnknown;
-}
-
-bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
- NOTIMPLEMENTED();
- return false;
-}
-
-void SSLServerSocketNSS::GetConnectionAttempts(ConnectionAttempts* out) const {
- out->clear();
-}
-
-int64_t SSLServerSocketNSS::GetTotalReceivedBytes() const {
- NOTIMPLEMENTED();
- return 0;
-}
-
-int SSLServerSocketNSS::InitializeSSLOptions() {
- // Transport connected, now hook it up to nss
- nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
- if (nss_fd_ == NULL) {
- return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
- }
-
- // Grab pointer to buffers
- nss_bufs_ = memio_GetSecret(nss_fd_);
-
- /* Create SSL state machine */
- /* Push SSL onto our fake I/O socket */
- nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
- if (nss_fd_ == NULL) {
- LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
- return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
- }
- // TODO(port): set more ssl options! Check errors!
-
- int rv;
-
- if (ssl_server_config_.client_cert_type ==
- SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT) {
- rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet",
- "SSL_REQUEST_CERTIFICATE");
- return ERR_UNEXPECTED;
- }
- }
-
- rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
- return ERR_UNEXPECTED;
- }
-
- SSLVersionRange version_range;
- version_range.min = ssl_server_config_.version_min;
- version_range.max = ssl_server_config_.version_max;
- rv = SSL_VersionRangeSet(nss_fd_, &version_range);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
- return ERR_NO_SSL_VERSIONS_ENABLED;
- }
-
- if (ssl_server_config_.require_ecdhe) {
- const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
- const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
-
- // Iterate over the cipher suites and disable those that don't use ECDHE.
- for (unsigned i = 0; i < num_ciphers; i++) {
- SSLCipherSuiteInfo info;
- if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
- SECSuccess) {
- if (strcmp(info.keaTypeName, "ECDHE") != 0) {
- SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
- }
- }
- }
- }
-
- for (std::vector<uint16_t>::const_iterator it =
- ssl_server_config_.disabled_cipher_suites.begin();
- it != ssl_server_config_.disabled_cipher_suites.end(); ++it) {
- // This will fail if the specified cipher is not implemented by NSS, but
- // the failure is harmless.
- SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
- }
-
- // Server socket doesn't need session tickets.
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(
- net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
- }
-
- // Doing this will force PR_Accept perform handshake as server.
- rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
- return ERR_UNEXPECTED;
- }
-
- // Get a certificate of CERTCertificate structure.
- std::string der_string;
- if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
- return ERR_UNEXPECTED;
-
- SECItem der_cert;
- der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
- der_string.data()));
- der_cert.len = der_string.length();
- der_cert.type = siDERCertBuffer;
-
- // Parse into a CERTCertificate structure.
- CERTCertificate* cert = CERT_NewTempCertificate(
- CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
- if (!cert) {
- LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
- return MapNSSError(PORT_GetError());
- }
-
- // Get a key of SECKEYPrivateKey* structure.
- std::vector<uint8_t> key_vector;
- if (!key_->ExportPrivateKey(&key_vector)) {
- CERT_DestroyCertificate(cert);
- return ERR_UNEXPECTED;
- }
-
- SECKEYPrivateKeyStr* private_key = NULL;
- PK11SlotInfo* slot = PK11_GetInternalSlot();
- if (!slot) {
- CERT_DestroyCertificate(cert);
- return ERR_UNEXPECTED;
- }
-
- SECItem der_private_key_info;
- der_private_key_info.data =
- const_cast<unsigned char*>(&key_vector.front());
- der_private_key_info.len = key_vector.size();
- // The server's RSA private key must be imported into NSS with the
- // following key usage bits:
- // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
- // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
- // exchange algorithms.
- const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
- rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
- slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
- key_usage, &private_key, NULL);
- PK11_FreeSlot(slot);
- if (rv != SECSuccess) {
- CERT_DestroyCertificate(cert);
- return ERR_UNEXPECTED;
- }
-
- // Assign server certificate and private key.
- SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
- rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
- CERT_DestroyCertificate(cert);
- SECKEY_DestroyPrivateKey(private_key);
-
- if (rv != SECSuccess) {
- PRErrorCode prerr = PR_GetError();
- LOG(ERROR) << "Failed to config SSL server: " << prerr;
- LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
- return ERR_UNEXPECTED;
- }
-
- // Tell SSL we're a server; needed if not letting NSPR do socket I/O
- rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
- return ERR_UNEXPECTED;
- }
-
- return OK;
-}
-
-void SSLServerSocketNSS::OnSendComplete(int result) {
- if (next_handshake_state_ == STATE_HANDSHAKE) {
- // In handshake phase.
- OnHandshakeIOComplete(result);
- return;
- }
-
- // TODO(byungchul): This state machine is not correct. Copy the state machine
- // of SSLClientSocketNSS::OnSendComplete() which handles it better.
- if (!completed_handshake_)
- return;
-
- if (user_write_buf_) {
- int rv = DoWriteLoop(result);
- if (rv != ERR_IO_PENDING)
- DoWriteCallback(rv);
- } else {
- // Ensure that any queued ciphertext is flushed.
- DoTransportIO();
- }
-}
-
-void SSLServerSocketNSS::OnRecvComplete(int result) {
- if (next_handshake_state_ == STATE_HANDSHAKE) {
- // In handshake phase.
- OnHandshakeIOComplete(result);
- return;
- }
-
- // Network layer received some data, check if client requested to read
- // decrypted data.
- if (!user_read_buf_ || !completed_handshake_)
- return;
-
- int rv = DoReadLoop(result);
- if (rv != ERR_IO_PENDING)
- DoReadCallback(rv);
-}
-
-void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
- int rv = DoHandshakeLoop(result);
- if (rv == ERR_IO_PENDING)
- return;
-
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
- if (!user_handshake_callback_.is_null())
- DoHandshakeCallback(rv);
-}
-
-// Return 0 for EOF,
-// > 0 for bytes transferred immediately,
-// < 0 for error (or the non-error ERR_IO_PENDING).
-int SSLServerSocketNSS::BufferSend(void) {
- if (transport_send_busy_)
- return ERR_IO_PENDING;
-
- const char* buf1;
- const char* buf2;
- unsigned int len1, len2;
- if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
- // The error code itself is ignored, so just return ERR_ABORTED.
- return ERR_ABORTED;
- }
- const size_t len = len1 + len2;
-
- int rv = 0;
- if (len) {
- scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
- memcpy(send_buffer->data(), buf1, len1);
- memcpy(send_buffer->data() + len1, buf2, len2);
- rv = transport_socket_->Write(
- send_buffer.get(), len,
- base::Bind(&SSLServerSocketNSS::BufferSendComplete,
- base::Unretained(this)));
- if (rv == ERR_IO_PENDING) {
- transport_send_busy_ = true;
- } else {
- memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
- }
- }
-
- return rv;
-}
-
-void SSLServerSocketNSS::BufferSendComplete(int result) {
- memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
- transport_send_busy_ = false;
- OnSendComplete(result);
-}
-
-int SSLServerSocketNSS::BufferRecv(void) {
- if (transport_recv_busy_) return ERR_IO_PENDING;
-
- char* buf;
- int nb = memio_GetReadParams(nss_bufs_, &buf);
- int rv;
- if (!nb) {
- // buffer too full to read into, so no I/O possible at moment
- rv = ERR_IO_PENDING;
- } else {
- recv_buffer_ = new IOBuffer(nb);
- rv = transport_socket_->Read(
- recv_buffer_.get(), nb,
- base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
- base::Unretained(this)));
- if (rv == ERR_IO_PENDING) {
- transport_recv_busy_ = true;
- } else {
- if (rv > 0)
- memcpy(buf, recv_buffer_->data(), rv);
- memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
- recv_buffer_ = NULL;
- }
- }
- return rv;
-}
-
-void SSLServerSocketNSS::BufferRecvComplete(int result) {
- if (result > 0) {
- char* buf;
- memio_GetReadParams(nss_bufs_, &buf);
- memcpy(buf, recv_buffer_->data(), result);
- }
- recv_buffer_ = NULL;
- memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
- transport_recv_busy_ = false;
- OnRecvComplete(result);
-}
-
-// Do as much network I/O as possible between the buffer and the
-// transport socket. Return true if some I/O performed, false
-// otherwise (error or ERR_IO_PENDING).
-bool SSLServerSocketNSS::DoTransportIO() {
- bool network_moved = false;
- if (nss_bufs_ != NULL) {
- int rv;
- // Read and write as much data as we can. The loop is neccessary
- // because Write() may return synchronously.
- do {
- rv = BufferSend();
- if (rv > 0)
- network_moved = true;
- } while (rv > 0);
- if (BufferRecv() >= 0)
- network_moved = true;
- }
- return network_moved;
-}
-
-int SSLServerSocketNSS::DoPayloadRead() {
- DCHECK(user_read_buf_);
- DCHECK_GT(user_read_buf_len_, 0);
- int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
- if (rv >= 0)
- return rv;
- PRErrorCode prerr = PR_GetError();
- if (prerr == PR_WOULD_BLOCK_ERROR) {
- return ERR_IO_PENDING;
- }
- rv = MapNSSError(prerr);
- net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
- CreateNetLogSSLErrorCallback(rv, prerr));
- return rv;
-}
-
-int SSLServerSocketNSS::DoPayloadWrite() {
- DCHECK(user_write_buf_);
- int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
- if (rv >= 0)
- return rv;
- PRErrorCode prerr = PR_GetError();
- if (prerr == PR_WOULD_BLOCK_ERROR) {
- return ERR_IO_PENDING;
- }
- rv = MapNSSError(prerr);
- net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
- CreateNetLogSSLErrorCallback(rv, prerr));
- return rv;
-}
-
-int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
- int rv = last_io_result;
- do {
- // Default to STATE_NONE for next state.
- // (This is a quirk carried over from the windows
- // implementation. It makes reading the logs a bit harder.)
- // State handlers can and often do call GotoState just
- // to stay in the current state.
- State state = next_handshake_state_;
- GotoState(STATE_NONE);
- switch (state) {
- case STATE_HANDSHAKE:
- rv = DoHandshake();
- break;
- case STATE_NONE:
- default:
- rv = ERR_UNEXPECTED;
- LOG(DFATAL) << "unexpected state " << state;
- break;
- }
-
- // Do the actual network I/O
- bool network_moved = DoTransportIO();
- if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
- // In general we exit the loop if rv is ERR_IO_PENDING. In this
- // special case we keep looping even if rv is ERR_IO_PENDING because
- // the transport IO may allow DoHandshake to make progress.
- rv = OK; // This causes us to stay in the loop.
- }
- } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
- return rv;
-}
-
-int SSLServerSocketNSS::DoReadLoop(int result) {
- DCHECK(completed_handshake_);
- DCHECK(next_handshake_state_ == STATE_NONE);
-
- if (result < 0)
- return result;
-
- if (!nss_bufs_) {
- LOG(DFATAL) << "!nss_bufs_";
- int rv = ERR_UNEXPECTED;
- net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
- CreateNetLogSSLErrorCallback(rv, 0));
- return rv;
- }
-
- bool network_moved;
- int rv;
- do {
- rv = DoPayloadRead();
- network_moved = DoTransportIO();
- } while (rv == ERR_IO_PENDING && network_moved);
- return rv;
-}
-
-int SSLServerSocketNSS::DoWriteLoop(int result) {
- DCHECK(completed_handshake_);
- DCHECK_EQ(next_handshake_state_, STATE_NONE);
-
- if (result < 0)
- return result;
-
- if (!nss_bufs_) {
- LOG(DFATAL) << "!nss_bufs_";
- int rv = ERR_UNEXPECTED;
- net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
- CreateNetLogSSLErrorCallback(rv, 0));
- return rv;
- }
-
- bool network_moved;
- int rv;
- do {
- rv = DoPayloadWrite();
- network_moved = DoTransportIO();
- } while (rv == ERR_IO_PENDING && network_moved);
- return rv;
-}
-
-int SSLServerSocketNSS::DoHandshake() {
- int net_error = OK;
- SECStatus rv = SSL_ForceHandshake(nss_fd_);
-
- if (rv == SECSuccess) {
- completed_handshake_ = true;
- } else {
- PRErrorCode prerr = PR_GetError();
- net_error = MapNSSError(prerr);
-
- // If not done, stay in this state
- if (net_error == ERR_IO_PENDING) {
- GotoState(STATE_HANDSHAKE);
- } else {
- LOG(ERROR) << "handshake failed; NSS error code " << prerr
- << ", net_error " << net_error;
- net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
- CreateNetLogSSLErrorCallback(net_error, prerr));
- }
- }
- return net_error;
-}
-
-void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
- DCHECK_NE(rv, ERR_IO_PENDING);
- base::ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
-}
-
-void SSLServerSocketNSS::DoReadCallback(int rv) {
- DCHECK(rv != ERR_IO_PENDING);
- DCHECK(!user_read_callback_.is_null());
-
- user_read_buf_ = NULL;
- user_read_buf_len_ = 0;
- base::ResetAndReturn(&user_read_callback_).Run(rv);
-}
-
-void SSLServerSocketNSS::DoWriteCallback(int rv) {
- DCHECK(rv != ERR_IO_PENDING);
- DCHECK(!user_write_callback_.is_null());
-
- user_write_buf_ = NULL;
- user_write_buf_len_ = 0;
- base::ResetAndReturn(&user_write_callback_).Run(rv);
-}
-
-// static
-// NSS calls this if an incoming certificate needs to be verified.
-// Do nothing but return SECSuccess.
-// This is called only in full handshake mode.
-// Peer certificate is retrieved in HandshakeCallback() later, which is called
-// in full handshake mode or in resumption handshake mode.
-SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
- PRFileDesc* socket,
- PRBool checksig,
- PRBool is_server) {
- // TODO(hclam): Implement.
- // Tell NSS to not verify the certificate.
- return SECSuccess;
-}
-
-// static
-// NSS calls this when handshake is completed.
-// After the SSL handshake is finished we need to verify the certificate.
-void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, void* arg) {
- // TODO(hclam): Implement.
-}
-
-int SSLServerSocketNSS::Init() {
- // Initialize the NSS SSL library in a threadsafe way. This also
- // initializes the NSS base library.
- EnsureNSSSSLInit();
- if (!NSS_IsInitialized())
- return ERR_UNEXPECTED;
-
- EnableSSLServerSockets();
- return OK;
-}
-
-} // namespace
-
-std::unique_ptr<SSLServerContext> CreateSSLServerContext(
- X509Certificate* certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_server_config) {
- return std::unique_ptr<SSLServerContext>(
- new SSLServerContextNSS(certificate, key, ssl_server_config));
-}
-
-SSLServerContextNSS::SSLServerContextNSS(
- X509Certificate* certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_server_config)
- : ssl_server_config_(ssl_server_config),
- cert_(certificate),
- key_(key.Copy()) {
- CHECK(key_);
-}
-
-SSLServerContextNSS::~SSLServerContextNSS() {}
-
-std::unique_ptr<SSLServerSocket> SSLServerContextNSS::CreateSSLServerSocket(
- std::unique_ptr<StreamSocket> socket) {
- DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
- << " called yet!";
-
- return std::unique_ptr<SSLServerSocket>(new SSLServerSocketNSS(
- std::move(socket), cert_.get(), *key_, ssl_server_config_));
-}
-
-void EnableSSLServerSockets() {
- g_nss_ssl_server_init_singleton.Get();
-}
-
-} // namespace net
« no previous file with comments | « net/socket/ssl_server_socket_nss.h ('k') | net/socket/ssl_server_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698