Roll tools/swarming_client/ to b61a1802f5ef4bb8c7b81060cc80add47e6cf302.
[chromium-blink-merge.git] / net / socket / ssl_server_socket_openssl.cc
blob6bc13e6a3469942dcf75cd31ee29be8185780980
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/socket/ssl_server_socket_openssl.h"
7 #include <openssl/err.h>
8 #include <openssl/ssl.h>
10 #include "base/callback_helpers.h"
11 #include "base/logging.h"
12 #include "crypto/openssl_util.h"
13 #include "crypto/rsa_private_key.h"
14 #include "crypto/scoped_openssl_types.h"
15 #include "net/base/net_errors.h"
16 #include "net/ssl/openssl_ssl_util.h"
17 #include "net/ssl/scoped_openssl_types.h"
19 #define GotoState(s) next_handshake_state_ = s
21 namespace net {
23 void EnableSSLServerSockets() {
24 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit().
27 scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
28 scoped_ptr<StreamSocket> socket,
29 X509Certificate* certificate,
30 crypto::RSAPrivateKey* key,
31 const SSLConfig& ssl_config) {
32 crypto::EnsureOpenSSLInit();
33 return scoped_ptr<SSLServerSocket>(
34 new SSLServerSocketOpenSSL(socket.Pass(), certificate, key, ssl_config));
37 SSLServerSocketOpenSSL::SSLServerSocketOpenSSL(
38 scoped_ptr<StreamSocket> transport_socket,
39 scoped_refptr<X509Certificate> certificate,
40 crypto::RSAPrivateKey* key,
41 const SSLConfig& ssl_config)
42 : transport_send_busy_(false),
43 transport_recv_busy_(false),
44 transport_recv_eof_(false),
45 user_read_buf_len_(0),
46 user_write_buf_len_(0),
47 transport_write_error_(OK),
48 ssl_(NULL),
49 transport_bio_(NULL),
50 transport_socket_(transport_socket.Pass()),
51 ssl_config_(ssl_config),
52 cert_(certificate),
53 next_handshake_state_(STATE_NONE),
54 completed_handshake_(false) {
55 // TODO(byungchul): Need a better way to clone a key.
56 std::vector<uint8> key_bytes;
57 CHECK(key->ExportPrivateKey(&key_bytes));
58 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
59 CHECK(key_.get());
62 SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() {
63 if (ssl_) {
64 // Calling SSL_shutdown prevents the session from being marked as
65 // unresumable.
66 SSL_shutdown(ssl_);
67 SSL_free(ssl_);
68 ssl_ = NULL;
70 if (transport_bio_) {
71 BIO_free_all(transport_bio_);
72 transport_bio_ = NULL;
76 int SSLServerSocketOpenSSL::Handshake(const CompletionCallback& callback) {
77 net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
79 // Set up new ssl object.
80 int rv = Init();
81 if (rv != OK) {
82 LOG(ERROR) << "Failed to initialize OpenSSL: rv=" << rv;
83 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
84 return rv;
87 // Set SSL to server mode. Handshake happens in the loop below.
88 SSL_set_accept_state(ssl_);
90 GotoState(STATE_HANDSHAKE);
91 rv = DoHandshakeLoop(OK);
92 if (rv == ERR_IO_PENDING) {
93 user_handshake_callback_ = callback;
94 } else {
95 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
98 return rv > OK ? OK : rv;
101 int SSLServerSocketOpenSSL::ExportKeyingMaterial(
102 const base::StringPiece& label,
103 bool has_context,
104 const base::StringPiece& context,
105 unsigned char* out,
106 unsigned int outlen) {
107 if (!IsConnected())
108 return ERR_SOCKET_NOT_CONNECTED;
110 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
112 int rv = SSL_export_keying_material(
113 ssl_, out, outlen, label.data(), label.size(),
114 reinterpret_cast<const unsigned char*>(context.data()),
115 context.length(), context.length() > 0);
117 if (rv != 1) {
118 int ssl_error = SSL_get_error(ssl_, rv);
119 LOG(ERROR) << "Failed to export keying material;"
120 << " returned " << rv
121 << ", SSL error code " << ssl_error;
122 return MapOpenSSLError(ssl_error, err_tracer);
124 return OK;
127 int SSLServerSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
128 NOTIMPLEMENTED();
129 return ERR_NOT_IMPLEMENTED;
132 int SSLServerSocketOpenSSL::Read(IOBuffer* buf, int buf_len,
133 const CompletionCallback& callback) {
134 DCHECK(user_read_callback_.is_null());
135 DCHECK(user_handshake_callback_.is_null());
136 DCHECK(!user_read_buf_.get());
137 DCHECK(!callback.is_null());
139 user_read_buf_ = buf;
140 user_read_buf_len_ = buf_len;
142 DCHECK(completed_handshake_);
144 int rv = DoReadLoop(OK);
146 if (rv == ERR_IO_PENDING) {
147 user_read_callback_ = callback;
148 } else {
149 user_read_buf_ = NULL;
150 user_read_buf_len_ = 0;
153 return rv;
156 int SSLServerSocketOpenSSL::Write(IOBuffer* buf, int buf_len,
157 const CompletionCallback& callback) {
158 DCHECK(user_write_callback_.is_null());
159 DCHECK(!user_write_buf_.get());
160 DCHECK(!callback.is_null());
162 user_write_buf_ = buf;
163 user_write_buf_len_ = buf_len;
165 int rv = DoWriteLoop(OK);
167 if (rv == ERR_IO_PENDING) {
168 user_write_callback_ = callback;
169 } else {
170 user_write_buf_ = NULL;
171 user_write_buf_len_ = 0;
173 return rv;
176 int SSLServerSocketOpenSSL::SetReceiveBufferSize(int32 size) {
177 return transport_socket_->SetReceiveBufferSize(size);
180 int SSLServerSocketOpenSSL::SetSendBufferSize(int32 size) {
181 return transport_socket_->SetSendBufferSize(size);
184 int SSLServerSocketOpenSSL::Connect(const CompletionCallback& callback) {
185 NOTIMPLEMENTED();
186 return ERR_NOT_IMPLEMENTED;
189 void SSLServerSocketOpenSSL::Disconnect() {
190 transport_socket_->Disconnect();
193 bool SSLServerSocketOpenSSL::IsConnected() const {
194 // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
195 // as well.
196 return completed_handshake_;
199 bool SSLServerSocketOpenSSL::IsConnectedAndIdle() const {
200 return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
203 int SSLServerSocketOpenSSL::GetPeerAddress(IPEndPoint* address) const {
204 if (!IsConnected())
205 return ERR_SOCKET_NOT_CONNECTED;
206 return transport_socket_->GetPeerAddress(address);
209 int SSLServerSocketOpenSSL::GetLocalAddress(IPEndPoint* address) const {
210 if (!IsConnected())
211 return ERR_SOCKET_NOT_CONNECTED;
212 return transport_socket_->GetLocalAddress(address);
215 const BoundNetLog& SSLServerSocketOpenSSL::NetLog() const {
216 return net_log_;
219 void SSLServerSocketOpenSSL::SetSubresourceSpeculation() {
220 transport_socket_->SetSubresourceSpeculation();
223 void SSLServerSocketOpenSSL::SetOmniboxSpeculation() {
224 transport_socket_->SetOmniboxSpeculation();
227 bool SSLServerSocketOpenSSL::WasEverUsed() const {
228 return transport_socket_->WasEverUsed();
231 bool SSLServerSocketOpenSSL::UsingTCPFastOpen() const {
232 return transport_socket_->UsingTCPFastOpen();
235 bool SSLServerSocketOpenSSL::WasNpnNegotiated() const {
236 NOTIMPLEMENTED();
237 return false;
240 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const {
241 // NPN is not supported by this class.
242 return kProtoUnknown;
245 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
246 NOTIMPLEMENTED();
247 return false;
250 void SSLServerSocketOpenSSL::OnSendComplete(int result) {
251 if (next_handshake_state_ == STATE_HANDSHAKE) {
252 // In handshake phase.
253 OnHandshakeIOComplete(result);
254 return;
257 // TODO(byungchul): This state machine is not correct. Copy the state machine
258 // of SSLClientSocketOpenSSL::OnSendComplete() which handles it better.
259 if (!completed_handshake_)
260 return;
262 if (user_write_buf_.get()) {
263 int rv = DoWriteLoop(result);
264 if (rv != ERR_IO_PENDING)
265 DoWriteCallback(rv);
266 } else {
267 // Ensure that any queued ciphertext is flushed.
268 DoTransportIO();
272 void SSLServerSocketOpenSSL::OnRecvComplete(int result) {
273 if (next_handshake_state_ == STATE_HANDSHAKE) {
274 // In handshake phase.
275 OnHandshakeIOComplete(result);
276 return;
279 // Network layer received some data, check if client requested to read
280 // decrypted data.
281 if (!user_read_buf_.get() || !completed_handshake_)
282 return;
284 int rv = DoReadLoop(result);
285 if (rv != ERR_IO_PENDING)
286 DoReadCallback(rv);
289 void SSLServerSocketOpenSSL::OnHandshakeIOComplete(int result) {
290 int rv = DoHandshakeLoop(result);
291 if (rv == ERR_IO_PENDING)
292 return;
294 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
295 if (!user_handshake_callback_.is_null())
296 DoHandshakeCallback(rv);
299 // Return 0 for EOF,
300 // > 0 for bytes transferred immediately,
301 // < 0 for error (or the non-error ERR_IO_PENDING).
302 int SSLServerSocketOpenSSL::BufferSend() {
303 if (transport_send_busy_)
304 return ERR_IO_PENDING;
306 if (!send_buffer_.get()) {
307 // Get a fresh send buffer out of the send BIO.
308 size_t max_read = BIO_pending(transport_bio_);
309 if (!max_read)
310 return 0; // Nothing pending in the OpenSSL write BIO.
311 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
312 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
313 DCHECK_GT(read_bytes, 0);
314 CHECK_EQ(static_cast<int>(max_read), read_bytes);
317 int rv = transport_socket_->Write(
318 send_buffer_.get(),
319 send_buffer_->BytesRemaining(),
320 base::Bind(&SSLServerSocketOpenSSL::BufferSendComplete,
321 base::Unretained(this)));
322 if (rv == ERR_IO_PENDING) {
323 transport_send_busy_ = true;
324 } else {
325 TransportWriteComplete(rv);
327 return rv;
330 void SSLServerSocketOpenSSL::BufferSendComplete(int result) {
331 transport_send_busy_ = false;
332 TransportWriteComplete(result);
333 OnSendComplete(result);
336 void SSLServerSocketOpenSSL::TransportWriteComplete(int result) {
337 DCHECK(ERR_IO_PENDING != result);
338 if (result < 0) {
339 // Got a socket write error; close the BIO to indicate this upward.
341 // TODO(davidben): The value of |result| gets lost. Feed the error back into
342 // the BIO so it gets (re-)detected in OnSendComplete. Perhaps with
343 // BIO_set_callback.
344 DVLOG(1) << "TransportWriteComplete error " << result;
345 (void)BIO_shutdown_wr(SSL_get_wbio(ssl_));
347 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads
348 // from the socket after a write error.
350 // TODO(davidben): Avoid having read and write ends interact this way.
351 transport_write_error_ = result;
352 (void)BIO_shutdown_wr(transport_bio_);
353 send_buffer_ = NULL;
354 } else {
355 DCHECK(send_buffer_.get());
356 send_buffer_->DidConsume(result);
357 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
358 if (send_buffer_->BytesRemaining() <= 0)
359 send_buffer_ = NULL;
363 int SSLServerSocketOpenSSL::BufferRecv() {
364 if (transport_recv_busy_)
365 return ERR_IO_PENDING;
367 // Determine how much was requested from |transport_bio_| that was not
368 // actually available.
369 size_t requested = BIO_ctrl_get_read_request(transport_bio_);
370 if (requested == 0) {
371 // This is not a perfect match of error codes, as no operation is
372 // actually pending. However, returning 0 would be interpreted as
373 // a possible sign of EOF, which is also an inappropriate match.
374 return ERR_IO_PENDING;
377 // Known Issue: While only reading |requested| data is the more correct
378 // implementation, it has the downside of resulting in frequent reads:
379 // One read for the SSL record header (~5 bytes) and one read for the SSL
380 // record body. Rather than issuing these reads to the underlying socket
381 // (and constantly allocating new IOBuffers), a single Read() request to
382 // fill |transport_bio_| is issued. As long as an SSL client socket cannot
383 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
384 // traffic, this over-subscribed Read()ing will not cause issues.
385 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
386 if (!max_write)
387 return ERR_IO_PENDING;
389 recv_buffer_ = new IOBuffer(max_write);
390 int rv = transport_socket_->Read(
391 recv_buffer_.get(),
392 max_write,
393 base::Bind(&SSLServerSocketOpenSSL::BufferRecvComplete,
394 base::Unretained(this)));
395 if (rv == ERR_IO_PENDING) {
396 transport_recv_busy_ = true;
397 } else {
398 rv = TransportReadComplete(rv);
400 return rv;
403 void SSLServerSocketOpenSSL::BufferRecvComplete(int result) {
404 result = TransportReadComplete(result);
405 OnRecvComplete(result);
408 int SSLServerSocketOpenSSL::TransportReadComplete(int result) {
409 DCHECK(ERR_IO_PENDING != result);
410 if (result <= 0) {
411 DVLOG(1) << "TransportReadComplete result " << result;
412 // Received 0 (end of file) or an error. Either way, bubble it up to the
413 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
414 // relay up to the SSL socket client (i.e. via DoReadCallback).
415 if (result == 0)
416 transport_recv_eof_ = true;
417 (void)BIO_shutdown_wr(transport_bio_);
418 } else if (transport_write_error_ < 0) {
419 // Mirror transport write errors as read failures; transport_bio_ has been
420 // shut down by TransportWriteComplete, so the BIO_write will fail, failing
421 // the CHECK. http://crbug.com/335557.
422 result = transport_write_error_;
423 } else {
424 DCHECK(recv_buffer_.get());
425 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
426 // A write into a memory BIO should always succeed.
427 DCHECK_EQ(result, ret);
429 recv_buffer_ = NULL;
430 transport_recv_busy_ = false;
431 return result;
434 // Do as much network I/O as possible between the buffer and the
435 // transport socket. Return true if some I/O performed, false
436 // otherwise (error or ERR_IO_PENDING).
437 bool SSLServerSocketOpenSSL::DoTransportIO() {
438 bool network_moved = false;
439 int rv;
440 // Read and write as much data as possible. The loop is necessary because
441 // Write() may return synchronously.
442 do {
443 rv = BufferSend();
444 if (rv != ERR_IO_PENDING && rv != 0)
445 network_moved = true;
446 } while (rv > 0);
447 if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
448 network_moved = true;
449 return network_moved;
452 int SSLServerSocketOpenSSL::DoPayloadRead() {
453 DCHECK(user_read_buf_.get());
454 DCHECK_GT(user_read_buf_len_, 0);
455 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
456 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
457 if (rv >= 0)
458 return rv;
459 int ssl_error = SSL_get_error(ssl_, rv);
460 OpenSSLErrorInfo error_info;
461 int net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer,
462 &error_info);
463 if (net_error != ERR_IO_PENDING) {
464 net_log_.AddEvent(
465 NetLog::TYPE_SSL_READ_ERROR,
466 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
468 return net_error;
471 int SSLServerSocketOpenSSL::DoPayloadWrite() {
472 DCHECK(user_write_buf_.get());
473 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
474 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
475 if (rv >= 0)
476 return rv;
477 int ssl_error = SSL_get_error(ssl_, rv);
478 OpenSSLErrorInfo error_info;
479 int net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer,
480 &error_info);
481 if (net_error != ERR_IO_PENDING) {
482 net_log_.AddEvent(
483 NetLog::TYPE_SSL_WRITE_ERROR,
484 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
486 return net_error;
489 int SSLServerSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
490 int rv = last_io_result;
491 do {
492 // Default to STATE_NONE for next state.
493 // (This is a quirk carried over from the windows
494 // implementation. It makes reading the logs a bit harder.)
495 // State handlers can and often do call GotoState just
496 // to stay in the current state.
497 State state = next_handshake_state_;
498 GotoState(STATE_NONE);
499 switch (state) {
500 case STATE_HANDSHAKE:
501 rv = DoHandshake();
502 break;
503 case STATE_NONE:
504 default:
505 rv = ERR_UNEXPECTED;
506 LOG(DFATAL) << "unexpected state " << state;
507 break;
510 // Do the actual network I/O
511 bool network_moved = DoTransportIO();
512 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
513 // In general we exit the loop if rv is ERR_IO_PENDING. In this
514 // special case we keep looping even if rv is ERR_IO_PENDING because
515 // the transport IO may allow DoHandshake to make progress.
516 rv = OK; // This causes us to stay in the loop.
518 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
519 return rv;
522 int SSLServerSocketOpenSSL::DoReadLoop(int result) {
523 DCHECK(completed_handshake_);
524 DCHECK(next_handshake_state_ == STATE_NONE);
526 if (result < 0)
527 return result;
529 bool network_moved;
530 int rv;
531 do {
532 rv = DoPayloadRead();
533 network_moved = DoTransportIO();
534 } while (rv == ERR_IO_PENDING && network_moved);
535 return rv;
538 int SSLServerSocketOpenSSL::DoWriteLoop(int result) {
539 DCHECK(completed_handshake_);
540 DCHECK_EQ(next_handshake_state_, STATE_NONE);
542 if (result < 0)
543 return result;
545 bool network_moved;
546 int rv;
547 do {
548 rv = DoPayloadWrite();
549 network_moved = DoTransportIO();
550 } while (rv == ERR_IO_PENDING && network_moved);
551 return rv;
554 int SSLServerSocketOpenSSL::DoHandshake() {
555 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
556 int net_error = OK;
557 int rv = SSL_do_handshake(ssl_);
559 if (rv == 1) {
560 completed_handshake_ = true;
561 } else {
562 int ssl_error = SSL_get_error(ssl_, rv);
563 OpenSSLErrorInfo error_info;
564 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info);
566 // If not done, stay in this state
567 if (net_error == ERR_IO_PENDING) {
568 GotoState(STATE_HANDSHAKE);
569 } else {
570 LOG(ERROR) << "handshake failed; returned " << rv
571 << ", SSL error code " << ssl_error
572 << ", net_error " << net_error;
573 net_log_.AddEvent(
574 NetLog::TYPE_SSL_HANDSHAKE_ERROR,
575 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
578 return net_error;
581 void SSLServerSocketOpenSSL::DoHandshakeCallback(int rv) {
582 DCHECK_NE(rv, ERR_IO_PENDING);
583 ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
586 void SSLServerSocketOpenSSL::DoReadCallback(int rv) {
587 DCHECK(rv != ERR_IO_PENDING);
588 DCHECK(!user_read_callback_.is_null());
590 user_read_buf_ = NULL;
591 user_read_buf_len_ = 0;
592 ResetAndReturn(&user_read_callback_).Run(rv);
595 void SSLServerSocketOpenSSL::DoWriteCallback(int rv) {
596 DCHECK(rv != ERR_IO_PENDING);
597 DCHECK(!user_write_callback_.is_null());
599 user_write_buf_ = NULL;
600 user_write_buf_len_ = 0;
601 ResetAndReturn(&user_write_callback_).Run(rv);
604 int SSLServerSocketOpenSSL::Init() {
605 DCHECK(!ssl_);
606 DCHECK(!transport_bio_);
608 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
610 ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method()));
611 ssl_ = SSL_new(ssl_ctx.get());
612 if (!ssl_)
613 return ERR_UNEXPECTED;
615 BIO* ssl_bio = NULL;
616 // 0 => use default buffer sizes.
617 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
618 return ERR_UNEXPECTED;
619 DCHECK(ssl_bio);
620 DCHECK(transport_bio_);
622 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
624 // Set certificate and private key.
625 DCHECK(cert_->os_cert_handle());
626 #if defined(USE_OPENSSL_CERTS)
627 if (SSL_use_certificate(ssl_, cert_->os_cert_handle()) != 1) {
628 LOG(ERROR) << "Cannot set certificate.";
629 return ERR_UNEXPECTED;
631 #else
632 // Convert OSCertHandle to X509 structure.
633 std::string der_string;
634 if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
635 return ERR_UNEXPECTED;
637 const unsigned char* der_string_array =
638 reinterpret_cast<const unsigned char*>(der_string.data());
640 ScopedX509 x509(d2i_X509(NULL, &der_string_array, der_string.length()));
641 if (!x509.get())
642 return ERR_UNEXPECTED;
644 // On success, SSL_use_certificate acquires a reference to |x509|.
645 if (SSL_use_certificate(ssl_, x509.get()) != 1) {
646 LOG(ERROR) << "Cannot set certificate.";
647 return ERR_UNEXPECTED;
649 #endif // USE_OPENSSL_CERTS
651 DCHECK(key_->key());
652 if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) {
653 LOG(ERROR) << "Cannot set private key.";
654 return ERR_UNEXPECTED;
657 // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
658 // set everything we care about to an absolute value.
659 SslSetClearMask options;
660 options.ConfigureFlag(SSL_OP_NO_SSLv2, true);
661 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3);
662 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled);
663 bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 &&
664 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1);
665 options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled);
666 bool tls1_1_enabled =
667 (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1 &&
668 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1);
669 options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled);
670 bool tls1_2_enabled =
671 (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2 &&
672 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2);
673 options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled);
675 options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);
677 SSL_set_options(ssl_, options.set_mask);
678 SSL_clear_options(ssl_, options.clear_mask);
680 // Same as above, this time for the SSL mode.
681 SslSetClearMask mode;
683 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
685 SSL_set_mode(ssl_, mode.set_mask);
686 SSL_clear_mode(ssl_, mode.clear_mask);
688 return OK;
691 } // namespace net