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

Unified Diff: net/socket/ssl_server_socket_openssl.cc

Issue 1518613002: Support for server session cache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@client_certs
Patch Set: Added a missing period. Created 4 years, 10 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
Index: net/socket/ssl_server_socket_openssl.cc
diff --git a/net/socket/ssl_server_socket_openssl.cc b/net/socket/ssl_server_socket_openssl.cc
index adde711e7ec9f2ff27bd2cfbfba16ea69e55aae9..75a76da205b04ee514235352bb008d2c654de359 100644
--- a/net/socket/ssl_server_socket_openssl.cc
+++ b/net/socket/ssl_server_socket_openssl.cc
@@ -19,7 +19,6 @@
#include "net/cert/client_cert_verifier.h"
#include "net/cert/x509_util_openssl.h"
#include "net/ssl/openssl_ssl_util.h"
-#include "net/ssl/scoped_openssl_types.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h"
@@ -52,43 +51,142 @@ scoped_refptr<X509Certificate> CreateX509Certificate(X509* cert,
return X509Certificate::CreateFromDERCertChain(der_chain);
}
-} // namespace
-
-void EnableSSLServerSockets() {
- // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit().
-}
-
-scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
- scoped_ptr<StreamSocket> socket,
- X509Certificate* certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_server_config) {
- crypto::EnsureOpenSSLInit();
- return scoped_ptr<SSLServerSocket>(new SSLServerSocketOpenSSL(
- std::move(socket), certificate, key, ssl_server_config));
-}
+class SSLServerSocketOpenSSL : public SSLServerSocket {
+ public:
+ // See comments on CreateSSLServerSocket for details of how these
+ // parameters are used.
+ SSLServerSocketOpenSSL(scoped_ptr<StreamSocket> socket, SSL* ssl);
+ ~SSLServerSocketOpenSSL() 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;
+ int GetTLSUniqueChannelBinding(std::string* out) 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 UsingTCPFastOpen() 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;
+ static int CertVerifyCallback(X509_STORE_CTX* store_ctx, void* arg);
+
+ private:
+ enum State {
+ STATE_NONE,
+ STATE_HANDSHAKE,
+ };
+
+ void OnSendComplete(int result);
+ void OnRecvComplete(int result);
+ void OnHandshakeIOComplete(int result);
+
+ int BufferSend();
+ void BufferSendComplete(int result);
+ void TransportWriteComplete(int result);
+ int BufferRecv();
+ void BufferRecvComplete(int result);
+ int TransportReadComplete(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);
+
+ int Init();
+ void ExtractClientCert();
+
+ // Members used to send and receive buffer.
+ bool transport_send_busy_;
+ bool transport_recv_busy_;
+ bool transport_recv_eof_;
+
+ scoped_refptr<DrainableIOBuffer> send_buffer_;
+ 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_;
+
+ // Used by TransportWriteComplete() and TransportReadComplete() to signify an
+ // error writing to the transport socket. A value of OK indicates no error.
+ int transport_write_error_;
+
+ // OpenSSL stuff
+ SSL* ssl_;
+ BIO* transport_bio_;
+
+ // StreamSocket for sending and receiving data.
+ scoped_ptr<StreamSocket> transport_socket_;
+
+ // Certificate for the client.
+ scoped_refptr<X509Certificate> client_cert_;
+
+ State next_handshake_state_;
+ bool completed_handshake_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLServerSocketOpenSSL);
+};
SSLServerSocketOpenSSL::SSLServerSocketOpenSSL(
scoped_ptr<StreamSocket> transport_socket,
- scoped_refptr<X509Certificate> certificate,
- const crypto::RSAPrivateKey& key,
- const SSLServerConfig& ssl_server_config)
+ SSL* ssl)
: transport_send_busy_(false),
transport_recv_busy_(false),
transport_recv_eof_(false),
user_read_buf_len_(0),
user_write_buf_len_(0),
transport_write_error_(OK),
- ssl_(NULL),
+ ssl_(ssl),
transport_bio_(NULL),
transport_socket_(std::move(transport_socket)),
- ssl_server_config_(ssl_server_config),
- cert_(certificate),
- key_(key.Copy()),
next_handshake_state_(STATE_NONE),
- completed_handshake_(false) {
- CHECK(key_);
-}
+ completed_handshake_(false) {}
SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() {
if (ssl_) {
@@ -160,7 +258,8 @@ int SSLServerSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
return ERR_NOT_IMPLEMENTED;
}
-int SSLServerSocketOpenSSL::Read(IOBuffer* buf, int buf_len,
+int SSLServerSocketOpenSSL::Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) {
DCHECK(user_read_callback_.is_null());
DCHECK(user_handshake_callback_.is_null());
@@ -184,7 +283,8 @@ int SSLServerSocketOpenSSL::Read(IOBuffer* buf, int buf_len,
return rv;
}
-int SSLServerSocketOpenSSL::Write(IOBuffer* buf, int buf_len,
+int SSLServerSocketOpenSSL::Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) {
DCHECK(user_write_callback_.is_null());
DCHECK(!user_write_buf_);
@@ -377,8 +477,7 @@ int SSLServerSocketOpenSSL::BufferSend() {
}
int rv = transport_socket_->Write(
- send_buffer_.get(),
- send_buffer_->BytesRemaining(),
+ send_buffer_.get(), send_buffer_->BytesRemaining(),
base::Bind(&SSLServerSocketOpenSSL::BufferSendComplete,
base::Unretained(this)));
if (rv == ERR_IO_PENDING) {
@@ -450,8 +549,7 @@ int SSLServerSocketOpenSSL::BufferRecv() {
recv_buffer_ = new IOBuffer(max_write);
int rv = transport_socket_->Read(
- recv_buffer_.get(),
- max_write,
+ recv_buffer_.get(), max_write,
base::Bind(&SSLServerSocketOpenSSL::BufferRecvComplete,
base::Unretained(this)));
if (rv == ERR_IO_PENDING) {
@@ -681,27 +779,10 @@ void SSLServerSocketOpenSSL::DoWriteCallback(int rv) {
}
int SSLServerSocketOpenSSL::Init() {
- DCHECK(!ssl_);
DCHECK(!transport_bio_);
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedSSL_CTX ssl_ctx(SSL_CTX_new(TLS_method()));
- int verify_mode = 0;
- switch (ssl_server_config_.client_cert_type) {
- case SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT:
- verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- // Fall-through
- case SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT:
- verify_mode |= SSL_VERIFY_PEER;
- SSL_CTX_set_verify(ssl_ctx.get(), verify_mode, nullptr);
- SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), CertVerifyCallback,
- ssl_server_config_.client_cert_verifier);
- break;
- case SSLServerConfig::ClientCertType::NO_CLIENT_CERT:
- break;
- }
- ssl_ = SSL_new(ssl_ctx.get());
if (!ssl_)
return ERR_UNEXPECTED;
@@ -714,59 +795,122 @@ int SSLServerSocketOpenSSL::Init() {
SSL_set_bio(ssl_, ssl_bio, ssl_bio);
+ return OK;
+}
+
+// static
+int SSLServerSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx,
+ void* arg) {
+ ClientCertVerifier* verifier = reinterpret_cast<ClientCertVerifier*>(arg);
+ // If a verifier was not supplied, all certificates are accepted.
+ if (!verifier)
+ return 1;
+ STACK_OF(X509)* chain = store_ctx->untrusted;
+ scoped_refptr<X509Certificate> client_cert(
+ CreateX509Certificate(nullptr, chain));
+ if (!client_cert.get()) {
+ X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED);
+ return 0;
+ }
+ // Asynchronous completion of Verify is currently not supported.
+ // http://crbug.com/347402
+ // The API for Verify supports the parts needed for async completion
+ // but is currently expected to complete synchronously.
+ scoped_ptr<ClientCertVerifier::Request> ignore_async;
+ int res =
+ verifier->Verify(client_cert.get(), CompletionCallback(), &ignore_async);
+ DCHECK_NE(res, ERR_IO_PENDING);
+
+ if (res != OK) {
+ X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED);
+ return 0;
+ }
+ return 1;
+}
+
+} // namespace
+
+scoped_ptr<SSLServerContext> CreateSSLServerContext(
+ X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config) {
+ return scoped_ptr<SSLServerContext>(
+ new SSLServerContextOpenSSL(certificate, key, ssl_server_config));
+}
+
+SSLServerContextOpenSSL::SSLServerContextOpenSSL(
+ X509Certificate* certificate,
+ const crypto::RSAPrivateKey& key,
+ const SSLServerConfig& ssl_server_config)
+ : ssl_server_config_(ssl_server_config),
+ cert_(certificate),
+ key_(key.Copy()) {
+ CHECK(key_);
+ crypto::EnsureOpenSSLInit();
+ ssl_ctx_.reset(SSL_CTX_new(TLS_method()));
+ SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_SERVER);
+ uint8_t session_ctx_id = 0;
+ SSL_CTX_set_session_id_context(ssl_ctx_.get(), &session_ctx_id,
+ sizeof(session_ctx_id));
+
+ int verify_mode = 0;
+ switch (ssl_server_config_.client_cert_type) {
+ case SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT:
+ verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ // Fall-through
+ case SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT:
+ verify_mode |= SSL_VERIFY_PEER;
+ SSL_CTX_set_verify(ssl_ctx_.get(), verify_mode, nullptr);
+ SSL_CTX_set_cert_verify_callback(
+ ssl_ctx_.get(), SSLServerSocketOpenSSL::CertVerifyCallback,
+ ssl_server_config_.client_cert_verifier);
+ break;
+ case SSLServerConfig::ClientCertType::NO_CLIENT_CERT:
+ break;
+ }
+
// Set certificate and private key.
DCHECK(cert_->os_cert_handle());
#if defined(USE_OPENSSL_CERTS)
- if (SSL_use_certificate(ssl_, cert_->os_cert_handle()) != 1) {
- LOG(ERROR) << "Cannot set certificate.";
- return ERR_UNEXPECTED;
- }
+ CHECK(SSL_CTX_use_certificate(ssl_ctx_.get(), cert_->os_cert_handle()));
#else
// Convert OSCertHandle to X509 structure.
std::string der_string;
- if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
- return ERR_UNEXPECTED;
+ CHECK(X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string));
const unsigned char* der_string_array =
reinterpret_cast<const unsigned char*>(der_string.data());
ScopedX509 x509(d2i_X509(NULL, &der_string_array, der_string.length()));
- if (!x509)
- return ERR_UNEXPECTED;
+ CHECK(x509);
- // On success, SSL_use_certificate acquires a reference to |x509|.
- if (SSL_use_certificate(ssl_, x509.get()) != 1) {
- LOG(ERROR) << "Cannot set certificate.";
- return ERR_UNEXPECTED;
- }
+ // On success, SSL_CTX_use_certificate acquires a reference to |x509|.
+ CHECK(SSL_CTX_use_certificate(ssl_ctx_.get(), x509.get()));
#endif // USE_OPENSSL_CERTS
DCHECK(key_->key());
- if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) {
- LOG(ERROR) << "Cannot set private key.";
- return ERR_UNEXPECTED;
- }
+ CHECK(SSL_CTX_use_PrivateKey(ssl_ctx_.get(), key_->key()));
DCHECK_LT(SSL3_VERSION, ssl_server_config_.version_min);
DCHECK_LT(SSL3_VERSION, ssl_server_config_.version_max);
- SSL_set_min_version(ssl_, ssl_server_config_.version_min);
- SSL_set_max_version(ssl_, ssl_server_config_.version_max);
+ SSL_CTX_set_min_version(ssl_ctx_.get(), ssl_server_config_.version_min);
+ SSL_CTX_set_max_version(ssl_ctx_.get(), ssl_server_config_.version_max);
// OpenSSL defaults some options to on, others to off. To avoid ambiguity,
// set everything we care about to an absolute value.
SslSetClearMask options;
options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);
- SSL_set_options(ssl_, options.set_mask);
- SSL_clear_options(ssl_, options.clear_mask);
+ SSL_CTX_set_options(ssl_ctx_.get(), options.set_mask);
+ SSL_CTX_clear_options(ssl_ctx_.get(), options.clear_mask);
// Same as above, this time for the SSL mode.
SslSetClearMask mode;
mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
- SSL_set_mode(ssl_, mode.set_mask);
- SSL_clear_mode(ssl_, mode.clear_mask);
+ SSL_CTX_set_mode(ssl_ctx_.get(), mode.set_mask);
+ SSL_CTX_clear_mode(ssl_ctx_.get(), mode.clear_mask);
// See SSLServerConfig::disabled_cipher_suites for description of the suites
// disabled by default. Note that !SHA256 and !SHA384 only remove HMAC-SHA256
@@ -786,7 +930,7 @@ int SSLServerSocketOpenSSL::Init() {
}
}
- int rv = SSL_set_cipher_list(ssl_, command.c_str());
+ int rv = SSL_CTX_set_cipher_list(ssl_ctx_.get(), command.c_str());
// If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
// This will almost certainly result in the socket failing to complete the
// handshake at which point the appropriate error is bubbled up to the client.
@@ -801,44 +945,24 @@ int SSLServerSocketOpenSSL::Init() {
const uint8_t* name = reinterpret_cast<const uint8_t*>(authority.c_str());
const uint8_t* name_start = name;
ScopedX509_NAME subj(d2i_X509_NAME(nullptr, &name, authority.length()));
- if (!subj || name != name_start + authority.length())
- return ERR_UNEXPECTED;
+ CHECK(subj && name == name_start + authority.length());
sk_X509_NAME_push(stack.get(), subj.release());
}
- SSL_set_client_CA_list(ssl_, stack.release());
+ SSL_CTX_set_client_CA_list(ssl_ctx_.get(), stack.release());
}
-
- return OK;
}
-// static
-int SSLServerSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx,
- void* arg) {
- ClientCertVerifier* verifier = reinterpret_cast<ClientCertVerifier*>(arg);
- // If a verifier was not supplied, all certificates are accepted.
- if (!verifier)
- return 1;
- STACK_OF(X509)* chain = store_ctx->untrusted;
- scoped_refptr<X509Certificate> client_cert(
- CreateX509Certificate(nullptr, chain));
- if (!client_cert.get()) {
- X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED);
- return 0;
- }
- // Asynchronous completion of Verify is currently not supported.
- // http://crbug.com/347402
- // The API for Verify supports the parts needed for async completion
- // but is currently expected to complete synchronously.
- scoped_ptr<ClientCertVerifier::Request> ignore_async;
- int res =
- verifier->Verify(client_cert.get(), CompletionCallback(), &ignore_async);
- DCHECK_NE(res, ERR_IO_PENDING);
+SSLServerContextOpenSSL::~SSLServerContextOpenSSL() {}
- if (res != OK) {
- X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED);
- return 0;
- }
- return 1;
+scoped_ptr<SSLServerSocket> SSLServerContextOpenSSL::CreateSSLServerSocket(
+ scoped_ptr<StreamSocket> socket) {
+ SSL* ssl = SSL_new(ssl_ctx_.get());
+ return scoped_ptr<SSLServerSocket>(
+ new SSLServerSocketOpenSSL(std::move(socket), ssl));
+}
+
+void EnableSSLServerSockets() {
+ // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit().
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698