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