proxygen
AsyncSSLSocket.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-present Facebook, Inc.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
18 
21 
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/types.h>
25 #include <chrono>
26 #include <memory>
27 
28 #include <folly/Format.h>
29 #include <folly/SocketAddress.h>
30 #include <folly/SpinLock.h>
31 #include <folly/io/Cursor.h>
32 #include <folly/io/IOBuf.h>
33 #include <folly/lang/Bits.h>
35 
37 using folly::SSLContext;
38 using std::shared_ptr;
39 using std::string;
40 
41 using folly::Endian;
42 using folly::IOBuf;
43 using folly::SpinLock;
45 using folly::io::Cursor;
46 using std::bind;
47 using std::unique_ptr;
48 
49 namespace {
50 using folly::AsyncSocket;
53 using folly::Optional;
54 using folly::SSLContext;
55 // For OpenSSL portability API
56 using namespace folly::ssl;
58 
59 // We have one single dummy SSL context so that we can implement attach
60 // and detach methods in a thread safe fashion without modifying opnessl.
61 static SSLContext* dummyCtx = nullptr;
62 static SpinLock dummyCtxLock;
63 
64 // If given min write size is less than this, buffer will be allocated on
65 // stack, otherwise it is allocated on heap
66 const size_t MAX_STACK_BUF_SIZE = 2048;
67 
68 // This converts "illegal" shutdowns into ZERO_RETURN
69 inline bool zero_return(int error, int rc) {
70  return (error == SSL_ERROR_ZERO_RETURN || (rc == 0 && errno == 0));
71 }
72 
73 class AsyncSSLCertificate : public folly::AsyncTransportCertificate {
74  public:
75  // assumed to be non null
76  explicit AsyncSSLCertificate(folly::ssl::X509UniquePtr x509)
77  : x509_(std::move(x509)) {}
78 
79  folly::ssl::X509UniquePtr getX509() const override {
80  X509_up_ref(x509_.get());
81  return folly::ssl::X509UniquePtr(x509_.get());
82  }
83 
84  std::string getIdentity() const override {
85  return OpenSSLUtils::getCommonName(x509_.get());
86  }
87 
88  private:
90 };
91 
92 class AsyncSSLSocketConnector : public AsyncSocket::ConnectCallback,
93  public AsyncSSLSocket::HandshakeCB {
94  private:
95  AsyncSSLSocket* sslSocket_;
96  AsyncSSLSocket::ConnectCallback* callback_;
97  std::chrono::milliseconds timeout_;
98  std::chrono::steady_clock::time_point startTime_;
99 
100  protected:
101  ~AsyncSSLSocketConnector() override {}
102 
103  public:
104  AsyncSSLSocketConnector(
105  AsyncSSLSocket* sslSocket,
106  AsyncSocket::ConnectCallback* callback,
107  std::chrono::milliseconds timeout)
108  : sslSocket_(sslSocket),
109  callback_(callback),
110  timeout_(timeout),
111  startTime_(std::chrono::steady_clock::now()) {}
112 
113  void connectSuccess() noexcept override {
114  VLOG(7) << "client socket connected";
115 
116  std::chrono::milliseconds timeoutLeft{0};
117  if (timeout_ > std::chrono::milliseconds::zero()) {
118  auto curTime = std::chrono::steady_clock::now();
119 
120  timeoutLeft = std::chrono::duration_cast<std::chrono::milliseconds>(
121  timeout_ - (curTime - startTime_));
122  if (timeoutLeft <= std::chrono::milliseconds::zero()) {
123  AsyncSocketException ex(
126  "SSL connect timed out after {}ms", timeout_.count()));
127  fail(ex);
128  delete this;
129  return;
130  }
131  }
132  sslSocket_->sslConn(this, timeoutLeft);
133  }
134 
135  void connectErr(const AsyncSocketException& ex) noexcept override {
136  VLOG(1) << "TCP connect failed: " << ex.what();
137  fail(ex);
138  delete this;
139  }
140 
141  void handshakeSuc(AsyncSSLSocket* /* sock */) noexcept override {
142  VLOG(7) << "client handshake success";
143  if (callback_) {
144  callback_->connectSuccess();
145  }
146  delete this;
147  }
148 
149  void handshakeErr(
150  AsyncSSLSocket* /* socket */,
151  const AsyncSocketException& ex) noexcept override {
152  VLOG(1) << "client handshakeErr: " << ex.what();
153  fail(ex);
154  delete this;
155  }
156 
157  void fail(const AsyncSocketException& ex) {
158  // fail is a noop if called twice
159  if (callback_) {
160  AsyncSSLSocket::ConnectCallback* cb = callback_;
161  callback_ = nullptr;
162 
163  cb->connectErr(ex);
164  sslSocket_->closeNow();
165  // closeNow can call handshakeErr if it hasn't been called already.
166  // So this may have been deleted, no member variable access beyond this
167  // point
168  // Note that closeNow may invoke writeError callbacks if the socket had
169  // write data pending connection completion.
170  }
171  }
172 };
173 
174 void setup_SSL_CTX(SSL_CTX* ctx) {
175 #ifdef SSL_MODE_RELEASE_BUFFERS
176  SSL_CTX_set_mode(
177  ctx,
178  SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE |
179  SSL_MODE_RELEASE_BUFFERS);
180 #else
181  SSL_CTX_set_mode(
182  ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
183 #endif
184 // SSL_CTX_set_mode is a Macro
185 #ifdef SSL_MODE_WRITE_IOVEC
186  SSL_CTX_set_mode(ctx, SSL_CTX_get_mode(ctx) | SSL_MODE_WRITE_IOVEC);
187 #endif
188 }
189 
190 // Note: This is a Leaky Meyer's Singleton. The reason we can't use a non-leaky
191 // thing is because we will be setting this BIO_METHOD* inside BIOs owned by
192 // various SSL objects which may get callbacks even during teardown. We may
193 // eventually try to fix this
194 static BIO_METHOD* getSSLBioMethod() {
195  static auto const instance = OpenSSLUtils::newSocketBioMethod().release();
196  return instance;
197 }
198 
199 void* initsslBioMethod() {
200  auto sslBioMethod = getSSLBioMethod();
201  // override the bwrite method for MSG_EOR support
204 
205  // Note that the sslBioMethod.type and sslBioMethod.name are not
206  // set here. openssl code seems to be checking ".type == BIO_TYPE_SOCKET" and
207  // then have specific handlings. The sslWriteBioWrite should be compatible
208  // with the one in openssl.
209 
210  // Return something here to enable AsyncSSLSocket to call this method using
211  // a function-scoped static.
212  return nullptr;
213 }
214 
215 } // namespace
216 
217 namespace folly {
218 
223  const shared_ptr<SSLContext>& ctx,
224  EventBase* evb,
225  bool deferSecurityNegotiation)
226  : AsyncSocket(evb),
227  ctx_(ctx),
228  handshakeTimeout_(this, evb),
229  connectionTimeout_(this, evb) {
230  init();
231  if (deferSecurityNegotiation) {
233  }
234 }
235 
240  const shared_ptr<SSLContext>& ctx,
241  EventBase* evb,
242  int fd,
243  bool server,
244  bool deferSecurityNegotiation)
245  : AsyncSocket(evb, fd),
246  server_(server),
247  ctx_(ctx),
248  handshakeTimeout_(this, evb),
249  connectionTimeout_(this, evb) {
250  noTransparentTls_ = true;
251  init();
252  if (server) {
253  SSL_CTX_set_info_callback(
254  ctx_->getSSLCtx(), AsyncSSLSocket::sslInfoCallback);
255  }
256  if (deferSecurityNegotiation) {
258  }
259 }
260 
262  const shared_ptr<SSLContext>& ctx,
263  AsyncSocket::UniquePtr oldAsyncSocket,
264  bool server,
265  bool deferSecurityNegotiation)
266  : AsyncSocket(std::move(oldAsyncSocket)),
267  server_(server),
268  ctx_(ctx),
271  noTransparentTls_ = true;
272  init();
273  if (server) {
274  SSL_CTX_set_info_callback(
275  ctx_->getSSLCtx(), AsyncSSLSocket::sslInfoCallback);
276  }
277  if (deferSecurityNegotiation) {
279  }
280 }
281 
282 #if FOLLY_OPENSSL_HAS_SNI
283 
288  const shared_ptr<SSLContext>& ctx,
289  EventBase* evb,
290  const std::string& serverName,
291  bool deferSecurityNegotiation)
292  : AsyncSSLSocket(ctx, evb, deferSecurityNegotiation) {
293  tlsextHostname_ = serverName;
294 }
295 
301  const shared_ptr<SSLContext>& ctx,
302  EventBase* evb,
303  int fd,
304  const std::string& serverName,
305  bool deferSecurityNegotiation)
306  : AsyncSSLSocket(ctx, evb, fd, false, deferSecurityNegotiation) {
307  tlsextHostname_ = serverName;
308 }
309 #endif // FOLLY_OPENSSL_HAS_SNI
310 
312  VLOG(3) << "actual destruction of AsyncSSLSocket(this=" << this
313  << ", evb=" << eventBase_ << ", fd=" << fd_
314  << ", state=" << int(state_) << ", sslState=" << sslState_
315  << ", events=" << eventFlags_ << ")";
316 }
317 
319  // Do this here to ensure we initialize this once before any use of
320  // AsyncSSLSocket instances and not as part of library load.
321  static const auto sslBioMethodInitializer = initsslBioMethod();
322  (void)sslBioMethodInitializer;
323 
324  setup_SSL_CTX(ctx_->getSSLCtx());
325 }
326 
328  // Close the SSL connection.
329  if (ssl_ != nullptr && fd_ != -1) {
330  int rc = SSL_shutdown(ssl_.get());
331  if (rc == 0) {
332  rc = SSL_shutdown(ssl_.get());
333  }
334  if (rc < 0) {
335  ERR_clear_error();
336  }
337  }
338 
339  if (sslSession_ != nullptr) {
340  SSL_SESSION_free(sslSession_);
341  sslSession_ = nullptr;
342  }
343 
345 
348  }
349 
350  DestructorGuard dg(this);
351 
353  AsyncSocketException::END_OF_FILE, "SSL connection closed locally"));
354 
355  // Close the socket.
357 }
358 
360  // SSL sockets do not support half-shutdown, so just perform a full shutdown.
361  //
362  // (Performing a full shutdown here is more desirable than doing nothing at
363  // all. The purpose of shutdownWrite() is normally to notify the other end
364  // of the connection that no more data will be sent. If we do nothing, the
365  // other end will never know that no more data is coming, and this may result
366  // in protocol deadlock.)
367  close();
368 }
369 
371  closeNow();
372 }
373 
374 bool AsyncSSLSocket::good() const {
375  return (
376  AsyncSocket::good() &&
379  sslState_ == STATE_UNINIT));
380 }
381 
382 // The TAsyncTransport definition of 'good' states that the transport is
383 // ready to perform reads and writes, so sslState_ == UNINIT must report !good.
384 // connecting can be true when the sslState_ == UNINIT because the AsyncSocket
385 // is connected but we haven't initiated the call to SSL_connect.
387  return (
388  !server_ &&
390  (AsyncSocket::good() &&
392 }
393 
395  const unsigned char* protoName = nullptr;
396  unsigned protoLength;
397  if (getSelectedNextProtocolNoThrow(&protoName, &protoLength)) {
398  return std::string(reinterpret_cast<const char*>(protoName), protoLength);
399  }
400  return "";
401 }
402 
404  if (isEorTrackingEnabled() != track) {
406  appEorByteNo_ = 0;
407  minEorRawByteNo_ = 0;
408  }
409 }
410 
412  // The bio(s) in the write path are in a chain
413  // each bio flushes to the next and finally written into the socket
414  // to get the rawBytesWritten on the socket,
415  // get the write bytes of the last bio
416  BIO* b;
417  if (!ssl_ || !(b = SSL_get_wbio(ssl_.get()))) {
418  return 0;
419  }
420  BIO* next = BIO_next(b);
421  while (next != nullptr) {
422  b = next;
423  next = BIO_next(b);
424  }
425 
426  return BIO_number_written(b);
427 }
428 
430  BIO* b;
431  if (!ssl_ || !(b = SSL_get_rbio(ssl_.get()))) {
432  return 0;
433  }
434 
435  return BIO_number_read(b);
436 }
437 
439  LOG(ERROR) << "AsyncSSLSocket(this=" << this << ", fd=" << fd_
440  << ", state=" << int(state_) << ", sslState=" << sslState_ << ", "
441  << "events=" << eventFlags_ << ", server=" << short(server_)
442  << "): "
443  << "sslAccept/Connect() called in invalid "
444  << "state, handshake callback " << handshakeCallback_
445  << ", new callback " << callback;
446  assert(!handshakeTimeout_.isScheduled());
448 
451  "sslAccept() called with socket in invalid state");
452 
454  if (callback) {
455  callback->handshakeErr(this, ex);
456  }
457 
458  failHandshake(__func__, ex);
459 }
460 
462  HandshakeCB* callback,
463  std::chrono::milliseconds timeout,
464  const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
465  DestructorGuard dg(this);
467  verifyPeer_ = verifyPeer;
468 
469  // Make sure we're in the uninitialized state
470  if (!server_ ||
472  handshakeCallback_ != nullptr) {
473  return invalidState(callback);
474  }
475 
476  // Cache local and remote socket addresses to keep them available
477  // after socket file descriptor is closed.
478  if (cacheAddrOnFailure_) {
479  cacheAddresses();
480  }
481 
483  // Make end time at least >= start time.
485 
487  handshakeCallback_ = callback;
488 
489  if (timeout > std::chrono::milliseconds::zero()) {
491  }
492 
493  /* register for a read operation (waiting for CLIENT HELLO) */
495 
497 }
498 
499 void AsyncSSLSocket::attachSSLContext(const std::shared_ptr<SSLContext>& ctx) {
500  // Check to ensure we are in client mode. Changing a server's ssl
501  // context doesn't make sense since clients of that server would likely
502  // become confused when the server's context changes.
503  DCHECK(!server_);
504  DCHECK(!ctx_);
505  DCHECK(ctx);
506  DCHECK(ctx->getSSLCtx());
507  ctx_ = ctx;
508 
509  // It's possible this could be attached before ssl_ is set up
510  if (!ssl_) {
511  return;
512  }
513 
514  // In order to call attachSSLContext, detachSSLContext must have been
515  // previously called.
516  // We need to update the initial_ctx if necessary
517  // The 'initial_ctx' inside an SSL* points to the context that it was created
518  // with, which is also where session callbacks and servername callbacks
519  // happen.
520  // When we switch to a different SSL_CTX, we want to update the initial_ctx as
521  // well so that any callbacks don't go to a different object
522  // NOTE: this will only work if we have access to ssl_ internals, so it may
523  // not work on
524  // OpenSSL version >= 1.1.0
525  auto sslCtx = ctx->getSSLCtx();
526  OpenSSLUtils::setSSLInitialCtx(ssl_.get(), sslCtx);
527  // Detach sets the socket's context to the dummy context. Thus we must acquire
528  // this lock.
529  SpinLockGuard guard(dummyCtxLock);
530  SSL_set_SSL_CTX(ssl_.get(), sslCtx);
531 }
532 
533 void AsyncSSLSocket::detachSSLContext() {
534  DCHECK(ctx_);
535  ctx_.reset();
536  // It's possible for this to be called before ssl_ has been
537  // set up
538  if (!ssl_) {
539  return;
540  }
541  // The 'initial_ctx' inside an SSL* points to the context that it was created
542  // with, which is also where session callbacks and servername callbacks
543  // happen.
544  // Detach the initial_ctx as well. It will be reattached in attachSSLContext
545  // it is used for session info.
546  // NOTE: this will only work if we have access to ssl_ internals, so it may
547  // not work on
548  // OpenSSL version >= 1.1.0
549  SSL_CTX* initialCtx = OpenSSLUtils::getSSLInitialCtx(ssl_.get());
550  if (initialCtx) {
551  SSL_CTX_free(initialCtx);
552  OpenSSLUtils::setSSLInitialCtx(ssl_.get(), nullptr);
553  }
554 
555  SpinLockGuard guard(dummyCtxLock);
556  if (nullptr == dummyCtx) {
557  // We need to lazily initialize the dummy context so we don't
558  // accidentally override any programmatic settings to openssl
559  dummyCtx = new SSLContext;
560  }
561  // We must remove this socket's references to its context right now
562  // since this socket could get passed to any thread. If the context has
563  // had its locking disabled, just doing a set in attachSSLContext()
564  // would not be thread safe.
565  SSL_set_SSL_CTX(ssl_.get(), dummyCtx->getSSLCtx());
566 }
567 
568 #if FOLLY_OPENSSL_HAS_SNI
569 void AsyncSSLSocket::switchServerSSLContext(
570  const std::shared_ptr<SSLContext>& handshakeCtx) {
571  CHECK(server_);
572  if (sslState_ != STATE_ACCEPTING) {
573  // We log it here and allow the switch.
574  // It should not affect our re-negotiation support (which
575  // is not supported now).
576  VLOG(6) << "fd=" << getFd()
577  << " renegotation detected when switching SSL_CTX";
578  }
579 
580  setup_SSL_CTX(handshakeCtx->getSSLCtx());
581  SSL_CTX_set_info_callback(
582  handshakeCtx->getSSLCtx(), AsyncSSLSocket::sslInfoCallback);
583  handshakeCtx_ = handshakeCtx;
584  SSL_set_SSL_CTX(ssl_.get(), handshakeCtx->getSSLCtx());
585 }
586 
587 bool AsyncSSLSocket::isServerNameMatch() const {
588  CHECK(!server_);
589 
590  if (!ssl_) {
591  return false;
592  }
593 
594  SSL_SESSION* ss = SSL_get_session(ssl_.get());
595  if (!ss) {
596  return false;
597  }
598 
599  auto tlsextHostname = SSL_SESSION_get0_hostname(ss);
600  return (tlsextHostname && !tlsextHostname_.compare(tlsextHostname));
601 }
602 
603 void AsyncSSLSocket::setServerName(std::string serverName) noexcept {
604  tlsextHostname_ = std::move(serverName);
605 }
606 
607 #endif // FOLLY_OPENSSL_HAS_SNI
608 
610  std::chrono::milliseconds timeout) noexcept {
614  // We are expecting a callback in restartSSLAccept. The cache lookup
615  // and rsa-call necessarily have pointers to this ssl socket, so delay
616  // the cleanup until he calls us back.
617  } else if (state_ == StateEnum::CONNECTING) {
618  assert(sslState_ == STATE_CONNECTING);
619  DestructorGuard dg(this);
622  "Fallback connect timed out during TFO");
623  failHandshake(__func__, ex);
624  } else {
625  assert(
628  DestructorGuard dg(this);
632  "SSL {} timed out after {}ms",
633  (sslState_ == STATE_CONNECTING) ? "connect" : "accept",
634  timeout.count()));
635  failHandshake(__func__, ex);
636  }
637 }
638 
640  static auto index = SSL_get_ex_new_index(
641  0, (void*)"AsyncSSLSocket data index", nullptr, nullptr, nullptr);
642  return index;
643 }
644 
646  return static_cast<AsyncSSLSocket*>(
647  SSL_get_ex_data(ssl, getSSLExDataIndex()));
648 }
649 
651  const char* /* fn */,
652  const AsyncSocketException& ex) {
653  startFail();
656  }
657  invokeHandshakeErr(ex);
658  finishFail();
659 }
660 
663  if (handshakeCallback_ != nullptr) {
664  HandshakeCB* callback = handshakeCallback_;
665  handshakeCallback_ = nullptr;
666  callback->handshakeErr(this, ex);
667  }
668 }
669 
674  }
675  if (handshakeCallback_) {
676  HandshakeCB* callback = handshakeCallback_;
677  handshakeCallback_ = nullptr;
678  callback->handshakeSuc(this);
679  }
680 }
681 
683  ConnectCallback* callback,
684  const folly::SocketAddress& address,
685  int timeout,
686  const OptionMap& options,
687  const folly::SocketAddress& bindAddr) noexcept {
688  auto timeoutChrono = std::chrono::milliseconds(timeout);
689  connect(callback, address, timeoutChrono, timeoutChrono, options, bindAddr);
690 }
691 
693  ConnectCallback* callback,
694  const folly::SocketAddress& address,
695  std::chrono::milliseconds connectTimeout,
696  std::chrono::milliseconds totalConnectTimeout,
697  const OptionMap& options,
698  const folly::SocketAddress& bindAddr) noexcept {
699  assert(!server_);
700  assert(state_ == StateEnum::UNINIT);
702  noTransparentTls_ = true;
703  totalConnectTimeout_ = totalConnectTimeout;
704  if (sslState_ != STATE_UNENCRYPTED) {
705  callback = new AsyncSSLSocketConnector(this, callback, totalConnectTimeout);
706  }
708  callback, address, int(connectTimeout.count()), options, bindAddr);
709 }
710 
712  if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::USE_CTX) {
713  return ctx_->needsPeerVerification();
714  }
715  return (
716  verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY ||
717  verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT);
718 }
719 
721  // apply the settings specified in verifyPeer_
722  if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::USE_CTX) {
723  if (ctx_->needsPeerVerification()) {
724  SSL_set_verify(
725  ssl.get(),
726  ctx_->getVerificationMode(),
728  }
729  } else {
730  if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY ||
731  verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT) {
732  SSL_set_verify(
733  ssl.get(),
736  }
737  }
738 }
739 
741  auto sslBio = BIO_new(getSSLBioMethod());
742 
743  if (!sslBio) {
744  return false;
745  }
746 
747  OpenSSLUtils::setBioAppData(sslBio, this);
748  OpenSSLUtils::setBioFd(sslBio, fd_, BIO_NOCLOSE);
749  SSL_set_bio(ssl_.get(), sslBio, sslBio);
750  return true;
751 }
752 
754  HandshakeCB* callback,
755  std::chrono::milliseconds timeout,
756  const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
757  DestructorGuard dg(this);
759 
760  // Cache local and remote socket addresses to keep them available
761  // after socket file descriptor is closed.
762  if (cacheAddrOnFailure_) {
763  cacheAddresses();
764  }
765 
766  verifyPeer_ = verifyPeer;
767 
768  // Make sure we're in the uninitialized state
769  if (server_ ||
771  handshakeCallback_ != nullptr) {
772  return invalidState(callback);
773  }
774 
776  handshakeCallback_ = callback;
777 
778  try {
779  ssl_.reset(ctx_->createSSL());
780  } catch (std::exception& e) {
784  "error calling SSLContext::createSSL()");
785  LOG(ERROR) << "AsyncSSLSocket::sslConn(this=" << this << ", fd=" << fd_
786  << "): " << e.what();
787  return failHandshake(__func__, ex);
788  }
789 
790  if (!setupSSLBio()) {
793  AsyncSocketException::INTERNAL_ERROR, "error creating SSL bio");
794  return failHandshake(__func__, ex);
795  }
796 
798 
799  if (sslSession_ != nullptr) {
801  SSL_set_session(ssl_.get(), sslSession_);
802  SSL_SESSION_free(sslSession_);
803  sslSession_ = nullptr;
804  }
805 #if FOLLY_OPENSSL_HAS_SNI
806  if (tlsextHostname_.size()) {
807  SSL_set_tlsext_host_name(ssl_.get(), tlsextHostname_.c_str());
808  }
809 #endif
810 
811  SSL_set_ex_data(ssl_.get(), getSSLExDataIndex(), this);
812 
813  handshakeConnectTimeout_ = timeout;
814  startSSLConnect();
815 }
816 
817 // This could be called multiple times, during normal ssl connections
818 // and after TFO fallback.
821  // Make end time at least >= start time.
823  if (handshakeConnectTimeout_ > std::chrono::milliseconds::zero()) {
825  }
826  handleConnect();
827 }
828 
830  if (ssl_ != nullptr && sslState_ == STATE_ESTABLISHED) {
831  return SSL_get1_session(ssl_.get());
832  }
833 
834  return sslSession_;
835 }
836 
837 const SSL* AsyncSSLSocket::getSSL() const {
838  return ssl_.get();
839 }
840 
841 void AsyncSSLSocket::setSSLSession(SSL_SESSION* session, bool takeOwnership) {
842  if (sslSession_) {
843  SSL_SESSION_free(sslSession_);
844  }
845  sslSession_ = session;
846  if (!takeOwnership && session != nullptr) {
847  // Increment the reference count
848  // This API exists in BoringSSL and OpenSSL 1.1.0
849  SSL_SESSION_up_ref(session);
850  }
851 }
852 
854  const unsigned char** protoName,
855  unsigned* protoLen) const {
856  if (!getSelectedNextProtocolNoThrow(protoName, protoLen)) {
857  throw AsyncSocketException(
858  AsyncSocketException::NOT_SUPPORTED, "ALPN not supported");
859  }
860 }
861 
863  const unsigned char** protoName,
864  unsigned* protoLen) const {
865  *protoName = nullptr;
866  *protoLen = 0;
867 #if FOLLY_OPENSSL_HAS_ALPN
868  SSL_get0_alpn_selected(ssl_.get(), protoName, protoLen);
869  return true;
870 #else
871  return false;
872 #endif
873 }
874 
876  if (ssl_ != nullptr && sslState_ == STATE_ESTABLISHED) {
877  return SSL_session_reused(ssl_.get());
878  }
879  return false;
880 }
881 
883  return (ssl_ != nullptr) ? SSL_get_cipher_name(ssl_.get()) : nullptr;
884 }
885 
886 /* static */
888  if (ssl == nullptr) {
889  return nullptr;
890  }
891 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
892  return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
893 #else
894  return nullptr;
895 #endif
896 }
897 
898 const char* AsyncSSLSocket::getSSLServerName() const {
899 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
900  return getSSLServerNameFromSSL(ssl_.get());
901 #else
902  throw AsyncSocketException(
903  AsyncSocketException::NOT_SUPPORTED, "SNI not supported");
904 #endif
905 }
906 
908  return getSSLServerNameFromSSL(ssl_.get());
909 }
910 
912  return (ssl_ != nullptr) ? SSL_version(ssl_.get()) : 0;
913 }
914 
916  X509* cert = (ssl_ != nullptr) ? SSL_get_certificate(ssl_.get()) : nullptr;
917  if (cert) {
918  int nid = X509_get_signature_nid(cert);
919  return OBJ_nid2ln(nid);
920  }
921  return nullptr;
922 }
923 
925  int certSize = 0;
926  X509* cert = (ssl_ != nullptr) ? SSL_get_certificate(ssl_.get()) : nullptr;
927  if (cert) {
928  EVP_PKEY* key = X509_get_pubkey(cert);
929  certSize = EVP_PKEY_bits(key);
930  EVP_PKEY_free(key);
931  }
932  return certSize;
933 }
934 
936  if (peerCertData_) {
937  return peerCertData_.get();
938  }
939  if (ssl_ != nullptr) {
940  auto peerX509 = SSL_get_peer_certificate(ssl_.get());
941  if (peerX509) {
942  // already up ref'd
943  folly::ssl::X509UniquePtr peer(peerX509);
944  peerCertData_ = std::make_unique<AsyncSSLCertificate>(std::move(peer));
945  }
946  }
947  return peerCertData_.get();
948 }
949 
951  if (selfCertData_) {
952  return selfCertData_.get();
953  }
954  if (ssl_ != nullptr) {
955  auto selfX509 = SSL_get_certificate(ssl_.get());
956  if (selfX509) {
957  // need to upref
958  X509_up_ref(selfX509);
959  folly::ssl::X509UniquePtr peer(selfX509);
960  selfCertData_ = std::make_unique<AsyncSSLCertificate>(std::move(peer));
961  }
962  }
963  return selfCertData_.get();
964 }
965 
966 // TODO: deprecate/remove in favor of getSelfCertificate.
967 const X509* AsyncSSLSocket::getSelfCert() const {
968  return (ssl_ != nullptr) ? SSL_get_certificate(ssl_.get()) : nullptr;
969 }
970 
972  int ret,
973  int* sslErrorOut,
974  unsigned long* errErrorOut) noexcept {
975  *errErrorOut = 0;
976  int error = *sslErrorOut = SSL_get_error(ssl_.get(), ret);
977  if (error == SSL_ERROR_WANT_READ) {
978  // Register for read event if not already.
980  return true;
981  } else if (error == SSL_ERROR_WANT_WRITE) {
982  VLOG(3) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
983  << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
984  << "SSL_ERROR_WANT_WRITE";
985  // Register for write event if not already.
987  return true;
988 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
989  } else if (error == SSL_ERROR_WANT_SESS_CACHE_LOOKUP) {
990  // We will block but we can't register our own socket. The callback that
991  // triggered this code will re-call handleAccept at the appropriate time.
992 
993  // We can only get here if the linked libssl.so has support for this feature
994  // as well, otherwise SSL_get_error cannot return our error code.
996 
997  // Unregister for all events while blocked here
1000 
1001  // The timeout (if set) keeps running here
1002  return true;
1003 #endif
1004  } else if ((false
1005 #ifdef SSL_ERROR_WANT_RSA_ASYNC_PENDING
1006  || error == SSL_ERROR_WANT_RSA_ASYNC_PENDING
1007 #endif
1008 #ifdef SSL_ERROR_WANT_ECDSA_ASYNC_PENDING
1009  || error == SSL_ERROR_WANT_ECDSA_ASYNC_PENDING
1010 #endif
1011 #ifdef SSL_ERROR_WANT_ASYNC // OpenSSL 1.1.0 Async API
1012  || error == SSL_ERROR_WANT_ASYNC
1013 #endif
1014  )) {
1015  // Our custom openssl function has kicked off an async request to do
1016  // rsa/ecdsa private key operation. When that call returns, a callback will
1017  // be invoked that will re-call handleAccept.
1019 
1020  // Unregister for all events while blocked here
1023 
1024 #ifdef SSL_ERROR_WANT_ASYNC
1025  if (error == SSL_ERROR_WANT_ASYNC) {
1026  size_t numfds;
1027  if (SSL_get_all_async_fds(ssl_.get(), NULL, &numfds) <= 0) {
1028  VLOG(4) << "SSL_ERROR_WANT_ASYNC but no async FDs set!";
1029  return false;
1030  }
1031  if (numfds != 1) {
1032  VLOG(4) << "SSL_ERROR_WANT_ASYNC expected exactly 1 async fd, got "
1033  << numfds;
1034  return false;
1035  }
1036  OSSL_ASYNC_FD ofd; // This should just be an int in POSIX
1037  if (SSL_get_all_async_fds(ssl_.get(), &ofd, &numfds) <= 0) {
1038  VLOG(4) << "SSL_ERROR_WANT_ASYNC cant get async fd";
1039  return false;
1040  }
1041 
1042  auto asyncPipeReader = AsyncPipeReader::newReader(eventBase_, ofd);
1043  auto asyncPipeReaderPtr = asyncPipeReader.get();
1047  std::move(asyncPipeReader), this, DestructorGuard(this)));
1048  }
1049  asyncPipeReaderPtr->setReadCB(asyncOperationFinishCallback_.get());
1050  }
1051 #endif
1052 
1053  // The timeout (if set) keeps running here
1054  return true;
1055  } else {
1056  unsigned long lastError = *errErrorOut = ERR_get_error();
1057  VLOG(6) << "AsyncSSLSocket(fd=" << fd_ << ", "
1058  << "state=" << state_ << ", "
1059  << "sslState=" << sslState_ << ", "
1060  << "events=" << std::hex << eventFlags_ << "): "
1061  << "SSL error: " << error << ", "
1062  << "errno: " << errno << ", "
1063  << "ret: " << ret << ", "
1064  << "read: " << BIO_number_read(SSL_get_rbio(ssl_.get())) << ", "
1065  << "written: " << BIO_number_written(SSL_get_wbio(ssl_.get()))
1066  << ", "
1067  << "func: " << ERR_func_error_string(lastError) << ", "
1068  << "reason: " << ERR_reason_error_string(lastError);
1069  return false;
1070  }
1071 }
1072 
1074  // openssl may have buffered data that it read from the socket already.
1075  // In this case we have to process it immediately, rather than waiting for
1076  // the socket to become readable again.
1077  if (ssl_ != nullptr && SSL_pending(ssl_.get()) > 0) {
1079  } else {
1081  }
1082 }
1083 
1085  VLOG(3) << "AsyncSSLSocket::restartSSLAccept() this=" << this
1086  << ", fd=" << fd_ << ", state=" << int(state_) << ", "
1087  << "sslState=" << sslState_ << ", events=" << eventFlags_;
1088  DestructorGuard dg(this);
1089  assert(
1092  if (sslState_ == STATE_CLOSED) {
1093  // I sure hope whoever closed this socket didn't delete it already,
1094  // but this is not strictly speaking an error
1095  return;
1096  }
1097  if (sslState_ == STATE_ERROR) {
1098  // go straight to fail if timeout expired during lookup
1100  AsyncSocketException::TIMED_OUT, "SSL accept timed out");
1101  failHandshake(__func__, ex);
1102  return;
1103  }
1105  this->handleAccept();
1106 }
1107 
1109  VLOG(3) << "AsyncSSLSocket::handleAccept() this=" << this << ", fd=" << fd_
1110  << ", state=" << int(state_) << ", "
1111  << "sslState=" << sslState_ << ", events=" << eventFlags_;
1112  assert(server_);
1114  if (!ssl_) {
1115  /* lazily create the SSL structure */
1116  try {
1117  ssl_.reset(ctx_->createSSL());
1118  } catch (std::exception& e) {
1122  "error calling SSLContext::createSSL()");
1123  LOG(ERROR) << "AsyncSSLSocket::handleAccept(this=" << this
1124  << ", fd=" << fd_ << "): " << e.what();
1125  return failHandshake(__func__, ex);
1126  }
1127 
1128  if (!setupSSLBio()) {
1131  AsyncSocketException::INTERNAL_ERROR, "error creating write bio");
1132  return failHandshake(__func__, ex);
1133  }
1134 
1135  SSL_set_ex_data(ssl_.get(), getSSLExDataIndex(), this);
1136 
1138  }
1139 
1140  if (server_ && parseClientHello_) {
1141  SSL_set_msg_callback(
1143  SSL_set_msg_callback_arg(ssl_.get(), this);
1144  }
1145 
1146  DCHECK(ctx_->sslAcceptRunner());
1150  ctx_->sslAcceptRunner()->run(
1151  [this, dg]() { return SSL_accept(ssl_.get()); },
1152  [this, dg](int ret) { handleReturnFromSSLAccept(ret); });
1153 }
1154 
1156  if (sslState_ != STATE_ACCEPTING) {
1157  return;
1158  }
1159 
1160  if (ret <= 0) {
1161  VLOG(3) << "SSL_accept returned: " << ret;
1162  int sslError;
1163  unsigned long errError;
1164  int errnoCopy = errno;
1165  if (willBlock(ret, &sslError, &errError)) {
1166  return;
1167  } else {
1169  SSLException ex(sslError, errError, ret, errnoCopy);
1170  return failHandshake(__func__, ex);
1171  }
1172  }
1173 
1174  handshakeComplete_ = true;
1176 
1177  // Move into STATE_ESTABLISHED in the normal case that we are in
1178  // STATE_ACCEPTING.
1180 
1181  VLOG(3) << "AsyncSSLSocket " << this << ": fd " << fd_
1182  << " successfully accepted; state=" << int(state_)
1183  << ", sslState=" << sslState_ << ", events=" << eventFlags_;
1184 
1185  // Remember the EventBase we are attached to, before we start invoking any
1186  // callbacks (since the callbacks may call detachEventBase()).
1187  EventBase* originalEventBase = eventBase_;
1188 
1189  // Call the accept callback.
1191 
1192  // Note that the accept callback may have changed our state.
1193  // (set or unset the read callback, called write(), closed the socket, etc.)
1194  // The following code needs to handle these situations correctly.
1195  //
1196  // If the socket has been closed, readCallback_ and writeReqHead_ will
1197  // always be nullptr, so that will prevent us from trying to read or write.
1198  //
1199  // The main thing to check for is if eventBase_ is still originalEventBase.
1200  // If not, we have been detached from this event base, so we shouldn't
1201  // perform any more operations.
1202  if (eventBase_ != originalEventBase) {
1203  return;
1204  }
1205 
1207 }
1208 
1210  VLOG(3) << "AsyncSSLSocket::handleConnect() this=" << this << ", fd=" << fd_
1211  << ", state=" << int(state_) << ", "
1212  << "sslState=" << sslState_ << ", events=" << eventFlags_;
1213  assert(!server_);
1215  return AsyncSocket::handleConnect();
1216  }
1217 
1218  assert(
1221  assert(ssl_);
1222 
1223  auto originalState = state_;
1224  int ret = SSL_connect(ssl_.get());
1225  if (ret <= 0) {
1226  int sslError;
1227  unsigned long errError;
1228  int errnoCopy = errno;
1229  if (willBlock(ret, &sslError, &errError)) {
1230  // We fell back to connecting state due to TFO
1231  if (state_ == StateEnum::CONNECTING) {
1232  DCHECK_EQ(StateEnum::FAST_OPEN, originalState);
1235  }
1236  }
1237  return;
1238  } else {
1240  SSLException ex(sslError, errError, ret, errnoCopy);
1241  return failHandshake(__func__, ex);
1242  }
1243  }
1244 
1245  handshakeComplete_ = true;
1247 
1248  // Move into STATE_ESTABLISHED in the normal case that we are in
1249  // STATE_CONNECTING.
1251 
1252  VLOG(3) << "AsyncSSLSocket " << this << ": "
1253  << "fd " << fd_ << " successfully connected; "
1254  << "state=" << int(state_) << ", sslState=" << sslState_
1255  << ", events=" << eventFlags_;
1256 
1257  // Remember the EventBase we are attached to, before we start invoking any
1258  // callbacks (since the callbacks may call detachEventBase()).
1259  EventBase* originalEventBase = eventBase_;
1260 
1261  // Call the handshake callback.
1263 
1264  // Note that the connect callback may have changed our state.
1265  // (set or unset the read callback, called write(), closed the socket, etc.)
1266  // The following code needs to handle these situations correctly.
1267  //
1268  // If the socket has been closed, readCallback_ and writeReqHead_ will
1269  // always be nullptr, so that will prevent us from trying to read or write.
1270  //
1271  // The main thing to check for is if eventBase_ is still originalEventBase.
1272  // If not, we have been detached from this event base, so we shouldn't
1273  // perform any more operations.
1274  if (eventBase_ != originalEventBase) {
1275  return;
1276  }
1277 
1279 }
1280 
1284  if (sslState_ == SSLStateEnum::STATE_CONNECTING) {
1287  }
1288  // If we fell back to connecting state during TFO and the connection
1289  // failed, it would be an SSL failure as well.
1290  invokeHandshakeErr(ex);
1291  }
1292 }
1293 
1296  if (sslState_ == SSLStateEnum::STATE_CONNECTING) {
1297  assert(tfoAttempted_);
1298  // If we failed TFO, we'd fall back to trying to connect the socket,
1299  // to setup things like timeouts.
1300  startSSLConnect();
1301  }
1302  // still invoke the base class since it re-sets the connect time.
1304 }
1305 
1307  if (sslState_ == SSLStateEnum::STATE_CONNECTING) {
1308  // We fell back from TFO, and need to set the timeouts.
1309  // We will not have a connect callback in this case, thus if the timer
1310  // expires we would have no-one to notify.
1311  // Thus we should reset even the connect timers to point to the handshake
1312  // timeouts.
1313  assert(connectCallback_ == nullptr);
1314  // We use a different connect timeout here than the handshake timeout, so
1315  // that we can disambiguate the 2 timers.
1316  if (connectTimeout_.count() > 0) {
1318  throw AsyncSocketException(
1320  withAddr("failed to schedule AsyncSSLSocket connect timeout"));
1321  }
1322  }
1323  return;
1324  }
1326 }
1327 
1329 #ifdef SSL_MODE_MOVE_BUFFER_OWNERSHIP
1330  // turn on the buffer movable in openssl
1331  if (bufferMovableEnabled_ && ssl_ != nullptr && !isBufferMovable_ &&
1332  callback != nullptr && callback->isBufferMovable()) {
1333  SSL_set_mode(
1334  ssl_.get(), SSL_get_mode(ssl_.get()) | SSL_MODE_MOVE_BUFFER_OWNERSHIP);
1335  isBufferMovable_ = true;
1336  }
1337 #endif
1338 
1339  AsyncSocket::setReadCB(callback);
1340 }
1341 
1343  bufferMovableEnabled_ = enabled;
1344 }
1345 
1346 void AsyncSSLSocket::prepareReadBuffer(void** buf, size_t* buflen) {
1347  CHECK(readCallback_);
1348  if (isBufferMovable_) {
1349  *buf = nullptr;
1350  *buflen = 0;
1351  } else {
1352  // buf is necessary for SSLSocket without SSL_MODE_MOVE_BUFFER_OWNERSHIP
1353  readCallback_->getReadBuffer(buf, buflen);
1354  }
1355 }
1356 
1358  VLOG(5) << "AsyncSSLSocket::handleRead() this=" << this << ", fd=" << fd_
1359  << ", state=" << int(state_) << ", "
1360  << "sslState=" << sslState_ << ", events=" << eventFlags_;
1362  return AsyncSocket::handleRead();
1363  }
1364 
1365  if (sslState_ == STATE_ACCEPTING) {
1366  assert(server_);
1367  handleAccept();
1368  return;
1369  } else if (sslState_ == STATE_CONNECTING) {
1370  assert(!server_);
1371  handleConnect();
1372  return;
1373  }
1374 
1375  // Normal read
1377 }
1378 
1380 AsyncSSLSocket::performRead(void** buf, size_t* buflen, size_t* offset) {
1381  VLOG(4) << "AsyncSSLSocket::performRead() this=" << this << ", buf=" << *buf
1382  << ", buflen=" << *buflen;
1383 
1384  if (sslState_ == STATE_UNENCRYPTED) {
1385  return AsyncSocket::performRead(buf, buflen, offset);
1386  }
1387 
1388  int bytes = 0;
1389  if (!isBufferMovable_) {
1390  bytes = SSL_read(ssl_.get(), *buf, int(*buflen));
1391  }
1392 #ifdef SSL_MODE_MOVE_BUFFER_OWNERSHIP
1393  else {
1394  bytes = SSL_read_buf(ssl_.get(), buf, (int*)offset, (int*)buflen);
1395  }
1396 #endif
1397 
1398  if (server_ && renegotiateAttempted_) {
1399  LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1400  << ", sslstate=" << sslState_ << ", events=" << eventFlags_
1401  << "): client intitiated SSL renegotiation not permitted";
1402  return ReadResult(
1403  READ_ERROR,
1404  std::make_unique<SSLException>(SSLError::CLIENT_RENEGOTIATION));
1405  }
1406  if (bytes <= 0) {
1407  int error = SSL_get_error(ssl_.get(), bytes);
1408  if (error == SSL_ERROR_WANT_READ) {
1409  // The caller will register for read event if not already.
1410  if (errno == EWOULDBLOCK || errno == EAGAIN) {
1411  return ReadResult(READ_BLOCKING);
1412  } else {
1413  return ReadResult(READ_ERROR);
1414  }
1415  } else if (error == SSL_ERROR_WANT_WRITE) {
1416  // TODO: Even though we are attempting to read data, SSL_read() may
1417  // need to write data if renegotiation is being performed. We currently
1418  // don't support this and just fail the read.
1419  LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1420  << ", sslState=" << sslState_ << ", events=" << eventFlags_
1421  << "): unsupported SSL renegotiation during read";
1422  return ReadResult(
1423  READ_ERROR,
1424  std::make_unique<SSLException>(SSLError::INVALID_RENEGOTIATION));
1425  } else {
1426  if (zero_return(error, bytes)) {
1427  return ReadResult(bytes);
1428  }
1429  auto errError = ERR_get_error();
1430  VLOG(6) << "AsyncSSLSocket(fd=" << fd_ << ", "
1431  << "state=" << state_ << ", "
1432  << "sslState=" << sslState_ << ", "
1433  << "events=" << std::hex << eventFlags_ << "): "
1434  << "bytes: " << bytes << ", "
1435  << "error: " << error << ", "
1436  << "errno: " << errno << ", "
1437  << "func: " << ERR_func_error_string(errError) << ", "
1438  << "reason: " << ERR_reason_error_string(errError);
1439  return ReadResult(
1440  READ_ERROR,
1441  std::make_unique<SSLException>(error, errError, bytes, errno));
1442  }
1443  } else {
1444  appBytesReceived_ += bytes;
1445  return ReadResult(bytes);
1446  }
1447 }
1448 
1450  VLOG(5) << "AsyncSSLSocket::handleWrite() this=" << this << ", fd=" << fd_
1451  << ", state=" << int(state_) << ", "
1452  << "sslState=" << sslState_ << ", events=" << eventFlags_;
1454  return AsyncSocket::handleWrite();
1455  }
1456 
1457  if (sslState_ == STATE_ACCEPTING) {
1458  assert(server_);
1459  handleAccept();
1460  return;
1461  }
1462 
1463  if (sslState_ == STATE_CONNECTING) {
1464  assert(!server_);
1465  handleConnect();
1466  return;
1467  }
1468 
1469  // Normal write
1471 }
1472 
1474  if (error == SSL_ERROR_WANT_READ) {
1475  // Even though we are attempting to write data, SSL_write() may
1476  // need to read data if renegotiation is being performed. We currently
1477  // don't support this and just fail the write.
1478  LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1479  << ", sslState=" << sslState_ << ", events=" << eventFlags_
1480  << "): "
1481  << "unsupported SSL renegotiation during write";
1482  return WriteResult(
1483  WRITE_ERROR,
1484  std::make_unique<SSLException>(SSLError::INVALID_RENEGOTIATION));
1485  } else {
1486  if (zero_return(error, rc)) {
1487  return WriteResult(0);
1488  }
1489  auto errError = ERR_get_error();
1490  VLOG(3) << "ERROR: AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1491  << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
1492  << "SSL error: " << error << ", errno: " << errno
1493  << ", func: " << ERR_func_error_string(errError)
1494  << ", reason: " << ERR_reason_error_string(errError);
1495  return WriteResult(
1496  WRITE_ERROR,
1497  std::make_unique<SSLException>(error, errError, rc, errno));
1498  }
1499 }
1500 
1502  const iovec* vec,
1503  uint32_t count,
1504  WriteFlags flags,
1505  uint32_t* countWritten,
1506  uint32_t* partialWritten) {
1507  if (sslState_ == STATE_UNENCRYPTED) {
1509  vec, count, flags, countWritten, partialWritten);
1510  }
1511  if (sslState_ != STATE_ESTABLISHED) {
1512  LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1513  << ", sslState=" << sslState_ << ", events=" << eventFlags_
1514  << "): "
1515  << "TODO: AsyncSSLSocket currently does not support calling "
1516  << "write() before the handshake has fully completed";
1517  return WriteResult(
1518  WRITE_ERROR, std::make_unique<SSLException>(SSLError::EARLY_WRITE));
1519  }
1520 
1521  // Declare a buffer used to hold small write requests. It could point to a
1522  // memory block either on stack or on heap. If it is on heap, we release it
1523  // manually when scope exits
1524  char* combinedBuf{nullptr};
1525  SCOPE_EXIT {
1526  // Note, always keep this check consistent with what we do below
1527  if (combinedBuf != nullptr && minWriteSize_ > MAX_STACK_BUF_SIZE) {
1528  delete[] combinedBuf;
1529  }
1530  };
1531 
1532  *countWritten = 0;
1533  *partialWritten = 0;
1534  ssize_t totalWritten = 0;
1535  size_t bytesStolenFromNextBuffer = 0;
1536  for (uint32_t i = 0; i < count; i++) {
1537  const iovec* v = vec + i;
1538  size_t offset = bytesStolenFromNextBuffer;
1539  bytesStolenFromNextBuffer = 0;
1540  size_t len = v->iov_len - offset;
1541  const void* buf;
1542  if (len == 0) {
1543  (*countWritten)++;
1544  continue;
1545  }
1546  buf = ((const char*)v->iov_base) + offset;
1547 
1548  ssize_t bytes;
1549  uint32_t buffersStolen = 0;
1550  auto sslWriteBuf = buf;
1551  if ((len < minWriteSize_) && ((i + 1) < count)) {
1552  // Combine this buffer with part or all of the next buffers in
1553  // order to avoid really small-grained calls to SSL_write().
1554  // Each call to SSL_write() produces a separate record in
1555  // the egress SSL stream, and we've found that some low-end
1556  // mobile clients can't handle receiving an HTTP response
1557  // header and the first part of the response body in two
1558  // separate SSL records (even if those two records are in
1559  // the same TCP packet).
1560 
1561  if (combinedBuf == nullptr) {
1562  if (minWriteSize_ > MAX_STACK_BUF_SIZE) {
1563  // Allocate the buffer on heap
1564  combinedBuf = new char[minWriteSize_];
1565  } else {
1566  // Allocate the buffer on stack
1567  combinedBuf = (char*)alloca(minWriteSize_);
1568  }
1569  }
1570  assert(combinedBuf != nullptr);
1571  sslWriteBuf = combinedBuf;
1572 
1573  memcpy(combinedBuf, buf, len);
1574  do {
1575  // INVARIANT: i + buffersStolen == complete chunks serialized
1576  uint32_t nextIndex = i + buffersStolen + 1;
1577  bytesStolenFromNextBuffer =
1578  std::min(vec[nextIndex].iov_len, minWriteSize_ - len);
1579  if (bytesStolenFromNextBuffer > 0) {
1580  assert(vec[nextIndex].iov_base != nullptr);
1581  ::memcpy(
1582  combinedBuf + len,
1583  vec[nextIndex].iov_base,
1584  bytesStolenFromNextBuffer);
1585  }
1586  len += bytesStolenFromNextBuffer;
1587  if (bytesStolenFromNextBuffer < vec[nextIndex].iov_len) {
1588  // couldn't steal the whole buffer
1589  break;
1590  } else {
1591  bytesStolenFromNextBuffer = 0;
1592  buffersStolen++;
1593  }
1594  } while ((i + buffersStolen + 1) < count && (len < minWriteSize_));
1595  }
1596 
1597  // Advance any empty buffers immediately after.
1598  if (bytesStolenFromNextBuffer == 0) {
1599  while ((i + buffersStolen + 1) < count &&
1600  vec[i + buffersStolen + 1].iov_len == 0) {
1601  buffersStolen++;
1602  }
1603  }
1604 
1606  isSet(flags, WriteFlags::CORK) || (i + buffersStolen + 1 < count);
1607  bytes = eorAwareSSLWrite(
1608  ssl_,
1609  sslWriteBuf,
1610  int(len),
1611  (isSet(flags, WriteFlags::EOR) && i + buffersStolen + 1 == count));
1612 
1613  if (bytes <= 0) {
1614  int error = SSL_get_error(ssl_.get(), int(bytes));
1615  if (error == SSL_ERROR_WANT_WRITE) {
1616  // The caller will register for write event if not already.
1617  *partialWritten = uint32_t(offset);
1618  return WriteResult(totalWritten);
1619  }
1620  auto writeResult = interpretSSLError(int(bytes), error);
1621  if (writeResult.writeReturn < 0) {
1622  return writeResult;
1623  } // else fall through to below to correctly record totalWritten
1624  }
1625 
1626  totalWritten += bytes;
1627 
1628  if (bytes == (ssize_t)len) {
1629  // The full iovec is written.
1630  (*countWritten) += 1 + buffersStolen;
1631  i += buffersStolen;
1632  // continue
1633  } else {
1634  bytes += offset; // adjust bytes to account for all of v
1635  while (bytes >= (ssize_t)v->iov_len) {
1636  // We combined this buf with part or all of the next one, and
1637  // we managed to write all of this buf but not all of the bytes
1638  // from the next one that we'd hoped to write.
1639  bytes -= v->iov_len;
1640  (*countWritten)++;
1641  v = &(vec[++i]);
1642  }
1643  *partialWritten = uint32_t(bytes);
1644  return WriteResult(totalWritten);
1645  }
1646  }
1647 
1648  return WriteResult(totalWritten);
1649 }
1650 
1652  const ssl::SSLUniquePtr& ssl,
1653  const void* buf,
1654  int n,
1655  bool eor) {
1656  if (eor && isEorTrackingEnabled()) {
1657  if (appEorByteNo_) {
1658  // cannot track for more than one app byte EOR
1659  CHECK(appEorByteNo_ == appBytesWritten_ + n);
1660  } else {
1662  }
1663 
1664  // 1. It is fine to keep updating minEorRawByteNo_.
1665  // 2. It is _min_ in the sense that SSL record will add some overhead.
1667  }
1668 
1669  n = sslWriteImpl(ssl.get(), buf, n);
1670  if (n > 0) {
1671  appBytesWritten_ += n;
1672  if (appEorByteNo_) {
1674  minEorRawByteNo_ = 0;
1675  }
1677  appEorByteNo_ = 0;
1678  } else {
1680  }
1681  }
1682  }
1683  return n;
1684 }
1685 
1686 void AsyncSSLSocket::sslInfoCallback(const SSL* ssl, int where, int ret) {
1687  AsyncSSLSocket* sslSocket = AsyncSSLSocket::getFromSSL(ssl);
1688  if (sslSocket->handshakeComplete_ && (where & SSL_CB_HANDSHAKE_START)) {
1689  sslSocket->renegotiateAttempted_ = true;
1690  }
1691  if (where & SSL_CB_READ_ALERT) {
1692  const char* type = SSL_alert_type_string(ret);
1693  if (type) {
1694  const char* desc = SSL_alert_desc_string(ret);
1695  sslSocket->alertsReceived_.emplace_back(
1696  *type, StringPiece(desc, std::strlen(desc)));
1697  }
1698  }
1699 }
1700 
1701 int AsyncSSLSocket::bioWrite(BIO* b, const char* in, int inl) {
1702  struct msghdr msg;
1703  struct iovec iov;
1704  AsyncSSLSocket* tsslSock;
1705 
1706  iov.iov_base = const_cast<char*>(in);
1707  iov.iov_len = size_t(inl);
1708  memset(&msg, 0, sizeof(msg));
1709  msg.msg_iov = &iov;
1710  msg.msg_iovlen = 1;
1711 
1712  auto appData = OpenSSLUtils::getBioAppData(b);
1713  CHECK(appData);
1714 
1715  tsslSock = reinterpret_cast<AsyncSSLSocket*>(appData);
1716  CHECK(tsslSock);
1717 
1719  if (tsslSock->isEorTrackingEnabled() && tsslSock->minEorRawByteNo_ &&
1720  tsslSock->minEorRawByteNo_ <= BIO_number_written(b) + inl) {
1721  flags |= WriteFlags::EOR;
1722  }
1723 
1724  if (tsslSock->corkCurrentWrite_) {
1725  flags |= WriteFlags::CORK;
1726  }
1727 
1728  int msg_flags = tsslSock->getSendMsgParamsCB()->getFlags(
1729  flags, false /*zeroCopyEnabled*/);
1730  msg.msg_controllen =
1731  tsslSock->getSendMsgParamsCB()->getAncillaryDataSize(flags);
1732  CHECK_GE(
1734  msg.msg_controllen);
1735  if (msg.msg_controllen != 0) {
1736  msg.msg_control = reinterpret_cast<char*>(alloca(msg.msg_controllen));
1737  tsslSock->getSendMsgParamsCB()->getAncillaryData(flags, msg.msg_control);
1738  }
1739 
1740  auto result = tsslSock->sendSocketMessage(
1741  OpenSSLUtils::getBioFd(b, nullptr), &msg, msg_flags);
1742  BIO_clear_retry_flags(b);
1743  if (!result.exception && result.writeReturn <= 0) {
1744  if (OpenSSLUtils::getBioShouldRetryWrite(int(result.writeReturn))) {
1745  BIO_set_retry_write(b);
1746  }
1747  }
1748  return int(result.writeReturn);
1749 }
1750 
1751 int AsyncSSLSocket::bioRead(BIO* b, char* out, int outl) {
1752  if (!out) {
1753  return 0;
1754  }
1755  BIO_clear_retry_flags(b);
1756 
1757  auto appData = OpenSSLUtils::getBioAppData(b);
1758  CHECK(appData);
1759  auto sslSock = reinterpret_cast<AsyncSSLSocket*>(appData);
1760 
1761  if (sslSock->preReceivedData_ && !sslSock->preReceivedData_->empty()) {
1762  VLOG(5) << "AsyncSSLSocket::bioRead() this=" << sslSock
1763  << ", reading pre-received data";
1764 
1765  Cursor cursor(sslSock->preReceivedData_.get());
1766  auto len = cursor.pullAtMost(out, outl);
1767 
1768  IOBufQueue queue;
1769  queue.append(std::move(sslSock->preReceivedData_));
1770  queue.trimStart(len);
1771  sslSock->preReceivedData_ = queue.move();
1772  return static_cast<int>(len);
1773  } else {
1774  auto result = int(recv(OpenSSLUtils::getBioFd(b, nullptr), out, outl, 0));
1775  if (result <= 0 && OpenSSLUtils::getBioShouldRetryWrite(result)) {
1776  BIO_set_retry_read(b);
1777  }
1778  return result;
1779  }
1780 }
1781 
1783  int preverifyOk,
1784  X509_STORE_CTX* x509Ctx) {
1785  SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(
1786  x509Ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
1788 
1789  VLOG(3) << "AsyncSSLSocket::sslVerifyCallback() this=" << self << ", "
1790  << "fd=" << self->fd_ << ", preverifyOk=" << preverifyOk;
1791  return (self->handshakeCallback_)
1792  ? self->handshakeCallback_->handshakeVer(self, preverifyOk, x509Ctx)
1793  : preverifyOk;
1794 }
1795 
1797  parseClientHello_ = true;
1798  clientHelloInfo_ = std::make_unique<ssl::ClientHelloInfo>();
1799 }
1800 
1802  SSL_set_msg_callback(ssl, nullptr);
1803  SSL_set_msg_callback_arg(ssl, nullptr);
1804  clientHelloInfo_->clientHelloBuf_.clear();
1805 }
1806 
1808  int written,
1809  int /* version */,
1810  int contentType,
1811  const void* buf,
1812  size_t len,
1813  SSL* ssl,
1814  void* arg) {
1815  AsyncSSLSocket* sock = static_cast<AsyncSSLSocket*>(arg);
1816  if (written != 0) {
1817  sock->resetClientHelloParsing(ssl);
1818  return;
1819  }
1820  if (contentType != SSL3_RT_HANDSHAKE) {
1821  return;
1822  }
1823  if (len == 0) {
1824  return;
1825  }
1826 
1827  auto& clientHelloBuf = sock->clientHelloInfo_->clientHelloBuf_;
1828  clientHelloBuf.append(IOBuf::wrapBuffer(buf, len));
1829  try {
1830  Cursor cursor(clientHelloBuf.front());
1831  if (cursor.read<uint8_t>() != SSL3_MT_CLIENT_HELLO) {
1832  sock->resetClientHelloParsing(ssl);
1833  return;
1834  }
1835 
1836  if (cursor.totalLength() < 3) {
1837  clientHelloBuf.trimEnd(len);
1838  clientHelloBuf.append(IOBuf::copyBuffer(buf, len));
1839  return;
1840  }
1841 
1842  uint32_t messageLength = cursor.read<uint8_t>();
1843  messageLength <<= 8;
1844  messageLength |= cursor.read<uint8_t>();
1845  messageLength <<= 8;
1846  messageLength |= cursor.read<uint8_t>();
1847  if (cursor.totalLength() < messageLength) {
1848  clientHelloBuf.trimEnd(len);
1849  clientHelloBuf.append(IOBuf::copyBuffer(buf, len));
1850  return;
1851  }
1852 
1853  sock->clientHelloInfo_->clientHelloMajorVersion_ = cursor.read<uint8_t>();
1854  sock->clientHelloInfo_->clientHelloMinorVersion_ = cursor.read<uint8_t>();
1855 
1856  cursor.skip(4); // gmt_unix_time
1857  cursor.skip(28); // random_bytes
1858 
1859  cursor.skip(cursor.read<uint8_t>()); // session_id
1860 
1861  uint16_t cipherSuitesLength = cursor.readBE<uint16_t>();
1862  for (int i = 0; i < cipherSuitesLength; i += 2) {
1863  sock->clientHelloInfo_->clientHelloCipherSuites_.push_back(
1864  cursor.readBE<uint16_t>());
1865  }
1866 
1867  uint8_t compressionMethodsLength = cursor.read<uint8_t>();
1868  for (int i = 0; i < compressionMethodsLength; ++i) {
1869  sock->clientHelloInfo_->clientHelloCompressionMethods_.push_back(
1870  cursor.readBE<uint8_t>());
1871  }
1872 
1873  if (cursor.totalLength() > 0) {
1874  uint16_t extensionsLength = cursor.readBE<uint16_t>();
1875  while (extensionsLength) {
1876  ssl::TLSExtension extensionType =
1877  static_cast<ssl::TLSExtension>(cursor.readBE<uint16_t>());
1878  sock->clientHelloInfo_->clientHelloExtensions_.push_back(extensionType);
1879  extensionsLength -= 2;
1880  uint16_t extensionDataLength = cursor.readBE<uint16_t>();
1881  extensionsLength -= 2;
1882  extensionsLength -= extensionDataLength;
1883 
1884  if (extensionType == ssl::TLSExtension::SIGNATURE_ALGORITHMS) {
1885  cursor.skip(2);
1886  extensionDataLength -= 2;
1887  while (extensionDataLength) {
1888  ssl::HashAlgorithm hashAlg =
1889  static_cast<ssl::HashAlgorithm>(cursor.readBE<uint8_t>());
1890  ssl::SignatureAlgorithm sigAlg =
1891  static_cast<ssl::SignatureAlgorithm>(cursor.readBE<uint8_t>());
1892  extensionDataLength -= 2;
1893  sock->clientHelloInfo_->clientHelloSigAlgs_.emplace_back(
1894  hashAlg, sigAlg);
1895  }
1896  } else if (extensionType == ssl::TLSExtension::SUPPORTED_VERSIONS) {
1897  cursor.skip(1);
1898  extensionDataLength -= 1;
1899  while (extensionDataLength) {
1900  sock->clientHelloInfo_->clientHelloSupportedVersions_.push_back(
1901  cursor.readBE<uint16_t>());
1902  extensionDataLength -= 2;
1903  }
1904  } else {
1905  cursor.skip(extensionDataLength);
1906  }
1907  }
1908  }
1909  } catch (std::out_of_range&) {
1910  // we'll use what we found and cleanup below.
1911  VLOG(4) << "AsyncSSLSocket::clientHelloParsingCallback(): "
1912  << "buffer finished unexpectedly."
1913  << " AsyncSSLSocket socket=" << sock;
1914  }
1915 
1916  sock->resetClientHelloParsing(ssl);
1917 }
1918 
1920  std::string& clientCiphers,
1921  bool convertToString) const {
1922  std::string ciphers;
1923 
1924  if (parseClientHello_ == false ||
1925  clientHelloInfo_->clientHelloCipherSuites_.empty()) {
1926  clientCiphers = "";
1927  return;
1928  }
1929 
1930  bool first = true;
1931  for (auto originalCipherCode : clientHelloInfo_->clientHelloCipherSuites_) {
1932  if (first) {
1933  first = false;
1934  } else {
1935  ciphers += ":";
1936  }
1937 
1938  bool nameFound = convertToString;
1939 
1940  if (convertToString) {
1941  const auto& name = OpenSSLUtils::getCipherName(originalCipherCode);
1942  if (name.empty()) {
1943  nameFound = false;
1944  } else {
1945  ciphers += name;
1946  }
1947  }
1948 
1949  if (!nameFound) {
1951  std::array<uint8_t, 2>{
1952  {static_cast<uint8_t>((originalCipherCode >> 8) & 0xffL),
1953  static_cast<uint8_t>(originalCipherCode & 0x00ffL)}},
1954  ciphers,
1955  /* append to ciphers = */ true);
1956  }
1957  }
1958 
1959  clientCiphers = std::move(ciphers);
1960 }
1961 
1963  if (!parseClientHello_) {
1964  return "";
1965  }
1966  return folly::join(":", clientHelloInfo_->clientHelloCompressionMethods_);
1967 }
1968 
1970  if (!parseClientHello_) {
1971  return "";
1972  }
1973  return folly::join(":", clientHelloInfo_->clientHelloExtensions_);
1974 }
1975 
1977  if (!parseClientHello_) {
1978  return "";
1979  }
1980 
1981  std::string sigAlgs;
1982  sigAlgs.reserve(clientHelloInfo_->clientHelloSigAlgs_.size() * 4);
1983  for (size_t i = 0; i < clientHelloInfo_->clientHelloSigAlgs_.size(); i++) {
1984  if (i) {
1985  sigAlgs.push_back(':');
1986  }
1987  sigAlgs.append(
1988  folly::to<std::string>(clientHelloInfo_->clientHelloSigAlgs_[i].first));
1989  sigAlgs.push_back(',');
1990  sigAlgs.append(folly::to<std::string>(
1991  clientHelloInfo_->clientHelloSigAlgs_[i].second));
1992  }
1993 
1994  return sigAlgs;
1995 }
1996 
1998  if (!parseClientHello_) {
1999  return "";
2000  }
2001  return folly::join(":", clientHelloInfo_->clientHelloSupportedVersions_);
2002 }
2003 
2005  std::string ret;
2006 
2007  for (const auto& alert : alertsReceived_) {
2008  if (!ret.empty()) {
2009  ret.append(",");
2010  }
2011  ret.append(folly::to<std::string>(alert.first, ": ", alert.second));
2012  }
2013 
2014  return ret;
2015 }
2016 
2019 }
2020 
2022  return sslVerificationAlert_;
2023 }
2024 
2026  char ciphersBuffer[1024];
2027  ciphersBuffer[0] = '\0';
2028  SSL_get_shared_ciphers(ssl_.get(), ciphersBuffer, sizeof(ciphersBuffer) - 1);
2029  sharedCiphers = ciphersBuffer;
2030 }
2031 
2033  serverCiphers = SSL_get_cipher_list(ssl_.get(), 0);
2034  int i = 1;
2035  const char* cipher;
2036  while ((cipher = SSL_get_cipher_list(ssl_.get(), i)) != nullptr) {
2037  serverCiphers.append(":");
2038  serverCiphers.append(cipher);
2039  i++;
2040  }
2041 }
2042 
2043 } // namespace folly
void applyVerificationOptions(const ssl::SSLUniquePtr &ssl)
static std::string getCommonName(X509 *x509)
bool good() const override
chrono
Definition: CMakeCache.txt:563
size_t getRawBytesReceived() const override
void checkForImmediateRead() noexceptoverride
static SSL_CTX * getSSLInitialCtx(SSL *ssl)
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
Definition: IOBufQueue.cpp:143
ReadResult performRead(void **buf, size_t *buflen, size_t *offset) override
void invokeHandshakeErr(const AsyncSocketException &ex)
flags
Definition: http_parser.h:127
bool connecting() const override
Definition: AsyncSocket.h:567
static bool setCustomBioReadMethod(BIO_METHOD *bioMeth, int(*meth)(BIO *, char *, int))
virtual int getVerificationMode()
Definition: SSLContext.cpp:185
std::unique_ptr< ReadCallback > asyncOperationFinishCallback_
std::string withAddr(const std::string &s)
std::unique_ptr< X509, X509Deleter > X509UniquePtr
void handleRead() noexceptoverride
char b
WriteResult interpretSSLError(int rc, int error)
bool connecting() const override
static std::unique_ptr< IOBuf > wrapBuffer(const void *buf, std::size_t capacity)
Definition: IOBuf.cpp:353
static UniquePtr newReader(Args &&...args)
Definition: AsyncPipe.h:43
static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX *ctx)
static int bioRead(BIO *b, char *out, int outl)
static const char * getSSLServerNameFromSSL(SSL *ssl)
std::string sformat(StringPiece fmt, Args &&...args)
Definition: Format.h:280
virtual WriteResult performWrite(const iovec *vec, uint32_t count, WriteFlags flags, uint32_t *countWritten, uint32_t *partialWritten)
folly::SSLContext::SSLVerifyPeerEnum verifyPeer_
PskType type
std::unique_ptr< const AsyncTransportCertificate > peerCertData_
Definition: AsyncSocket.h:1282
void setEorTracking(bool track) override
void connect(ConnectCallback *callback, const folly::SocketAddress &address, int timeout=0, const OptionMap &options=emptyOptionMap, const folly::SocketAddress &bindAddr=anyAddress()) noexceptoverride
const char * getSSLCertSigAlgName() const
size_t getRawBytesWritten() const override
bool willBlock(int ret, int *sslErrorOut, unsigned long *errErrorOut) noexcept
std::string getSSLClientComprMethods() const
std::string getSSLClientSupportedVersions() const
const AsyncTransportCertificate * getPeerCertificate() const override
const X509 * getSelfCert() const override
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
ssl::SSLUniquePtr ssl_
static void * getBioAppData(BIO *b)
virtual void sslAccept(HandshakeCB *callback, std::chrono::milliseconds timeout=std::chrono::milliseconds::zero(), const folly::SSLContext::SSLVerifyPeerEnum &verifyPeer=folly::SSLContext::SSLVerifyPeerEnum::USE_CTX)
virtual void handleConnect() noexcept
WriteResult performWrite(const iovec *vec, uint32_t count, WriteFlags flags, uint32_t *countWritten, uint32_t *partialWritten) override
STL namespace.
SpinLockGuardImpl< SpinLock > SpinLockGuard
Definition: SpinLock.h:79
virtual bool isBufferMovable() noexcept
virtual void sslConn(HandshakeCB *callback, std::chrono::milliseconds timeout=std::chrono::milliseconds::zero(), const folly::SSLContext::SSLVerifyPeerEnum &verifyPeer=folly::SSLContext::SSLVerifyPeerEnum::USE_CTX)
std::chrono::milliseconds handshakeConnectTimeout_
SSL_SESSION * sslSession_
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
const char * getSSLServerName() const
std::unique_ptr< folly::IOBuf > move()
Definition: IOBufQueue.h:459
void shutdownWrite() override
std::string sslVerificationAlert_
size_t pullAtMost(void *buf, size_t len)
Definition: Cursor.h:407
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
EventBase * eventBase_
The EventBase.
Definition: AsyncSocket.h:1240
requires E e noexcept(noexcept(s.error(std::move(e))))
void closeNow() override
bool updateEventRegistration()
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
Definition: error.h:48
std::shared_ptr< FizzServerContext > ctx_
CipherSuite cipher
std::chrono::milliseconds connectTimeout_
Definition: AsyncSocket.h:1263
bool isSet(WriteFlags a, WriteFlags b)
virtual void connect(ConnectCallback *callback, const folly::SocketAddress &address, int timeout=0, const OptionMap &options=emptyOptionMap, const folly::SocketAddress &bindAddr=anyAddress()) noexcept
bool needsPeerVerification() const
std::shared_ptr< folly::SSLContext > ctx_
void scheduleConnectTimeout() override
void setReadCB(ReadCallback *callback) override
virtual void handleRead() noexcept
void handleWrite() noexceptoverride
static void setSSLInitialCtx(SSL *ssl, SSL_CTX *ctx)
const char * name
Definition: http_parser.c:437
std::chrono::milliseconds totalConnectTimeout_
std::map< OptionKey, int > OptionMap
Definition: AsyncSocket.h:376
SSL_CTX * getSSLCtx() const
Definition: SSLContext.h:503
static void setBioFd(BIO *b, int fd, int flags)
LogLevel min
Definition: LogLevel.cpp:30
size_t appBytesReceived_
Num of bytes received from socket.
Definition: AsyncSocket.h:1253
void invokeConnectSuccess() override
virtual void getReadBuffer(void **bufReturn, size_t *lenReturn)=0
void fail()
AsyncSSLSocket::UniquePtr sslSocket_
uint16_t eventFlags_
EventBase::HandlerFlags settings.
Definition: AsyncSocket.h:1228
void handleReturnFromSSLAccept(int ret)
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
std::string getSSLCertVerificationAlert() const
void setEorTracking(bool track) override
Definition: AsyncSocket.h:563
bool good() const override
static void clientHelloParsingCallback(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
std::unique_ptr< const AsyncTransportCertificate > selfCertData_
Definition: AsyncSocket.h:1284
static int getBioFd(BIO *b, int *fd)
void invokeConnectErr(const AsyncSocketException &ex) override
void timeoutExpired() noexcept
static bool setCustomBioWriteMethod(BIO_METHOD *bioMeth, int(*meth)(BIO *, const char *, int))
virtual int getFd() const
Definition: AsyncSocket.h:335
Definition: Traits.h:588
bool isEorTrackingEnabled() const override
Definition: AsyncSocket.h:559
void getSSLClientCiphers(std::string &clientCiphers, bool convertToString=true) const
static BioMethodUniquePtr newSocketBioMethod()
void setBufferMovableEnabled(bool enabled)
virtual ReadResult performRead(void **buf, size_t *buflen, size_t *offset)
virtual bool getSSLSessionReused() const
virtual void handleWrite() noexcept
void getSSLSharedCiphers(std::string &sharedCiphers) const
void dcheckIsInEventBaseThread() const
Definition: EventBase.h:520
const char * SSL_SESSION_get0_hostname(const SSL_SESSION *s)
Definition: OpenSSL.cpp:195
virtual void handshakeSuc(AsyncSSLSocket *sock) noexcept=0
void prepareReadBuffer(void **buf, size_t *buflen) override
virtual void scheduleConnectTimeout()
int * count
static int getBioShouldRetryWrite(int ret)
void handleConnect() noexceptoverride
virtual void handshakeErr(AsyncSSLSocket *sock, const AsyncSocketException &ex) noexcept=0
void setSSLCertVerificationAlert(std::string alert)
ReadCallback * readCallback_
ReadCallback.
Definition: AsyncSocket.h:1249
virtual bool getSelectedNextProtocolNoThrow(const unsigned char **protoName, unsigned *protoLen) const
std::vector< std::pair< char, StringPiece > > alertsReceived_
std::unique_ptr< ssl::ClientHelloInfo > clientHelloInfo_
std::string getSSLClientExts() const
void setReadCB(ReadCallback *callback) override
void getSSLServerCiphers(std::string &serverCiphers) const
AsyncSSLSocket(const std::shared_ptr< folly::SSLContext > &ctx, EventBase *evb, bool deferSecurityNegotiation=false)
std::chrono::steady_clock::time_point handshakeEndTime_
std::string getSSLClientSigAlgs() const
const char * string
Definition: Conv.cpp:212
SSL_SESSION * getSSLSession()
StateEnum state_
StateEnum describing current state.
Definition: AsyncSocket.h:1226
int bind(NetworkSocket s, const sockaddr *name, socklen_t namelen)
Definition: NetOps.cpp:76
void close() override
const
Definition: upload.py:398
void resetClientHelloParsing(SSL *ssl)
virtual void invokeConnectSuccess()
EventBase * getEventBase() const override
Definition: AsyncSocket.h:328
static void setBioAppData(BIO *b, void *ptr)
void trimStart(size_t amount)
Definition: IOBufQueue.cpp:255
int fd_
The socket file descriptor.
Definition: AsyncSocket.h:1229
void setSSLSession(SSL_SESSION *session, bool takeOwnership=false)
void join(const Delim &delimiter, Iterator begin, Iterator end, String &output)
Definition: String-inl.h:498
HandshakeCB * handshakeCallback_
std::string getSSLAlertsReceived() const
bool isScheduled() const
folly::Function< void()> callback_
void failHandshake(const char *fn, const AsyncSocketException &ex)
int eorAwareSSLWrite(const ssl::SSLUniquePtr &ssl, const void *buf, int n, bool eor)
void invalidState(HandshakeCB *callback)
std::chrono::steady_clock::time_point handshakeStartTime_
virtual void checkForImmediateRead() noexcept
bool scheduleTimeout(TimeoutManager::timeout_type timeout)
ssize_t recv(NetworkSocket s, void *buf, size_t len, int flags)
Definition: NetOps.cpp:180
std::string getApplicationProtocol() const noexceptoverride
virtual void handleInitialReadWrite() noexcept
const SSL * getSSL() const
const AsyncTransportCertificate * getSelfCertificate() const override
Range< const char * > StringPiece
bool hexlify(const InputString &input, OutputString &output, bool append_output)
Definition: String-inl.h:596
static int bioWrite(BIO *b, const char *in, int inl)
static std::unique_ptr< IOBuf > copyBuffer(const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
Definition: IOBuf.h:1587
virtual const char * getNegotiatedCipherName() const
void shutdownWriteNow() override
static void sslInfoCallback(const SSL *ssl, int type, int val)
size_t appBytesWritten_
Num of bytes written to socket.
Definition: AsyncSocket.h:1254
static AsyncSSLSocket * getFromSSL(const SSL *ssl)
static const std::string & getCipherName(uint16_t cipherCode)
std::unique_ptr< AsyncSocket, Destructor > UniquePtr
Definition: AsyncSocket.h:83
static int getSSLExDataIndex()
virtual void invokeConnectErr(const AsyncSocketException &ex)
const char * getSSLServerNameNoThrow() const
ConnectCallback * connectCallback_
ConnectCallback.
Definition: AsyncSocket.h:1245
virtual int sslWriteImpl(SSL *ssl, const void *buf, int n)
void closeNow() override
virtual void getSelectedNextProtocol(const unsigned char **protoName, unsigned *protoLen) const
void handleAccept() noexcept
std::unique_ptr< SSL, SSLDeleter > SSLUniquePtr
constexpr detail::First first
Definition: Base-inl.h:2553
def next(obj)
Definition: ast.py:58