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