2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/io/async/AsyncSSLSocket.h>
19 #include <folly/io/async/EventBase.h>
20 #include <folly/portability/Sockets.h>
22 #include <boost/noncopyable.hpp>
25 #include <openssl/err.h>
26 #include <openssl/asn1.h>
27 #include <openssl/ssl.h>
28 #include <sys/types.h>
31 #include <folly/Bits.h>
32 #include <folly/SocketAddress.h>
33 #include <folly/SpinLock.h>
34 #include <folly/io/Cursor.h>
35 #include <folly/io/IOBuf.h>
36 #include <folly/portability/OpenSSL.h>
38 using folly::SocketAddress;
39 using folly::SSLContext;
41 using std::shared_ptr;
45 using folly::SpinLock;
46 using folly::SpinLockGuard;
47 using folly::io::Cursor;
48 using std::unique_ptr;
52 using folly::AsyncSocket;
53 using folly::AsyncSocketException;
54 using folly::AsyncSSLSocket;
55 using folly::Optional;
56 using folly::SSLContext;
57 // For OpenSSL portability API
58 using namespace folly::ssl;
59 using folly::ssl::OpenSSLUtils;
62 // We have one single dummy SSL context so that we can implement attach
63 // and detach methods in a thread safe fashion without modifying opnessl.
64 static SSLContext *dummyCtx = nullptr;
65 static SpinLock dummyCtxLock;
67 // If given min write size is less than this, buffer will be allocated on
68 // stack, otherwise it is allocated on heap
69 const size_t MAX_STACK_BUF_SIZE = 2048;
71 // This converts "illegal" shutdowns into ZERO_RETURN
72 inline bool zero_return(int error, int rc) {
73 return (error == SSL_ERROR_ZERO_RETURN || (rc == 0 && errno == 0));
76 class AsyncSSLSocketConnector: public AsyncSocket::ConnectCallback,
77 public AsyncSSLSocket::HandshakeCB {
80 AsyncSSLSocket *sslSocket_;
81 AsyncSSLSocket::ConnectCallback *callback_;
86 ~AsyncSSLSocketConnector() override {}
89 AsyncSSLSocketConnector(AsyncSSLSocket *sslSocket,
90 AsyncSocket::ConnectCallback *callback,
92 sslSocket_(sslSocket),
95 startTime_(std::chrono::duration_cast<std::chrono::milliseconds>(
96 std::chrono::steady_clock::now().time_since_epoch()).count()) {
99 void connectSuccess() noexcept override {
100 VLOG(7) << "client socket connected";
102 int64_t timeoutLeft = 0;
104 auto curTime = std::chrono::duration_cast<std::chrono::milliseconds>(
105 std::chrono::steady_clock::now().time_since_epoch()).count();
107 timeoutLeft = timeout_ - (curTime - startTime_);
108 if (timeoutLeft <= 0) {
109 AsyncSocketException ex(
110 AsyncSocketException::TIMED_OUT,
111 folly::sformat("SSL connect timed out after {}ms", timeout_));
117 sslSocket_->sslConn(this, std::chrono::milliseconds(timeoutLeft));
120 void connectErr(const AsyncSocketException& ex) noexcept override {
121 VLOG(1) << "TCP connect failed: " << ex.what();
126 void handshakeSuc(AsyncSSLSocket* /* sock */) noexcept override {
127 VLOG(7) << "client handshake success";
129 callback_->connectSuccess();
134 void handshakeErr(AsyncSSLSocket* /* socket */,
135 const AsyncSocketException& ex) noexcept override {
136 VLOG(1) << "client handshakeErr: " << ex.what();
141 void fail(const AsyncSocketException &ex) {
142 // fail is a noop if called twice
144 AsyncSSLSocket::ConnectCallback *cb = callback_;
148 sslSocket_->closeNow();
149 // closeNow can call handshakeErr if it hasn't been called already.
150 // So this may have been deleted, no member variable access beyond this
152 // Note that closeNow may invoke writeError callbacks if the socket had
153 // write data pending connection completion.
158 void setup_SSL_CTX(SSL_CTX *ctx) {
159 #ifdef SSL_MODE_RELEASE_BUFFERS
160 SSL_CTX_set_mode(ctx,
161 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
162 SSL_MODE_ENABLE_PARTIAL_WRITE
163 | SSL_MODE_RELEASE_BUFFERS
166 SSL_CTX_set_mode(ctx,
167 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
168 SSL_MODE_ENABLE_PARTIAL_WRITE
171 // SSL_CTX_set_mode is a Macro
172 #ifdef SSL_MODE_WRITE_IOVEC
173 SSL_CTX_set_mode(ctx,
174 SSL_CTX_get_mode(ctx)
175 | SSL_MODE_WRITE_IOVEC);
180 // Note: This is a Leaky Meyer's Singleton. The reason we can't use a non-leaky
181 // thing is because we will be setting this BIO_METHOD* inside BIOs owned by
182 // various SSL objects which may get callbacks even during teardown. We may
183 // eventually try to fix this
184 static BIO_METHOD* getSSLBioMethod() {
185 static auto const instance = OpenSSLUtils::newSocketBioMethod().release();
189 void* initsslBioMethod(void) {
190 auto sslBioMethod = getSSLBioMethod();
191 // override the bwrite method for MSG_EOR support
192 OpenSSLUtils::setCustomBioWriteMethod(sslBioMethod, AsyncSSLSocket::bioWrite);
193 OpenSSLUtils::setCustomBioReadMethod(sslBioMethod, AsyncSSLSocket::bioRead);
195 // Note that the sslBioMethod.type and sslBioMethod.name are not
196 // set here. openssl code seems to be checking ".type == BIO_TYPE_SOCKET" and
197 // then have specific handlings. The sslWriteBioWrite should be compatible
198 // with the one in openssl.
200 // Return something here to enable AsyncSSLSocket to call this method using
201 // a function-scoped static.
205 } // anonymous namespace
210 * Create a client AsyncSSLSocket
212 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext> &ctx,
213 EventBase* evb, bool deferSecurityNegotiation) :
216 handshakeTimeout_(this, evb),
217 connectionTimeout_(this, evb) {
219 if (deferSecurityNegotiation) {
220 sslState_ = STATE_UNENCRYPTED;
225 * Create a server/client AsyncSSLSocket
227 AsyncSSLSocket::AsyncSSLSocket(
228 const shared_ptr<SSLContext>& ctx,
232 bool deferSecurityNegotiation)
233 : AsyncSocket(evb, fd),
236 handshakeTimeout_(this, evb),
237 connectionTimeout_(this, evb) {
238 noTransparentTls_ = true;
241 SSL_CTX_set_info_callback(
242 ctx_->getSSLCtx(), AsyncSSLSocket::sslInfoCallback);
244 if (deferSecurityNegotiation) {
245 sslState_ = STATE_UNENCRYPTED;
249 AsyncSSLSocket::AsyncSSLSocket(
250 const shared_ptr<SSLContext>& ctx,
251 AsyncSocket::UniquePtr oldAsyncSocket,
253 bool deferSecurityNegotiation)
254 : AsyncSocket(std::move(oldAsyncSocket)),
257 handshakeTimeout_(this, AsyncSocket::getEventBase()),
258 connectionTimeout_(this, AsyncSocket::getEventBase()) {
259 noTransparentTls_ = true;
262 SSL_CTX_set_info_callback(ctx_->getSSLCtx(),
263 AsyncSSLSocket::sslInfoCallback);
265 if (deferSecurityNegotiation) {
266 sslState_ = STATE_UNENCRYPTED;
270 #if FOLLY_OPENSSL_HAS_SNI
272 * Create a client AsyncSSLSocket and allow tlsext_hostname
273 * to be sent in Client Hello.
275 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext> &ctx,
277 const std::string& serverName,
278 bool deferSecurityNegotiation) :
279 AsyncSSLSocket(ctx, evb, deferSecurityNegotiation) {
280 tlsextHostname_ = serverName;
284 * Create a client AsyncSSLSocket from an already connected fd
285 * and allow tlsext_hostname to be sent in Client Hello.
287 AsyncSSLSocket::AsyncSSLSocket(
288 const shared_ptr<SSLContext>& ctx,
291 const std::string& serverName,
292 bool deferSecurityNegotiation)
293 : AsyncSSLSocket(ctx, evb, fd, false, deferSecurityNegotiation) {
294 tlsextHostname_ = serverName;
296 #endif // FOLLY_OPENSSL_HAS_SNI
298 AsyncSSLSocket::~AsyncSSLSocket() {
299 VLOG(3) << "actual destruction of AsyncSSLSocket(this=" << this
300 << ", evb=" << eventBase_ << ", fd=" << fd_
301 << ", state=" << int(state_) << ", sslState="
302 << sslState_ << ", events=" << eventFlags_ << ")";
305 void AsyncSSLSocket::init() {
306 // Do this here to ensure we initialize this once before any use of
307 // AsyncSSLSocket instances and not as part of library load.
308 static const auto sslBioMethodInitializer = initsslBioMethod();
309 (void)sslBioMethodInitializer;
311 setup_SSL_CTX(ctx_->getSSLCtx());
314 void AsyncSSLSocket::closeNow() {
315 // Close the SSL connection.
316 if (ssl_ != nullptr && fd_ != -1) {
317 int rc = SSL_shutdown(ssl_);
319 rc = SSL_shutdown(ssl_);
326 if (sslSession_ != nullptr) {
327 SSL_SESSION_free(sslSession_);
328 sslSession_ = nullptr;
331 sslState_ = STATE_CLOSED;
333 if (handshakeTimeout_.isScheduled()) {
334 handshakeTimeout_.cancelTimeout();
337 DestructorGuard dg(this);
340 AsyncSocketException(
341 AsyncSocketException::END_OF_FILE,
342 "SSL connection closed locally"));
344 if (ssl_ != nullptr) {
350 AsyncSocket::closeNow();
353 void AsyncSSLSocket::shutdownWrite() {
354 // SSL sockets do not support half-shutdown, so just perform a full shutdown.
356 // (Performing a full shutdown here is more desirable than doing nothing at
357 // all. The purpose of shutdownWrite() is normally to notify the other end
358 // of the connection that no more data will be sent. If we do nothing, the
359 // other end will never know that no more data is coming, and this may result
360 // in protocol deadlock.)
364 void AsyncSSLSocket::shutdownWriteNow() {
368 bool AsyncSSLSocket::good() const {
369 return (AsyncSocket::good() &&
370 (sslState_ == STATE_ACCEPTING || sslState_ == STATE_CONNECTING ||
371 sslState_ == STATE_ESTABLISHED || sslState_ == STATE_UNENCRYPTED));
374 // The TAsyncTransport definition of 'good' states that the transport is
375 // ready to perform reads and writes, so sslState_ == UNINIT must report !good.
376 // connecting can be true when the sslState_ == UNINIT because the AsyncSocket
377 // is connected but we haven't initiated the call to SSL_connect.
378 bool AsyncSSLSocket::connecting() const {
380 (AsyncSocket::connecting() ||
381 (AsyncSocket::good() && (sslState_ == STATE_UNINIT ||
382 sslState_ == STATE_CONNECTING))));
385 std::string AsyncSSLSocket::getApplicationProtocol() noexcept {
386 const unsigned char* protoName = nullptr;
387 unsigned protoLength;
388 if (getSelectedNextProtocolNoThrow(&protoName, &protoLength)) {
389 return std::string(reinterpret_cast<const char*>(protoName), protoLength);
394 void AsyncSSLSocket::setEorTracking(bool track) {
395 if (isEorTrackingEnabled() != track) {
396 AsyncSocket::setEorTracking(track);
398 minEorRawByteNo_ = 0;
402 size_t AsyncSSLSocket::getRawBytesWritten() const {
403 // The bio(s) in the write path are in a chain
404 // each bio flushes to the next and finally written into the socket
405 // to get the rawBytesWritten on the socket,
406 // get the write bytes of the last bio
408 if (!ssl_ || !(b = SSL_get_wbio(ssl_))) {
411 BIO* next = BIO_next(b);
412 while (next != NULL) {
417 return BIO_number_written(b);
420 size_t AsyncSSLSocket::getRawBytesReceived() const {
422 if (!ssl_ || !(b = SSL_get_rbio(ssl_))) {
426 return BIO_number_read(b);
430 void AsyncSSLSocket::invalidState(HandshakeCB* callback) {
431 LOG(ERROR) << "AsyncSSLSocket(this=" << this << ", fd=" << fd_
432 << ", state=" << int(state_) << ", sslState=" << sslState_ << ", "
433 << "events=" << eventFlags_ << ", server=" << short(server_)
434 << "): " << "sslAccept/Connect() called in invalid "
435 << "state, handshake callback " << handshakeCallback_
436 << ", new callback " << callback;
437 assert(!handshakeTimeout_.isScheduled());
438 sslState_ = STATE_ERROR;
440 AsyncSocketException ex(AsyncSocketException::INVALID_STATE,
441 "sslAccept() called with socket in invalid state");
443 handshakeEndTime_ = std::chrono::steady_clock::now();
445 callback->handshakeErr(this, ex);
448 failHandshake(__func__, ex);
451 void AsyncSSLSocket::sslAccept(
452 HandshakeCB* callback,
453 std::chrono::milliseconds timeout,
454 const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
455 DestructorGuard dg(this);
456 assert(eventBase_->isInEventBaseThread());
457 verifyPeer_ = verifyPeer;
459 // Make sure we're in the uninitialized state
460 if (!server_ || (sslState_ != STATE_UNINIT &&
461 sslState_ != STATE_UNENCRYPTED) ||
462 handshakeCallback_ != nullptr) {
463 return invalidState(callback);
466 // Cache local and remote socket addresses to keep them available
467 // after socket file descriptor is closed.
468 if (cacheAddrOnFailure_ && -1 != getFd()) {
469 cacheLocalPeerAddr();
472 handshakeStartTime_ = std::chrono::steady_clock::now();
473 // Make end time at least >= start time.
474 handshakeEndTime_ = handshakeStartTime_;
476 sslState_ = STATE_ACCEPTING;
477 handshakeCallback_ = callback;
479 if (timeout > std::chrono::milliseconds::zero()) {
480 handshakeTimeout_.scheduleTimeout(timeout);
483 /* register for a read operation (waiting for CLIENT HELLO) */
484 updateEventRegistration(EventHandler::READ, EventHandler::WRITE);
486 checkForImmediateRead();
489 void AsyncSSLSocket::attachSSLContext(
490 const std::shared_ptr<SSLContext>& ctx) {
492 // Check to ensure we are in client mode. Changing a server's ssl
493 // context doesn't make sense since clients of that server would likely
494 // become confused when the server's context changes.
498 DCHECK(ctx->getSSLCtx());
501 // It's possible this could be attached before ssl_ is set up
506 // In order to call attachSSLContext, detachSSLContext must have been
507 // previously called.
508 // We need to update the initial_ctx if necessary
509 auto sslCtx = ctx->getSSLCtx();
510 SSL_CTX_up_ref(sslCtx);
512 // The 'initial_ctx' inside an SSL* points to the context that it was created
513 // with, which is also where session callbacks and servername callbacks
515 // When we switch to a different SSL_CTX, we want to update the initial_ctx as
516 // well so that any callbacks don't go to a different object
517 // NOTE: this will only work if we have access to ssl_ internals, so it may
519 // OpenSSL version >= 1.1.0
520 OpenSSLUtils::setSSLInitialCtx(ssl_, sslCtx);
521 // Detach sets the socket's context to the dummy context. Thus we must acquire
523 SpinLockGuard guard(dummyCtxLock);
524 SSL_set_SSL_CTX(ssl_, sslCtx);
527 void AsyncSSLSocket::detachSSLContext() {
530 // It's possible for this to be called before ssl_ has been
535 // The 'initial_ctx' inside an SSL* points to the context that it was created
536 // with, which is also where session callbacks and servername callbacks
538 // Detach the initial_ctx as well. It will be reattached in attachSSLContext
539 // it is used for session info.
540 // NOTE: this will only work if we have access to ssl_ internals, so it may
542 // OpenSSL version >= 1.1.0
543 SSL_CTX* initialCtx = OpenSSLUtils::getSSLInitialCtx(ssl_);
545 SSL_CTX_free(initialCtx);
546 OpenSSLUtils::setSSLInitialCtx(ssl_, nullptr);
549 SpinLockGuard guard(dummyCtxLock);
550 if (nullptr == dummyCtx) {
551 // We need to lazily initialize the dummy context so we don't
552 // accidentally override any programmatic settings to openssl
553 dummyCtx = new SSLContext;
555 // We must remove this socket's references to its context right now
556 // since this socket could get passed to any thread. If the context has
557 // had its locking disabled, just doing a set in attachSSLContext()
558 // would not be thread safe.
559 SSL_set_SSL_CTX(ssl_, dummyCtx->getSSLCtx());
562 #if FOLLY_OPENSSL_HAS_SNI
563 void AsyncSSLSocket::switchServerSSLContext(
564 const std::shared_ptr<SSLContext>& handshakeCtx) {
566 if (sslState_ != STATE_ACCEPTING) {
567 // We log it here and allow the switch.
568 // It should not affect our re-negotiation support (which
569 // is not supported now).
570 VLOG(6) << "fd=" << getFd()
571 << " renegotation detected when switching SSL_CTX";
574 setup_SSL_CTX(handshakeCtx->getSSLCtx());
575 SSL_CTX_set_info_callback(handshakeCtx->getSSLCtx(),
576 AsyncSSLSocket::sslInfoCallback);
577 handshakeCtx_ = handshakeCtx;
578 SSL_set_SSL_CTX(ssl_, handshakeCtx->getSSLCtx());
581 bool AsyncSSLSocket::isServerNameMatch() const {
588 SSL_SESSION *ss = SSL_get_session(ssl_);
593 auto tlsextHostname = SSL_SESSION_get0_hostname(ss);
594 return (tlsextHostname && !tlsextHostname_.compare(tlsextHostname));
597 void AsyncSSLSocket::setServerName(std::string serverName) noexcept {
598 tlsextHostname_ = std::move(serverName);
601 #endif // FOLLY_OPENSSL_HAS_SNI
603 void AsyncSSLSocket::timeoutExpired(
604 std::chrono::milliseconds timeout) noexcept {
605 if (state_ == StateEnum::ESTABLISHED &&
606 (sslState_ == STATE_CACHE_LOOKUP || sslState_ == STATE_ASYNC_PENDING)) {
607 sslState_ = STATE_ERROR;
608 // We are expecting a callback in restartSSLAccept. The cache lookup
609 // and rsa-call necessarily have pointers to this ssl socket, so delay
610 // the cleanup until he calls us back.
611 } else if (state_ == StateEnum::CONNECTING) {
612 assert(sslState_ == STATE_CONNECTING);
613 DestructorGuard dg(this);
614 AsyncSocketException ex(AsyncSocketException::TIMED_OUT,
615 "Fallback connect timed out during TFO");
616 failHandshake(__func__, ex);
618 assert(state_ == StateEnum::ESTABLISHED &&
619 (sslState_ == STATE_CONNECTING || sslState_ == STATE_ACCEPTING));
620 DestructorGuard dg(this);
621 AsyncSocketException ex(
622 AsyncSocketException::TIMED_OUT,
624 "SSL {} timed out after {}ms",
625 (sslState_ == STATE_CONNECTING) ? "connect" : "accept",
627 failHandshake(__func__, ex);
631 int AsyncSSLSocket::getSSLExDataIndex() {
632 static auto index = SSL_get_ex_new_index(
633 0, (void*)"AsyncSSLSocket data index", nullptr, nullptr, nullptr);
637 AsyncSSLSocket* AsyncSSLSocket::getFromSSL(const SSL *ssl) {
638 return static_cast<AsyncSSLSocket *>(SSL_get_ex_data(ssl,
639 getSSLExDataIndex()));
642 void AsyncSSLSocket::failHandshake(const char* /* fn */,
643 const AsyncSocketException& ex) {
645 if (handshakeTimeout_.isScheduled()) {
646 handshakeTimeout_.cancelTimeout();
648 invokeHandshakeErr(ex);
652 void AsyncSSLSocket::invokeHandshakeErr(const AsyncSocketException& ex) {
653 handshakeEndTime_ = std::chrono::steady_clock::now();
654 if (handshakeCallback_ != nullptr) {
655 HandshakeCB* callback = handshakeCallback_;
656 handshakeCallback_ = nullptr;
657 callback->handshakeErr(this, ex);
661 void AsyncSSLSocket::invokeHandshakeCB() {
662 handshakeEndTime_ = std::chrono::steady_clock::now();
663 if (handshakeTimeout_.isScheduled()) {
664 handshakeTimeout_.cancelTimeout();
666 if (handshakeCallback_) {
667 HandshakeCB* callback = handshakeCallback_;
668 handshakeCallback_ = nullptr;
669 callback->handshakeSuc(this);
673 void AsyncSSLSocket::cacheLocalPeerAddr() {
674 SocketAddress address;
676 getLocalAddress(&address);
677 getPeerAddress(&address);
678 } catch (const std::system_error& e) {
679 // The handle can be still valid while the connection is already closed.
680 if (e.code() != std::error_code(ENOTCONN, std::system_category())) {
686 void AsyncSSLSocket::connect(
687 ConnectCallback* callback,
688 const folly::SocketAddress& address,
690 const OptionMap& options,
691 const folly::SocketAddress& bindAddr) noexcept {
692 auto timeoutChrono = std::chrono::milliseconds(timeout);
693 connect(callback, address, timeoutChrono, timeoutChrono, options, bindAddr);
696 void AsyncSSLSocket::connect(
697 ConnectCallback* callback,
698 const folly::SocketAddress& address,
699 std::chrono::milliseconds connectTimeout,
700 std::chrono::milliseconds totalConnectTimeout,
701 const OptionMap& options,
702 const folly::SocketAddress& bindAddr) noexcept {
704 assert(state_ == StateEnum::UNINIT);
705 assert(sslState_ == STATE_UNINIT);
706 noTransparentTls_ = true;
707 totalConnectTimeout_ = totalConnectTimeout;
708 AsyncSSLSocketConnector* connector =
709 new AsyncSSLSocketConnector(this, callback, totalConnectTimeout.count());
710 AsyncSocket::connect(
711 connector, address, connectTimeout.count(), options, bindAddr);
714 bool AsyncSSLSocket::needsPeerVerification() const {
715 if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::USE_CTX) {
716 return ctx_->needsPeerVerification();
719 verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY ||
720 verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT);
723 void AsyncSSLSocket::applyVerificationOptions(SSL * ssl) {
724 // apply the settings specified in verifyPeer_
725 if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::USE_CTX) {
726 if(ctx_->needsPeerVerification()) {
727 SSL_set_verify(ssl, ctx_->getVerificationMode(),
728 AsyncSSLSocket::sslVerifyCallback);
731 if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY ||
732 verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT) {
733 SSL_set_verify(ssl, SSLContext::getVerificationMode(verifyPeer_),
734 AsyncSSLSocket::sslVerifyCallback);
739 bool AsyncSSLSocket::setupSSLBio() {
740 auto sslBio = BIO_new(getSSLBioMethod());
746 OpenSSLUtils::setBioAppData(sslBio, this);
747 OpenSSLUtils::setBioFd(sslBio, fd_, BIO_NOCLOSE);
748 SSL_set_bio(ssl_, sslBio, sslBio);
752 void AsyncSSLSocket::sslConn(
753 HandshakeCB* callback,
754 std::chrono::milliseconds timeout,
755 const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
756 DestructorGuard dg(this);
757 assert(eventBase_->isInEventBaseThread());
759 // Cache local and remote socket addresses to keep them available
760 // after socket file descriptor is closed.
761 if (cacheAddrOnFailure_ && -1 != getFd()) {
762 cacheLocalPeerAddr();
765 verifyPeer_ = verifyPeer;
767 // Make sure we're in the uninitialized state
768 if (server_ || (sslState_ != STATE_UNINIT && sslState_ !=
769 STATE_UNENCRYPTED) ||
770 handshakeCallback_ != nullptr) {
771 return invalidState(callback);
774 sslState_ = STATE_CONNECTING;
775 handshakeCallback_ = callback;
778 ssl_ = ctx_->createSSL();
779 } catch (std::exception &e) {
780 sslState_ = STATE_ERROR;
781 AsyncSocketException ex(AsyncSocketException::INTERNAL_ERROR,
782 "error calling SSLContext::createSSL()");
783 LOG(ERROR) << "AsyncSSLSocket::sslConn(this=" << this << ", fd="
784 << fd_ << "): " << e.what();
785 return failHandshake(__func__, ex);
788 if (!setupSSLBio()) {
789 sslState_ = STATE_ERROR;
790 AsyncSocketException ex(
791 AsyncSocketException::INTERNAL_ERROR, "error creating SSL bio");
792 return failHandshake(__func__, ex);
795 applyVerificationOptions(ssl_);
797 if (sslSession_ != nullptr) {
798 sessionResumptionAttempted_ = true;
799 SSL_set_session(ssl_, sslSession_);
800 SSL_SESSION_free(sslSession_);
801 sslSession_ = nullptr;
803 #if FOLLY_OPENSSL_HAS_SNI
804 if (tlsextHostname_.size()) {
805 SSL_set_tlsext_host_name(ssl_, tlsextHostname_.c_str());
809 SSL_set_ex_data(ssl_, getSSLExDataIndex(), this);
811 handshakeConnectTimeout_ = timeout;
815 // This could be called multiple times, during normal ssl connections
816 // and after TFO fallback.
817 void AsyncSSLSocket::startSSLConnect() {
818 handshakeStartTime_ = std::chrono::steady_clock::now();
819 // Make end time at least >= start time.
820 handshakeEndTime_ = handshakeStartTime_;
821 if (handshakeConnectTimeout_ > std::chrono::milliseconds::zero()) {
822 handshakeTimeout_.scheduleTimeout(handshakeConnectTimeout_);
827 SSL_SESSION *AsyncSSLSocket::getSSLSession() {
828 if (ssl_ != nullptr && sslState_ == STATE_ESTABLISHED) {
829 return SSL_get1_session(ssl_);
835 const SSL* AsyncSSLSocket::getSSL() const {
839 void AsyncSSLSocket::setSSLSession(SSL_SESSION *session, bool takeOwnership) {
840 sslSession_ = session;
841 if (!takeOwnership && session != nullptr) {
842 // Increment the reference count
843 // This API exists in BoringSSL and OpenSSL 1.1.0
844 SSL_SESSION_up_ref(session);
848 void AsyncSSLSocket::getSelectedNextProtocol(
849 const unsigned char** protoName,
851 SSLContext::NextProtocolType* protoType) const {
852 if (!getSelectedNextProtocolNoThrow(protoName, protoLen, protoType)) {
853 throw AsyncSocketException(AsyncSocketException::NOT_SUPPORTED,
854 "NPN not supported");
858 bool AsyncSSLSocket::getSelectedNextProtocolNoThrow(
859 const unsigned char** protoName,
861 SSLContext::NextProtocolType* protoType) const {
862 *protoName = nullptr;
864 #if FOLLY_OPENSSL_HAS_ALPN
865 SSL_get0_alpn_selected(ssl_, protoName, protoLen);
868 *protoType = SSLContext::NextProtocolType::ALPN;
873 #ifdef OPENSSL_NPN_NEGOTIATED
874 SSL_get0_next_proto_negotiated(ssl_, protoName, protoLen);
876 *protoType = SSLContext::NextProtocolType::NPN;
885 bool AsyncSSLSocket::getSSLSessionReused() const {
886 if (ssl_ != nullptr && sslState_ == STATE_ESTABLISHED) {
887 return SSL_session_reused(ssl_);
892 const char *AsyncSSLSocket::getNegotiatedCipherName() const {
893 return (ssl_ != nullptr) ? SSL_get_cipher_name(ssl_) : nullptr;
897 const char* AsyncSSLSocket::getSSLServerNameFromSSL(SSL* ssl) {
898 if (ssl == nullptr) {
901 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
902 return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
908 const char *AsyncSSLSocket::getSSLServerName() const {
909 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
910 return getSSLServerNameFromSSL(ssl_);
912 throw AsyncSocketException(AsyncSocketException::NOT_SUPPORTED,
913 "SNI not supported");
917 const char *AsyncSSLSocket::getSSLServerNameNoThrow() const {
918 return getSSLServerNameFromSSL(ssl_);
921 int AsyncSSLSocket::getSSLVersion() const {
922 return (ssl_ != nullptr) ? SSL_version(ssl_) : 0;
925 const char *AsyncSSLSocket::getSSLCertSigAlgName() const {
926 X509 *cert = (ssl_ != nullptr) ? SSL_get_certificate(ssl_) : nullptr;
928 int nid = X509_get_signature_nid(cert);
929 return OBJ_nid2ln(nid);
934 int AsyncSSLSocket::getSSLCertSize() const {
936 X509 *cert = (ssl_ != nullptr) ? SSL_get_certificate(ssl_) : nullptr;
938 EVP_PKEY *key = X509_get_pubkey(cert);
939 certSize = EVP_PKEY_bits(key);
945 const X509* AsyncSSLSocket::getSelfCert() const {
946 return (ssl_ != nullptr) ? SSL_get_certificate(ssl_) : nullptr;
949 bool AsyncSSLSocket::willBlock(int ret,
951 unsigned long* errErrorOut) noexcept {
953 int error = *sslErrorOut = SSL_get_error(ssl_, ret);
954 if (error == SSL_ERROR_WANT_READ) {
955 // Register for read event if not already.
956 updateEventRegistration(EventHandler::READ, EventHandler::WRITE);
958 } else if (error == SSL_ERROR_WANT_WRITE) {
959 VLOG(3) << "AsyncSSLSocket(fd=" << fd_
960 << ", state=" << int(state_) << ", sslState="
961 << sslState_ << ", events=" << eventFlags_ << "): "
962 << "SSL_ERROR_WANT_WRITE";
963 // Register for write event if not already.
964 updateEventRegistration(EventHandler::WRITE, EventHandler::READ);
966 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
967 } else if (error == SSL_ERROR_WANT_SESS_CACHE_LOOKUP) {
968 // We will block but we can't register our own socket. The callback that
969 // triggered this code will re-call handleAccept at the appropriate time.
971 // We can only get here if the linked libssl.so has support for this feature
972 // as well, otherwise SSL_get_error cannot return our error code.
973 sslState_ = STATE_CACHE_LOOKUP;
975 // Unregister for all events while blocked here
976 updateEventRegistration(EventHandler::NONE,
977 EventHandler::READ | EventHandler::WRITE);
979 // The timeout (if set) keeps running here
983 #ifdef SSL_ERROR_WANT_RSA_ASYNC_PENDING
984 || error == SSL_ERROR_WANT_RSA_ASYNC_PENDING
986 #ifdef SSL_ERROR_WANT_ECDSA_ASYNC_PENDING
987 || error == SSL_ERROR_WANT_ECDSA_ASYNC_PENDING
990 // Our custom openssl function has kicked off an async request to do
991 // rsa/ecdsa private key operation. When that call returns, a callback will
992 // be invoked that will re-call handleAccept.
993 sslState_ = STATE_ASYNC_PENDING;
995 // Unregister for all events while blocked here
996 updateEventRegistration(
998 EventHandler::READ | EventHandler::WRITE
1001 // The timeout (if set) keeps running here
1004 unsigned long lastError = *errErrorOut = ERR_get_error();
1005 VLOG(6) << "AsyncSSLSocket(fd=" << fd_ << ", "
1006 << "state=" << state_ << ", "
1007 << "sslState=" << sslState_ << ", "
1008 << "events=" << std::hex << eventFlags_ << "): "
1009 << "SSL error: " << error << ", "
1010 << "errno: " << errno << ", "
1011 << "ret: " << ret << ", "
1012 << "read: " << BIO_number_read(SSL_get_rbio(ssl_)) << ", "
1013 << "written: " << BIO_number_written(SSL_get_wbio(ssl_)) << ", "
1014 << "func: " << ERR_func_error_string(lastError) << ", "
1015 << "reason: " << ERR_reason_error_string(lastError);
1020 void AsyncSSLSocket::checkForImmediateRead() noexcept {
1021 // openssl may have buffered data that it read from the socket already.
1022 // In this case we have to process it immediately, rather than waiting for
1023 // the socket to become readable again.
1024 if (ssl_ != nullptr && SSL_pending(ssl_) > 0) {
1025 AsyncSocket::handleRead();
1027 AsyncSocket::checkForImmediateRead();
1032 AsyncSSLSocket::restartSSLAccept()
1034 VLOG(3) << "AsyncSSLSocket::restartSSLAccept() this=" << this
1035 << ", fd=" << fd_ << ", state=" << int(state_) << ", "
1036 << "sslState=" << sslState_ << ", events=" << eventFlags_;
1037 DestructorGuard dg(this);
1039 sslState_ == STATE_CACHE_LOOKUP ||
1040 sslState_ == STATE_ASYNC_PENDING ||
1041 sslState_ == STATE_ERROR ||
1042 sslState_ == STATE_CLOSED);
1043 if (sslState_ == STATE_CLOSED) {
1044 // I sure hope whoever closed this socket didn't delete it already,
1045 // but this is not strictly speaking an error
1048 if (sslState_ == STATE_ERROR) {
1049 // go straight to fail if timeout expired during lookup
1050 AsyncSocketException ex(
1051 AsyncSocketException::TIMED_OUT, "SSL accept timed out");
1052 failHandshake(__func__, ex);
1055 sslState_ = STATE_ACCEPTING;
1056 this->handleAccept();
1060 AsyncSSLSocket::handleAccept() noexcept {
1061 VLOG(3) << "AsyncSSLSocket::handleAccept() this=" << this
1062 << ", fd=" << fd_ << ", state=" << int(state_) << ", "
1063 << "sslState=" << sslState_ << ", events=" << eventFlags_;
1065 assert(state_ == StateEnum::ESTABLISHED &&
1066 sslState_ == STATE_ACCEPTING);
1068 /* lazily create the SSL structure */
1070 ssl_ = ctx_->createSSL();
1071 } catch (std::exception &e) {
1072 sslState_ = STATE_ERROR;
1073 AsyncSocketException ex(AsyncSocketException::INTERNAL_ERROR,
1074 "error calling SSLContext::createSSL()");
1075 LOG(ERROR) << "AsyncSSLSocket::handleAccept(this=" << this
1076 << ", fd=" << fd_ << "): " << e.what();
1077 return failHandshake(__func__, ex);
1080 if (!setupSSLBio()) {
1081 sslState_ = STATE_ERROR;
1082 AsyncSocketException ex(
1083 AsyncSocketException::INTERNAL_ERROR, "error creating write bio");
1084 return failHandshake(__func__, ex);
1087 SSL_set_ex_data(ssl_, getSSLExDataIndex(), this);
1089 applyVerificationOptions(ssl_);
1092 if (server_ && parseClientHello_) {
1093 SSL_set_msg_callback(ssl_, &AsyncSSLSocket::clientHelloParsingCallback);
1094 SSL_set_msg_callback_arg(ssl_, this);
1097 int ret = SSL_accept(ssl_);
1100 unsigned long errError;
1101 int errnoCopy = errno;
1102 if (willBlock(ret, &sslError, &errError)) {
1105 sslState_ = STATE_ERROR;
1106 SSLException ex(sslError, errError, ret, errnoCopy);
1107 return failHandshake(__func__, ex);
1111 handshakeComplete_ = true;
1112 updateEventRegistration(0, EventHandler::READ | EventHandler::WRITE);
1114 // Move into STATE_ESTABLISHED in the normal case that we are in
1116 sslState_ = STATE_ESTABLISHED;
1118 VLOG(3) << "AsyncSSLSocket " << this << ": fd " << fd_
1119 << " successfully accepted; state=" << int(state_)
1120 << ", sslState=" << sslState_ << ", events=" << eventFlags_;
1122 // Remember the EventBase we are attached to, before we start invoking any
1123 // callbacks (since the callbacks may call detachEventBase()).
1124 EventBase* originalEventBase = eventBase_;
1126 // Call the accept callback.
1127 invokeHandshakeCB();
1129 // Note that the accept callback may have changed our state.
1130 // (set or unset the read callback, called write(), closed the socket, etc.)
1131 // The following code needs to handle these situations correctly.
1133 // If the socket has been closed, readCallback_ and writeReqHead_ will
1134 // always be nullptr, so that will prevent us from trying to read or write.
1136 // The main thing to check for is if eventBase_ is still originalEventBase.
1137 // If not, we have been detached from this event base, so we shouldn't
1138 // perform any more operations.
1139 if (eventBase_ != originalEventBase) {
1143 AsyncSocket::handleInitialReadWrite();
1147 AsyncSSLSocket::handleConnect() noexcept {
1148 VLOG(3) << "AsyncSSLSocket::handleConnect() this=" << this
1149 << ", fd=" << fd_ << ", state=" << int(state_) << ", "
1150 << "sslState=" << sslState_ << ", events=" << eventFlags_;
1152 if (state_ < StateEnum::ESTABLISHED) {
1153 return AsyncSocket::handleConnect();
1157 (state_ == StateEnum::FAST_OPEN || state_ == StateEnum::ESTABLISHED) &&
1158 sslState_ == STATE_CONNECTING);
1161 auto originalState = state_;
1162 int ret = SSL_connect(ssl_);
1165 unsigned long errError;
1166 int errnoCopy = errno;
1167 if (willBlock(ret, &sslError, &errError)) {
1168 // We fell back to connecting state due to TFO
1169 if (state_ == StateEnum::CONNECTING) {
1170 DCHECK_EQ(StateEnum::FAST_OPEN, originalState);
1171 if (handshakeTimeout_.isScheduled()) {
1172 handshakeTimeout_.cancelTimeout();
1177 sslState_ = STATE_ERROR;
1178 SSLException ex(sslError, errError, ret, errnoCopy);
1179 return failHandshake(__func__, ex);
1183 handshakeComplete_ = true;
1184 updateEventRegistration(0, EventHandler::READ | EventHandler::WRITE);
1186 // Move into STATE_ESTABLISHED in the normal case that we are in
1187 // STATE_CONNECTING.
1188 sslState_ = STATE_ESTABLISHED;
1190 VLOG(3) << "AsyncSSLSocket " << this << ": "
1191 << "fd " << fd_ << " successfully connected; "
1192 << "state=" << int(state_) << ", sslState=" << sslState_
1193 << ", events=" << eventFlags_;
1195 // Remember the EventBase we are attached to, before we start invoking any
1196 // callbacks (since the callbacks may call detachEventBase()).
1197 EventBase* originalEventBase = eventBase_;
1199 // Call the handshake callback.
1200 invokeHandshakeCB();
1202 // Note that the connect callback may have changed our state.
1203 // (set or unset the read callback, called write(), closed the socket, etc.)
1204 // The following code needs to handle these situations correctly.
1206 // If the socket has been closed, readCallback_ and writeReqHead_ will
1207 // always be nullptr, so that will prevent us from trying to read or write.
1209 // The main thing to check for is if eventBase_ is still originalEventBase.
1210 // If not, we have been detached from this event base, so we shouldn't
1211 // perform any more operations.
1212 if (eventBase_ != originalEventBase) {
1216 AsyncSocket::handleInitialReadWrite();
1219 void AsyncSSLSocket::invokeConnectErr(const AsyncSocketException& ex) {
1220 connectionTimeout_.cancelTimeout();
1221 AsyncSocket::invokeConnectErr(ex);
1222 if (sslState_ == SSLStateEnum::STATE_CONNECTING) {
1223 if (handshakeTimeout_.isScheduled()) {
1224 handshakeTimeout_.cancelTimeout();
1226 // If we fell back to connecting state during TFO and the connection
1227 // failed, it would be an SSL failure as well.
1228 invokeHandshakeErr(ex);
1232 void AsyncSSLSocket::invokeConnectSuccess() {
1233 connectionTimeout_.cancelTimeout();
1234 if (sslState_ == SSLStateEnum::STATE_CONNECTING) {
1235 assert(tfoAttempted_);
1236 // If we failed TFO, we'd fall back to trying to connect the socket,
1237 // to setup things like timeouts.
1240 // still invoke the base class since it re-sets the connect time.
1241 AsyncSocket::invokeConnectSuccess();
1244 void AsyncSSLSocket::scheduleConnectTimeout() {
1245 if (sslState_ == SSLStateEnum::STATE_CONNECTING) {
1246 // We fell back from TFO, and need to set the timeouts.
1247 // We will not have a connect callback in this case, thus if the timer
1248 // expires we would have no-one to notify.
1249 // Thus we should reset even the connect timers to point to the handshake
1251 assert(connectCallback_ == nullptr);
1252 // We use a different connect timeout here than the handshake timeout, so
1253 // that we can disambiguate the 2 timers.
1254 if (connectTimeout_.count() > 0) {
1255 if (!connectionTimeout_.scheduleTimeout(connectTimeout_)) {
1256 throw AsyncSocketException(
1257 AsyncSocketException::INTERNAL_ERROR,
1258 withAddr("failed to schedule AsyncSSLSocket connect timeout"));
1263 AsyncSocket::scheduleConnectTimeout();
1266 void AsyncSSLSocket::setReadCB(ReadCallback *callback) {
1267 #ifdef SSL_MODE_MOVE_BUFFER_OWNERSHIP
1268 // turn on the buffer movable in openssl
1269 if (bufferMovableEnabled_ && ssl_ != nullptr && !isBufferMovable_ &&
1270 callback != nullptr && callback->isBufferMovable()) {
1271 SSL_set_mode(ssl_, SSL_get_mode(ssl_) | SSL_MODE_MOVE_BUFFER_OWNERSHIP);
1272 isBufferMovable_ = true;
1276 AsyncSocket::setReadCB(callback);
1279 void AsyncSSLSocket::setBufferMovableEnabled(bool enabled) {
1280 bufferMovableEnabled_ = enabled;
1283 void AsyncSSLSocket::prepareReadBuffer(void** buf, size_t* buflen) {
1284 CHECK(readCallback_);
1285 if (isBufferMovable_) {
1289 // buf is necessary for SSLSocket without SSL_MODE_MOVE_BUFFER_OWNERSHIP
1290 readCallback_->getReadBuffer(buf, buflen);
1295 AsyncSSLSocket::handleRead() noexcept {
1296 VLOG(5) << "AsyncSSLSocket::handleRead() this=" << this << ", fd=" << fd_
1297 << ", state=" << int(state_) << ", "
1298 << "sslState=" << sslState_ << ", events=" << eventFlags_;
1299 if (state_ < StateEnum::ESTABLISHED) {
1300 return AsyncSocket::handleRead();
1304 if (sslState_ == STATE_ACCEPTING) {
1309 else if (sslState_ == STATE_CONNECTING) {
1316 AsyncSocket::handleRead();
1319 AsyncSocket::ReadResult
1320 AsyncSSLSocket::performRead(void** buf, size_t* buflen, size_t* offset) {
1321 VLOG(4) << "AsyncSSLSocket::performRead() this=" << this << ", buf=" << *buf
1322 << ", buflen=" << *buflen;
1324 if (sslState_ == STATE_UNENCRYPTED) {
1325 return AsyncSocket::performRead(buf, buflen, offset);
1329 if (!isBufferMovable_) {
1330 bytes = SSL_read(ssl_, *buf, int(*buflen));
1332 #ifdef SSL_MODE_MOVE_BUFFER_OWNERSHIP
1334 bytes = SSL_read_buf(ssl_, buf, (int *) offset, (int *) buflen);
1338 if (server_ && renegotiateAttempted_) {
1339 LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1340 << ", sslstate=" << sslState_ << ", events=" << eventFlags_
1341 << "): client intitiated SSL renegotiation not permitted";
1344 folly::make_unique<SSLException>(SSLError::CLIENT_RENEGOTIATION));
1347 int error = SSL_get_error(ssl_, bytes);
1348 if (error == SSL_ERROR_WANT_READ) {
1349 // The caller will register for read event if not already.
1350 if (errno == EWOULDBLOCK || errno == EAGAIN) {
1351 return ReadResult(READ_BLOCKING);
1353 return ReadResult(READ_ERROR);
1355 } else if (error == SSL_ERROR_WANT_WRITE) {
1356 // TODO: Even though we are attempting to read data, SSL_read() may
1357 // need to write data if renegotiation is being performed. We currently
1358 // don't support this and just fail the read.
1359 LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1360 << ", sslState=" << sslState_ << ", events=" << eventFlags_
1361 << "): unsupported SSL renegotiation during read";
1364 folly::make_unique<SSLException>(SSLError::INVALID_RENEGOTIATION));
1366 if (zero_return(error, bytes)) {
1367 return ReadResult(bytes);
1369 auto errError = ERR_get_error();
1370 VLOG(6) << "AsyncSSLSocket(fd=" << fd_ << ", "
1371 << "state=" << state_ << ", "
1372 << "sslState=" << sslState_ << ", "
1373 << "events=" << std::hex << eventFlags_ << "): "
1374 << "bytes: " << bytes << ", "
1375 << "error: " << error << ", "
1376 << "errno: " << errno << ", "
1377 << "func: " << ERR_func_error_string(errError) << ", "
1378 << "reason: " << ERR_reason_error_string(errError);
1381 folly::make_unique<SSLException>(error, errError, bytes, errno));
1384 appBytesReceived_ += bytes;
1385 return ReadResult(bytes);
1389 void AsyncSSLSocket::handleWrite() noexcept {
1390 VLOG(5) << "AsyncSSLSocket::handleWrite() this=" << this << ", fd=" << fd_
1391 << ", state=" << int(state_) << ", "
1392 << "sslState=" << sslState_ << ", events=" << eventFlags_;
1393 if (state_ < StateEnum::ESTABLISHED) {
1394 return AsyncSocket::handleWrite();
1397 if (sslState_ == STATE_ACCEPTING) {
1403 if (sslState_ == STATE_CONNECTING) {
1410 AsyncSocket::handleWrite();
1413 AsyncSocket::WriteResult AsyncSSLSocket::interpretSSLError(int rc, int error) {
1414 if (error == SSL_ERROR_WANT_READ) {
1415 // Even though we are attempting to write data, SSL_write() may
1416 // need to read data if renegotiation is being performed. We currently
1417 // don't support this and just fail the write.
1418 LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1419 << ", sslState=" << sslState_ << ", events=" << eventFlags_
1421 << "unsupported SSL renegotiation during write";
1424 folly::make_unique<SSLException>(SSLError::INVALID_RENEGOTIATION));
1426 if (zero_return(error, rc)) {
1427 return WriteResult(0);
1429 auto errError = ERR_get_error();
1430 VLOG(3) << "ERROR: AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1431 << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
1432 << "SSL error: " << error << ", errno: " << errno
1433 << ", func: " << ERR_func_error_string(errError)
1434 << ", reason: " << ERR_reason_error_string(errError);
1437 folly::make_unique<SSLException>(error, errError, rc, errno));
1441 AsyncSocket::WriteResult AsyncSSLSocket::performWrite(
1445 uint32_t* countWritten,
1446 uint32_t* partialWritten) {
1447 if (sslState_ == STATE_UNENCRYPTED) {
1448 return AsyncSocket::performWrite(
1449 vec, count, flags, countWritten, partialWritten);
1451 if (sslState_ != STATE_ESTABLISHED) {
1452 LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1453 << ", sslState=" << sslState_
1454 << ", events=" << eventFlags_ << "): "
1455 << "TODO: AsyncSSLSocket currently does not support calling "
1456 << "write() before the handshake has fully completed";
1458 WRITE_ERROR, folly::make_unique<SSLException>(SSLError::EARLY_WRITE));
1461 // Declare a buffer used to hold small write requests. It could point to a
1462 // memory block either on stack or on heap. If it is on heap, we release it
1463 // manually when scope exits
1464 char* combinedBuf{nullptr};
1466 // Note, always keep this check consistent with what we do below
1467 if (combinedBuf != nullptr && minWriteSize_ > MAX_STACK_BUF_SIZE) {
1468 delete[] combinedBuf;
1473 *partialWritten = 0;
1474 ssize_t totalWritten = 0;
1475 size_t bytesStolenFromNextBuffer = 0;
1476 for (uint32_t i = 0; i < count; i++) {
1477 const iovec* v = vec + i;
1478 size_t offset = bytesStolenFromNextBuffer;
1479 bytesStolenFromNextBuffer = 0;
1480 size_t len = v->iov_len - offset;
1486 buf = ((const char*)v->iov_base) + offset;
1489 uint32_t buffersStolen = 0;
1490 auto sslWriteBuf = buf;
1491 if ((len < minWriteSize_) && ((i + 1) < count)) {
1492 // Combine this buffer with part or all of the next buffers in
1493 // order to avoid really small-grained calls to SSL_write().
1494 // Each call to SSL_write() produces a separate record in
1495 // the egress SSL stream, and we've found that some low-end
1496 // mobile clients can't handle receiving an HTTP response
1497 // header and the first part of the response body in two
1498 // separate SSL records (even if those two records are in
1499 // the same TCP packet).
1501 if (combinedBuf == nullptr) {
1502 if (minWriteSize_ > MAX_STACK_BUF_SIZE) {
1503 // Allocate the buffer on heap
1504 combinedBuf = new char[minWriteSize_];
1506 // Allocate the buffer on stack
1507 combinedBuf = (char*)alloca(minWriteSize_);
1510 assert(combinedBuf != nullptr);
1511 sslWriteBuf = combinedBuf;
1513 memcpy(combinedBuf, buf, len);
1515 // INVARIANT: i + buffersStolen == complete chunks serialized
1516 uint32_t nextIndex = i + buffersStolen + 1;
1517 bytesStolenFromNextBuffer = std::min(vec[nextIndex].iov_len,
1518 minWriteSize_ - len);
1519 if (bytesStolenFromNextBuffer > 0) {
1520 assert(vec[nextIndex].iov_base != nullptr);
1523 vec[nextIndex].iov_base,
1524 bytesStolenFromNextBuffer);
1526 len += bytesStolenFromNextBuffer;
1527 if (bytesStolenFromNextBuffer < vec[nextIndex].iov_len) {
1528 // couldn't steal the whole buffer
1531 bytesStolenFromNextBuffer = 0;
1534 } while ((i + buffersStolen + 1) < count && (len < minWriteSize_));
1537 // Advance any empty buffers immediately after.
1538 if (bytesStolenFromNextBuffer == 0) {
1539 while ((i + buffersStolen + 1) < count &&
1540 vec[i + buffersStolen + 1].iov_len == 0) {
1546 isSet(flags, WriteFlags::CORK) || (i + buffersStolen + 1 < count);
1547 bytes = eorAwareSSLWrite(
1551 (isSet(flags, WriteFlags::EOR) && i + buffersStolen + 1 == count));
1554 int error = SSL_get_error(ssl_, int(bytes));
1555 if (error == SSL_ERROR_WANT_WRITE) {
1556 // The caller will register for write event if not already.
1557 *partialWritten = uint32_t(offset);
1558 return WriteResult(totalWritten);
1560 auto writeResult = interpretSSLError(int(bytes), error);
1561 if (writeResult.writeReturn < 0) {
1563 } // else fall through to below to correctly record totalWritten
1566 totalWritten += bytes;
1568 if (bytes == (ssize_t)len) {
1569 // The full iovec is written.
1570 (*countWritten) += 1 + buffersStolen;
1574 bytes += offset; // adjust bytes to account for all of v
1575 while (bytes >= (ssize_t)v->iov_len) {
1576 // We combined this buf with part or all of the next one, and
1577 // we managed to write all of this buf but not all of the bytes
1578 // from the next one that we'd hoped to write.
1579 bytes -= v->iov_len;
1583 *partialWritten = uint32_t(bytes);
1584 return WriteResult(totalWritten);
1588 return WriteResult(totalWritten);
1591 int AsyncSSLSocket::eorAwareSSLWrite(SSL *ssl, const void *buf, int n,
1593 if (eor && isEorTrackingEnabled()) {
1594 if (appEorByteNo_) {
1595 // cannot track for more than one app byte EOR
1596 CHECK(appEorByteNo_ == appBytesWritten_ + n);
1598 appEorByteNo_ = appBytesWritten_ + n;
1601 // 1. It is fine to keep updating minEorRawByteNo_.
1602 // 2. It is _min_ in the sense that SSL record will add some overhead.
1603 minEorRawByteNo_ = getRawBytesWritten() + n;
1606 n = sslWriteImpl(ssl, buf, n);
1608 appBytesWritten_ += n;
1609 if (appEorByteNo_) {
1610 if (getRawBytesWritten() >= minEorRawByteNo_) {
1611 minEorRawByteNo_ = 0;
1613 if(appBytesWritten_ == appEorByteNo_) {
1616 CHECK(appBytesWritten_ < appEorByteNo_);
1623 void AsyncSSLSocket::sslInfoCallback(const SSL* ssl, int where, int ret) {
1624 AsyncSSLSocket *sslSocket = AsyncSSLSocket::getFromSSL(ssl);
1625 if (sslSocket->handshakeComplete_ && (where & SSL_CB_HANDSHAKE_START)) {
1626 sslSocket->renegotiateAttempted_ = true;
1628 if (where & SSL_CB_READ_ALERT) {
1629 const char* type = SSL_alert_type_string(ret);
1631 const char* desc = SSL_alert_desc_string(ret);
1632 sslSocket->alertsReceived_.emplace_back(
1633 *type, StringPiece(desc, std::strlen(desc)));
1638 int AsyncSSLSocket::bioWrite(BIO* b, const char* in, int inl) {
1641 AsyncSSLSocket* tsslSock;
1643 iov.iov_base = const_cast<char*>(in);
1644 iov.iov_len = size_t(inl);
1645 memset(&msg, 0, sizeof(msg));
1649 auto appData = OpenSSLUtils::getBioAppData(b);
1652 tsslSock = reinterpret_cast<AsyncSSLSocket*>(appData);
1655 WriteFlags flags = WriteFlags::NONE;
1656 if (tsslSock->isEorTrackingEnabled() && tsslSock->minEorRawByteNo_ &&
1657 tsslSock->minEorRawByteNo_ <= BIO_number_written(b) + inl) {
1658 flags |= WriteFlags::EOR;
1661 if (tsslSock->corkCurrentWrite_) {
1662 flags |= WriteFlags::CORK;
1665 int msg_flags = tsslSock->getSendMsgParamsCB()->getFlags(flags);
1666 msg.msg_controllen =
1667 tsslSock->getSendMsgParamsCB()->getAncillaryDataSize(flags);
1668 CHECK_GE(AsyncSocket::SendMsgParamsCallback::maxAncillaryDataSize,
1669 msg.msg_controllen);
1670 if (msg.msg_controllen != 0) {
1671 msg.msg_control = reinterpret_cast<char*>(alloca(msg.msg_controllen));
1672 tsslSock->getSendMsgParamsCB()->getAncillaryData(flags, msg.msg_control);
1675 auto result = tsslSock->sendSocketMessage(
1676 OpenSSLUtils::getBioFd(b, nullptr), &msg, msg_flags);
1677 BIO_clear_retry_flags(b);
1678 if (!result.exception && result.writeReturn <= 0) {
1679 if (OpenSSLUtils::getBioShouldRetryWrite(int(result.writeReturn))) {
1680 BIO_set_retry_write(b);
1683 return int(result.writeReturn);
1686 int AsyncSSLSocket::bioRead(BIO* b, char* out, int outl) {
1690 BIO_clear_retry_flags(b);
1692 auto appData = OpenSSLUtils::getBioAppData(b);
1694 auto sslSock = reinterpret_cast<AsyncSSLSocket*>(appData);
1696 if (sslSock->preReceivedData_ && !sslSock->preReceivedData_->empty()) {
1697 VLOG(5) << "AsyncSSLSocket::bioRead() this=" << sslSock
1698 << ", reading pre-received data";
1700 Cursor cursor(sslSock->preReceivedData_.get());
1701 auto len = cursor.pullAtMost(out, outl);
1704 queue.append(std::move(sslSock->preReceivedData_));
1705 queue.trimStart(len);
1706 sslSock->preReceivedData_ = queue.move();
1709 auto result = recv(OpenSSLUtils::getBioFd(b, nullptr), out, outl, 0);
1710 if (result <= 0 && OpenSSLUtils::getBioShouldRetryWrite(result)) {
1711 BIO_set_retry_read(b);
1717 int AsyncSSLSocket::sslVerifyCallback(
1719 X509_STORE_CTX* x509Ctx) {
1720 SSL* ssl = (SSL*) X509_STORE_CTX_get_ex_data(
1721 x509Ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
1722 AsyncSSLSocket* self = AsyncSSLSocket::getFromSSL(ssl);
1724 VLOG(3) << "AsyncSSLSocket::sslVerifyCallback() this=" << self << ", "
1725 << "fd=" << self->fd_ << ", preverifyOk=" << preverifyOk;
1726 return (self->handshakeCallback_) ?
1727 self->handshakeCallback_->handshakeVer(self, preverifyOk, x509Ctx) :
1731 void AsyncSSLSocket::enableClientHelloParsing() {
1732 parseClientHello_ = true;
1733 clientHelloInfo_.reset(new ssl::ClientHelloInfo());
1736 void AsyncSSLSocket::resetClientHelloParsing(SSL *ssl) {
1737 SSL_set_msg_callback(ssl, nullptr);
1738 SSL_set_msg_callback_arg(ssl, nullptr);
1739 clientHelloInfo_->clientHelloBuf_.clear();
1742 void AsyncSSLSocket::clientHelloParsingCallback(int written,
1749 AsyncSSLSocket *sock = static_cast<AsyncSSLSocket*>(arg);
1751 sock->resetClientHelloParsing(ssl);
1754 if (contentType != SSL3_RT_HANDSHAKE) {
1761 auto& clientHelloBuf = sock->clientHelloInfo_->clientHelloBuf_;
1762 clientHelloBuf.append(IOBuf::wrapBuffer(buf, len));
1764 Cursor cursor(clientHelloBuf.front());
1765 if (cursor.read<uint8_t>() != SSL3_MT_CLIENT_HELLO) {
1766 sock->resetClientHelloParsing(ssl);
1770 if (cursor.totalLength() < 3) {
1771 clientHelloBuf.trimEnd(len);
1772 clientHelloBuf.append(IOBuf::copyBuffer(buf, len));
1776 uint32_t messageLength = cursor.read<uint8_t>();
1777 messageLength <<= 8;
1778 messageLength |= cursor.read<uint8_t>();
1779 messageLength <<= 8;
1780 messageLength |= cursor.read<uint8_t>();
1781 if (cursor.totalLength() < messageLength) {
1782 clientHelloBuf.trimEnd(len);
1783 clientHelloBuf.append(IOBuf::copyBuffer(buf, len));
1787 sock->clientHelloInfo_->clientHelloMajorVersion_ = cursor.read<uint8_t>();
1788 sock->clientHelloInfo_->clientHelloMinorVersion_ = cursor.read<uint8_t>();
1790 cursor.skip(4); // gmt_unix_time
1791 cursor.skip(28); // random_bytes
1793 cursor.skip(cursor.read<uint8_t>()); // session_id
1795 uint16_t cipherSuitesLength = cursor.readBE<uint16_t>();
1796 for (int i = 0; i < cipherSuitesLength; i += 2) {
1797 sock->clientHelloInfo_->
1798 clientHelloCipherSuites_.push_back(cursor.readBE<uint16_t>());
1801 uint8_t compressionMethodsLength = cursor.read<uint8_t>();
1802 for (int i = 0; i < compressionMethodsLength; ++i) {
1803 sock->clientHelloInfo_->
1804 clientHelloCompressionMethods_.push_back(cursor.readBE<uint8_t>());
1807 if (cursor.totalLength() > 0) {
1808 uint16_t extensionsLength = cursor.readBE<uint16_t>();
1809 while (extensionsLength) {
1810 ssl::TLSExtension extensionType =
1811 static_cast<ssl::TLSExtension>(cursor.readBE<uint16_t>());
1812 sock->clientHelloInfo_->
1813 clientHelloExtensions_.push_back(extensionType);
1814 extensionsLength -= 2;
1815 uint16_t extensionDataLength = cursor.readBE<uint16_t>();
1816 extensionsLength -= 2;
1817 extensionsLength -= extensionDataLength;
1819 if (extensionType == ssl::TLSExtension::SIGNATURE_ALGORITHMS) {
1821 extensionDataLength -= 2;
1822 while (extensionDataLength) {
1823 ssl::HashAlgorithm hashAlg =
1824 static_cast<ssl::HashAlgorithm>(cursor.readBE<uint8_t>());
1825 ssl::SignatureAlgorithm sigAlg =
1826 static_cast<ssl::SignatureAlgorithm>(cursor.readBE<uint8_t>());
1827 extensionDataLength -= 2;
1828 sock->clientHelloInfo_->
1829 clientHelloSigAlgs_.emplace_back(hashAlg, sigAlg);
1831 } else if (extensionType == ssl::TLSExtension::SUPPORTED_VERSIONS) {
1833 extensionDataLength -= 1;
1834 while (extensionDataLength) {
1835 sock->clientHelloInfo_->clientHelloSupportedVersions_.push_back(
1836 cursor.readBE<uint16_t>());
1837 extensionDataLength -= 2;
1840 cursor.skip(extensionDataLength);
1844 } catch (std::out_of_range&) {
1845 // we'll use what we found and cleanup below.
1846 VLOG(4) << "AsyncSSLSocket::clientHelloParsingCallback(): "
1847 << "buffer finished unexpectedly." << " AsyncSSLSocket socket=" << sock;
1850 sock->resetClientHelloParsing(ssl);
1853 void AsyncSSLSocket::getSSLClientCiphers(
1854 std::string& clientCiphers,
1855 bool convertToString) const {
1856 std::string ciphers;
1858 if (parseClientHello_ == false
1859 || clientHelloInfo_->clientHelloCipherSuites_.empty()) {
1865 for (auto originalCipherCode : clientHelloInfo_->clientHelloCipherSuites_)
1873 bool nameFound = convertToString;
1875 if (convertToString) {
1876 const auto& name = OpenSSLUtils::getCipherName(originalCipherCode);
1886 std::array<uint8_t, 2>{{
1887 static_cast<uint8_t>((originalCipherCode >> 8) & 0xffL),
1888 static_cast<uint8_t>(originalCipherCode & 0x00ffL) }},
1890 /* append to ciphers = */ true);
1894 clientCiphers = std::move(ciphers);
1897 std::string AsyncSSLSocket::getSSLClientComprMethods() const {
1898 if (!parseClientHello_) {
1901 return folly::join(":", clientHelloInfo_->clientHelloCompressionMethods_);
1904 std::string AsyncSSLSocket::getSSLClientExts() const {
1905 if (!parseClientHello_) {
1908 return folly::join(":", clientHelloInfo_->clientHelloExtensions_);
1911 std::string AsyncSSLSocket::getSSLClientSigAlgs() const {
1912 if (!parseClientHello_) {
1916 std::string sigAlgs;
1917 sigAlgs.reserve(clientHelloInfo_->clientHelloSigAlgs_.size() * 4);
1918 for (size_t i = 0; i < clientHelloInfo_->clientHelloSigAlgs_.size(); i++) {
1920 sigAlgs.push_back(':');
1922 sigAlgs.append(folly::to<std::string>(
1923 clientHelloInfo_->clientHelloSigAlgs_[i].first));
1924 sigAlgs.push_back(',');
1925 sigAlgs.append(folly::to<std::string>(
1926 clientHelloInfo_->clientHelloSigAlgs_[i].second));
1932 std::string AsyncSSLSocket::getSSLClientSupportedVersions() const {
1933 if (!parseClientHello_) {
1936 return folly::join(":", clientHelloInfo_->clientHelloSupportedVersions_);
1939 std::string AsyncSSLSocket::getSSLAlertsReceived() const {
1942 for (const auto& alert : alertsReceived_) {
1946 ret.append(folly::to<std::string>(alert.first, ": ", alert.second));
1952 void AsyncSSLSocket::setSSLCertVerificationAlert(std::string alert) {
1953 sslVerificationAlert_ = std::move(alert);
1956 std::string AsyncSSLSocket::getSSLCertVerificationAlert() const {
1957 return sslVerificationAlert_;
1960 void AsyncSSLSocket::getSSLSharedCiphers(std::string& sharedCiphers) const {
1961 char ciphersBuffer[1024];
1962 ciphersBuffer[0] = '\0';
1963 SSL_get_shared_ciphers(ssl_, ciphersBuffer, sizeof(ciphersBuffer) - 1);
1964 sharedCiphers = ciphersBuffer;
1967 void AsyncSSLSocket::getSSLServerCiphers(std::string& serverCiphers) const {
1968 serverCiphers = SSL_get_cipher_list(ssl_, 0);
1971 while ((cipher = SSL_get_cipher_list(ssl_, i)) != nullptr) {
1972 serverCiphers.append(":");
1973 serverCiphers.append(cipher);