5ecde2f79221f03ab685265670ef3b470c955336
[folly.git] / folly / io / async / AsyncSSLSocket.cpp
1 /*
2  * Copyright 2014 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
21 #include <boost/noncopyable.hpp>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <netinet/in.h>
25 #include <netinet/tcp.h>
26 #include <openssl/err.h>
27 #include <openssl/asn1.h>
28 #include <openssl/ssl.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <unistd.h>
32 #include <chrono>
33
34 #include <folly/Bits.h>
35 #include <folly/SocketAddress.h>
36 #include <folly/SpinLock.h>
37 #include <folly/io/IOBuf.h>
38 #include <folly/io/Cursor.h>
39
40 using folly::SocketAddress;
41 using folly::SSLContext;
42 using std::string;
43 using std::shared_ptr;
44
45 using folly::Endian;
46 using folly::IOBuf;
47 using folly::SpinLock;
48 using folly::SpinLockGuard;
49 using folly::io::Cursor;
50 using std::unique_ptr;
51 using std::bind;
52
53 namespace {
54 using folly::AsyncSocket;
55 using folly::AsyncSocketException;
56 using folly::AsyncSSLSocket;
57 using folly::Optional;
58
59 /** Try to avoid calling SSL_write() for buffers smaller than this: */
60 size_t MIN_WRITE_SIZE = 1500;
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 // Numbers chosen as to not collide with functions in ssl.h
68 const uint8_t TASYNCSSLSOCKET_F_PERFORM_READ = 90;
69 const uint8_t TASYNCSSLSOCKET_F_PERFORM_WRITE = 91;
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   virtual ~AsyncSSLSocketConnector() {
87   }
88
89  public:
90   AsyncSSLSocketConnector(AsyncSSLSocket *sslSocket,
91                            AsyncSocket::ConnectCallback *callback,
92                            int timeout) :
93       sslSocket_(sslSocket),
94       callback_(callback),
95       timeout_(timeout),
96       startTime_(std::chrono::duration_cast<std::chrono::milliseconds>(
97                    std::chrono::steady_clock::now().time_since_epoch()).count()) {
98   }
99
100   virtual void connectSuccess() noexcept {
101     VLOG(7) << "client socket connected";
102
103     int64_t timeoutLeft = 0;
104     if (timeout_ > 0) {
105       auto curTime = std::chrono::duration_cast<std::chrono::milliseconds>(
106         std::chrono::steady_clock::now().time_since_epoch()).count();
107
108       timeoutLeft = timeout_ - (curTime - startTime_);
109       if (timeoutLeft <= 0) {
110         AsyncSocketException ex(AsyncSocketException::TIMED_OUT,
111                                 "SSL connect timed out");
112         fail(ex);
113         delete this;
114         return;
115       }
116     }
117     sslSocket_->sslConn(this, timeoutLeft);
118   }
119
120   virtual void connectErr(const AsyncSocketException& ex) noexcept {
121     LOG(ERROR) << "TCP connect failed: " <<  ex.what();
122     fail(ex);
123     delete this;
124   }
125
126   virtual void handshakeSuc(AsyncSSLSocket *sock) noexcept {
127     VLOG(7) << "client handshake success";
128     if (callback_) {
129       callback_->connectSuccess();
130     }
131     delete this;
132   }
133
134   virtual void handshakeErr(AsyncSSLSocket *socket,
135                               const AsyncSocketException& ex) noexcept {
136     LOG(ERROR) << "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 // XXX: implement an equivalent to corking for platforms with TCP_NOPUSH?
159 #ifdef TCP_CORK // Linux-only
160 /**
161  * Utility class that corks a TCP socket upon construction or uncorks
162  * the socket upon destruction
163  */
164 class CorkGuard : private boost::noncopyable {
165  public:
166   CorkGuard(int fd, bool multipleWrites, bool haveMore, bool* corked):
167     fd_(fd), haveMore_(haveMore), corked_(corked) {
168     if (*corked_) {
169       // socket is already corked; nothing to do
170       return;
171     }
172     if (multipleWrites || haveMore) {
173       // We are performing multiple writes in this performWrite() call,
174       // and/or there are more calls to performWrite() that will be invoked
175       // later, so enable corking
176       int flag = 1;
177       setsockopt(fd_, IPPROTO_TCP, TCP_CORK, &flag, sizeof(flag));
178       *corked_ = true;
179     }
180   }
181
182   ~CorkGuard() {
183     if (haveMore_) {
184       // more data to come; don't uncork yet
185       return;
186     }
187     if (!*corked_) {
188       // socket isn't corked; nothing to do
189       return;
190     }
191
192     int flag = 0;
193     setsockopt(fd_, IPPROTO_TCP, TCP_CORK, &flag, sizeof(flag));
194     *corked_ = false;
195   }
196
197  private:
198   int fd_;
199   bool haveMore_;
200   bool* corked_;
201 };
202 #else
203 class CorkGuard : private boost::noncopyable {
204  public:
205   CorkGuard(int, bool, bool, bool*) {}
206 };
207 #endif
208
209 void setup_SSL_CTX(SSL_CTX *ctx) {
210 #ifdef SSL_MODE_RELEASE_BUFFERS
211   SSL_CTX_set_mode(ctx,
212                    SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
213                    SSL_MODE_ENABLE_PARTIAL_WRITE
214                    | SSL_MODE_RELEASE_BUFFERS
215                    );
216 #else
217   SSL_CTX_set_mode(ctx,
218                    SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
219                    SSL_MODE_ENABLE_PARTIAL_WRITE
220                    );
221 #endif
222 }
223
224 BIO_METHOD eorAwareBioMethod;
225
226 __attribute__((__constructor__))
227 void initEorBioMethod(void) {
228   memcpy(&eorAwareBioMethod, BIO_s_socket(), sizeof(eorAwareBioMethod));
229   // override the bwrite method for MSG_EOR support
230   eorAwareBioMethod.bwrite = AsyncSSLSocket::eorAwareBioWrite;
231
232   // Note that the eorAwareBioMethod.type and eorAwareBioMethod.name are not
233   // set here. openssl code seems to be checking ".type == BIO_TYPE_SOCKET" and
234   // then have specific handlings. The eorAwareBioWrite should be compatible
235   // with the one in openssl.
236 }
237
238 } // anonymous namespace
239
240 namespace folly {
241
242 SSLException::SSLException(int sslError, int errno_copy):
243     AsyncSocketException(
244       AsyncSocketException::SSL_ERROR,
245       ERR_error_string(sslError, msg_),
246       sslError == SSL_ERROR_SYSCALL ? errno_copy : 0), error_(sslError) {}
247
248 /**
249  * Create a client AsyncSSLSocket
250  */
251 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext> &ctx,
252                                  EventBase* evb) :
253     AsyncSocket(evb),
254     ctx_(ctx),
255     handshakeTimeout_(this, evb) {
256   setup_SSL_CTX(ctx_->getSSLCtx());
257 }
258
259 /**
260  * Create a server/client AsyncSSLSocket
261  */
262 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext>& ctx,
263                                  EventBase* evb, int fd, bool server) :
264     AsyncSocket(evb, fd),
265     server_(server),
266     ctx_(ctx),
267     handshakeTimeout_(this, evb) {
268   setup_SSL_CTX(ctx_->getSSLCtx());
269   if (server) {
270     SSL_CTX_set_info_callback(ctx_->getSSLCtx(),
271                               AsyncSSLSocket::sslInfoCallback);
272   }
273 }
274
275 #if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
276 /**
277  * Create a client AsyncSSLSocket and allow tlsext_hostname
278  * to be sent in Client Hello.
279  */
280 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext> &ctx,
281                                  EventBase* evb,
282                                  const std::string& serverName) :
283     AsyncSocket(evb),
284     ctx_(ctx),
285     handshakeTimeout_(this, evb),
286     tlsextHostname_(serverName) {
287   setup_SSL_CTX(ctx_->getSSLCtx());
288 }
289
290 /**
291  * Create a client AsyncSSLSocket from an already connected fd
292  * and allow tlsext_hostname to be sent in Client Hello.
293  */
294 AsyncSSLSocket::AsyncSSLSocket(const shared_ptr<SSLContext>& ctx,
295                                  EventBase* evb, int fd,
296                                  const std::string& serverName) :
297     AsyncSocket(evb, fd),
298     ctx_(ctx),
299     handshakeTimeout_(this, evb),
300     tlsextHostname_(serverName) {
301   setup_SSL_CTX(ctx_->getSSLCtx());
302 }
303 #endif
304
305 AsyncSSLSocket::~AsyncSSLSocket() {
306   VLOG(3) << "actual destruction of AsyncSSLSocket(this=" << this
307           << ", evb=" << eventBase_ << ", fd=" << fd_
308           << ", state=" << int(state_) << ", sslState="
309           << sslState_ << ", events=" << eventFlags_ << ")";
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   if (handshakeCallback_) {
338     AsyncSocketException ex(AsyncSocketException::END_OF_FILE,
339                            "SSL connection closed locally");
340     HandshakeCB* callback = handshakeCallback_;
341     handshakeCallback_ = nullptr;
342     callback->handshakeErr(this, ex);
343   }
344
345   if (ssl_ != nullptr) {
346     SSL_free(ssl_);
347     ssl_ = nullptr;
348   }
349
350   // Close the socket.
351   AsyncSocket::closeNow();
352 }
353
354 void AsyncSSLSocket::shutdownWrite() {
355   // SSL sockets do not support half-shutdown, so just perform a full shutdown.
356   //
357   // (Performing a full shutdown here is more desirable than doing nothing at
358   // all.  The purpose of shutdownWrite() is normally to notify the other end
359   // of the connection that no more data will be sent.  If we do nothing, the
360   // other end will never know that no more data is coming, and this may result
361   // in protocol deadlock.)
362   close();
363 }
364
365 void AsyncSSLSocket::shutdownWriteNow() {
366   closeNow();
367 }
368
369 bool AsyncSSLSocket::good() const {
370   return (AsyncSocket::good() &&
371           (sslState_ == STATE_ACCEPTING || sslState_ == STATE_CONNECTING ||
372            sslState_ == STATE_ESTABLISHED));
373 }
374
375 // The TAsyncTransport definition of 'good' states that the transport is
376 // ready to perform reads and writes, so sslState_ == UNINIT must report !good.
377 // connecting can be true when the sslState_ == UNINIT because the AsyncSocket
378 // is connected but we haven't initiated the call to SSL_connect.
379 bool AsyncSSLSocket::connecting() const {
380   return (!server_ &&
381           (AsyncSocket::connecting() ||
382            (AsyncSocket::good() && (sslState_ == STATE_UNINIT ||
383                                      sslState_ == STATE_CONNECTING))));
384 }
385
386 bool AsyncSSLSocket::isEorTrackingEnabled() const {
387   const BIO *wb = SSL_get_wbio(ssl_);
388   return wb && wb->method == &eorAwareBioMethod;
389 }
390
391 void AsyncSSLSocket::setEorTracking(bool track) {
392   BIO *wb = SSL_get_wbio(ssl_);
393   if (!wb) {
394     throw AsyncSocketException(AsyncSocketException::INVALID_STATE,
395                               "setting EOR tracking without an initialized "
396                               "BIO");
397   }
398
399   if (track) {
400     if (wb->method != &eorAwareBioMethod) {
401       // only do this if we didn't
402       wb->method = &eorAwareBioMethod;
403       BIO_set_app_data(wb, this);
404       appEorByteNo_ = 0;
405       minEorRawByteNo_ = 0;
406     }
407   } else if (wb->method == &eorAwareBioMethod) {
408     wb->method = BIO_s_socket();
409     BIO_set_app_data(wb, nullptr);
410     appEorByteNo_ = 0;
411     minEorRawByteNo_ = 0;
412   } else {
413     CHECK(wb->method == BIO_s_socket());
414   }
415 }
416
417 size_t AsyncSSLSocket::getRawBytesWritten() const {
418   BIO *b;
419   if (!ssl_ || !(b = SSL_get_wbio(ssl_))) {
420     return 0;
421   }
422
423   return BIO_number_written(b);
424 }
425
426 size_t AsyncSSLSocket::getRawBytesReceived() const {
427   BIO *b;
428   if (!ssl_ || !(b = SSL_get_rbio(ssl_))) {
429     return 0;
430   }
431
432   return BIO_number_read(b);
433 }
434
435
436 void AsyncSSLSocket::invalidState(HandshakeCB* callback) {
437   LOG(ERROR) << "AsyncSSLSocket(this=" << this << ", fd=" << fd_
438              << ", state=" << int(state_) << ", sslState=" << sslState_ << ", "
439              << "events=" << eventFlags_ << ", server=" << short(server_) << "): "
440              << "sslAccept/Connect() called in invalid "
441              << "state, handshake callback " << handshakeCallback_ << ", new callback "
442              << callback;
443   assert(!handshakeTimeout_.isScheduled());
444   sslState_ = STATE_ERROR;
445
446   AsyncSocketException ex(AsyncSocketException::INVALID_STATE,
447                          "sslAccept() called with socket in invalid state");
448
449   if (callback) {
450     callback->handshakeErr(this, ex);
451   }
452
453   // Check the socket state not the ssl state here.
454   if (state_ != StateEnum::CLOSED || state_ != StateEnum::ERROR) {
455     failHandshake(__func__, ex);
456   }
457 }
458
459 void AsyncSSLSocket::sslAccept(HandshakeCB* callback, uint32_t timeout,
460       const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
461   DestructorGuard dg(this);
462   assert(eventBase_->isInEventBaseThread());
463   verifyPeer_ = verifyPeer;
464
465   // Make sure we're in the uninitialized state
466   if (!server_ || sslState_ != STATE_UNINIT || handshakeCallback_ != nullptr) {
467     return invalidState(callback);
468   }
469
470   sslState_ = STATE_ACCEPTING;
471   handshakeCallback_ = callback;
472
473   if (timeout > 0) {
474     handshakeTimeout_.scheduleTimeout(timeout);
475   }
476
477   /* register for a read operation (waiting for CLIENT HELLO) */
478   updateEventRegistration(EventHandler::READ, EventHandler::WRITE);
479 }
480
481 #if OPENSSL_VERSION_NUMBER >= 0x009080bfL
482 void AsyncSSLSocket::attachSSLContext(
483   const std::shared_ptr<SSLContext>& ctx) {
484
485   // Check to ensure we are in client mode. Changing a server's ssl
486   // context doesn't make sense since clients of that server would likely
487   // become confused when the server's context changes.
488   DCHECK(!server_);
489   DCHECK(!ctx_);
490   DCHECK(ctx);
491   DCHECK(ctx->getSSLCtx());
492   ctx_ = ctx;
493
494   // In order to call attachSSLContext, detachSSLContext must have been
495   // previously called which sets the socket's context to the dummy
496   // context. Thus we must acquire this lock.
497   SpinLockGuard guard(dummyCtxLock);
498   SSL_set_SSL_CTX(ssl_, ctx->getSSLCtx());
499 }
500
501 void AsyncSSLSocket::detachSSLContext() {
502   DCHECK(ctx_);
503   ctx_.reset();
504   // We aren't using the initial_ctx for now, and it can introduce race
505   // conditions in the destructor of the SSL object.
506 #ifndef OPENSSL_NO_TLSEXT
507   if (ssl_->initial_ctx) {
508     SSL_CTX_free(ssl_->initial_ctx);
509     ssl_->initial_ctx = nullptr;
510   }
511 #endif
512   SpinLockGuard guard(dummyCtxLock);
513   if (nullptr == dummyCtx) {
514     // We need to lazily initialize the dummy context so we don't
515     // accidentally override any programmatic settings to openssl
516     dummyCtx = new SSLContext;
517   }
518   // We must remove this socket's references to its context right now
519   // since this socket could get passed to any thread. If the context has
520   // had its locking disabled, just doing a set in attachSSLContext()
521   // would not be thread safe.
522   SSL_set_SSL_CTX(ssl_, dummyCtx->getSSLCtx());
523 }
524 #endif
525
526 #if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
527 void AsyncSSLSocket::switchServerSSLContext(
528   const std::shared_ptr<SSLContext>& handshakeCtx) {
529   CHECK(server_);
530   if (sslState_ != STATE_ACCEPTING) {
531     // We log it here and allow the switch.
532     // It should not affect our re-negotiation support (which
533     // is not supported now).
534     VLOG(6) << "fd=" << getFd()
535             << " renegotation detected when switching SSL_CTX";
536   }
537
538   setup_SSL_CTX(handshakeCtx->getSSLCtx());
539   SSL_CTX_set_info_callback(handshakeCtx->getSSLCtx(),
540                             AsyncSSLSocket::sslInfoCallback);
541   handshakeCtx_ = handshakeCtx;
542   SSL_set_SSL_CTX(ssl_, handshakeCtx->getSSLCtx());
543 }
544
545 bool AsyncSSLSocket::isServerNameMatch() const {
546   CHECK(!server_);
547
548   if (!ssl_) {
549     return false;
550   }
551
552   SSL_SESSION *ss = SSL_get_session(ssl_);
553   if (!ss) {
554     return false;
555   }
556
557   return (ss->tlsext_hostname ? true : false);
558 }
559
560 void AsyncSSLSocket::setServerName(std::string serverName) noexcept {
561   tlsextHostname_ = std::move(serverName);
562 }
563
564 #endif
565
566 void AsyncSSLSocket::timeoutExpired() noexcept {
567   if (state_ == StateEnum::ESTABLISHED &&
568       (sslState_ == STATE_CACHE_LOOKUP ||
569        sslState_ == STATE_RSA_ASYNC_PENDING)) {
570     sslState_ = STATE_ERROR;
571     // We are expecting a callback in restartSSLAccept.  The cache lookup
572     // and rsa-call necessarily have pointers to this ssl socket, so delay
573     // the cleanup until he calls us back.
574   } else {
575     assert(state_ == StateEnum::ESTABLISHED &&
576            (sslState_ == STATE_CONNECTING || sslState_ == STATE_ACCEPTING));
577     DestructorGuard dg(this);
578     AsyncSocketException ex(AsyncSocketException::TIMED_OUT,
579                            (sslState_ == STATE_CONNECTING) ?
580                            "SSL connect timed out" : "SSL accept timed out");
581     failHandshake(__func__, ex);
582   }
583 }
584
585 int AsyncSSLSocket::sslExDataIndex_ = -1;
586 std::mutex AsyncSSLSocket::mutex_;
587
588 int AsyncSSLSocket::getSSLExDataIndex() {
589   if (sslExDataIndex_ < 0) {
590     std::lock_guard<std::mutex> g(mutex_);
591     if (sslExDataIndex_ < 0) {
592       sslExDataIndex_ = SSL_get_ex_new_index(0,
593           (void*)"AsyncSSLSocket data index", nullptr, nullptr, nullptr);
594     }
595   }
596   return sslExDataIndex_;
597 }
598
599 AsyncSSLSocket* AsyncSSLSocket::getFromSSL(const SSL *ssl) {
600   return static_cast<AsyncSSLSocket *>(SSL_get_ex_data(ssl,
601       getSSLExDataIndex()));
602 }
603
604 void AsyncSSLSocket::failHandshake(const char* fn,
605                                     const AsyncSocketException& ex) {
606   startFail();
607
608   if (handshakeTimeout_.isScheduled()) {
609     handshakeTimeout_.cancelTimeout();
610   }
611   if (handshakeCallback_ != nullptr) {
612     HandshakeCB* callback = handshakeCallback_;
613     handshakeCallback_ = nullptr;
614     callback->handshakeErr(this, ex);
615   }
616
617   finishFail();
618 }
619
620 void AsyncSSLSocket::invokeHandshakeCB() {
621   if (handshakeTimeout_.isScheduled()) {
622     handshakeTimeout_.cancelTimeout();
623   }
624   if (handshakeCallback_) {
625     HandshakeCB* callback = handshakeCallback_;
626     handshakeCallback_ = nullptr;
627     callback->handshakeSuc(this);
628   }
629 }
630
631 void AsyncSSLSocket::connect(ConnectCallback* callback,
632                               const folly::SocketAddress& address,
633                               int timeout,
634                               const OptionMap &options,
635                               const folly::SocketAddress& bindAddr)
636                               noexcept {
637   assert(!server_);
638   assert(state_ == StateEnum::UNINIT);
639   assert(sslState_ == STATE_UNINIT);
640   AsyncSSLSocketConnector *connector =
641     new AsyncSSLSocketConnector(this, callback, timeout);
642   AsyncSocket::connect(connector, address, timeout, options, bindAddr);
643 }
644
645 void AsyncSSLSocket::applyVerificationOptions(SSL * ssl) {
646   // apply the settings specified in verifyPeer_
647   if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::USE_CTX) {
648     if(ctx_->needsPeerVerification()) {
649       SSL_set_verify(ssl, ctx_->getVerificationMode(),
650         AsyncSSLSocket::sslVerifyCallback);
651     }
652   } else {
653     if (verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY ||
654         verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT) {
655       SSL_set_verify(ssl, SSLContext::getVerificationMode(verifyPeer_),
656         AsyncSSLSocket::sslVerifyCallback);
657     }
658   }
659 }
660
661 void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout,
662         const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
663   DestructorGuard dg(this);
664   assert(eventBase_->isInEventBaseThread());
665
666   verifyPeer_ = verifyPeer;
667
668   // Make sure we're in the uninitialized state
669   if (server_ || sslState_ != STATE_UNINIT || handshakeCallback_ != nullptr) {
670     return invalidState(callback);
671   }
672
673   sslState_ = STATE_CONNECTING;
674   handshakeCallback_ = callback;
675
676   try {
677     ssl_ = ctx_->createSSL();
678   } catch (std::exception &e) {
679     sslState_ = STATE_ERROR;
680     AsyncSocketException ex(AsyncSocketException::INTERNAL_ERROR,
681                            "error calling SSLContext::createSSL()");
682     LOG(ERROR) << "AsyncSSLSocket::sslConn(this=" << this << ", fd="
683             << fd_ << "): " << e.what();
684     return failHandshake(__func__, ex);
685   }
686
687   applyVerificationOptions(ssl_);
688
689   SSL_set_fd(ssl_, fd_);
690   if (sslSession_ != nullptr) {
691     SSL_set_session(ssl_, sslSession_);
692     SSL_SESSION_free(sslSession_);
693     sslSession_ = nullptr;
694   }
695 #if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
696   if (tlsextHostname_.size()) {
697     SSL_set_tlsext_host_name(ssl_, tlsextHostname_.c_str());
698   }
699 #endif
700
701   SSL_set_ex_data(ssl_, getSSLExDataIndex(), this);
702
703   if (timeout > 0) {
704     handshakeTimeout_.scheduleTimeout(timeout);
705   }
706
707   handleConnect();
708 }
709
710 SSL_SESSION *AsyncSSLSocket::getSSLSession() {
711   if (ssl_ != nullptr && sslState_ == STATE_ESTABLISHED) {
712     return SSL_get1_session(ssl_);
713   }
714
715   return sslSession_;
716 }
717
718 void AsyncSSLSocket::setSSLSession(SSL_SESSION *session, bool takeOwnership) {
719   sslSession_ = session;
720   if (!takeOwnership && session != nullptr) {
721     // Increment the reference count
722     CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
723   }
724 }
725
726 void AsyncSSLSocket::getSelectedNextProtocol(const unsigned char** protoName,
727     unsigned* protoLen) const {
728   if (!getSelectedNextProtocolNoThrow(protoName, protoLen)) {
729     throw AsyncSocketException(AsyncSocketException::NOT_SUPPORTED,
730                               "NPN not supported");
731   }
732 }
733
734 bool AsyncSSLSocket::getSelectedNextProtocolNoThrow(
735   const unsigned char** protoName,
736   unsigned* protoLen) const {
737   *protoName = nullptr;
738   *protoLen = 0;
739 #ifdef OPENSSL_NPN_NEGOTIATED
740   SSL_get0_next_proto_negotiated(ssl_, protoName, protoLen);
741   return true;
742 #else
743   return false;
744 #endif
745 }
746
747 bool AsyncSSLSocket::getSSLSessionReused() const {
748   if (ssl_ != nullptr && sslState_ == STATE_ESTABLISHED) {
749     return SSL_session_reused(ssl_);
750   }
751   return false;
752 }
753
754 const char *AsyncSSLSocket::getNegotiatedCipherName() const {
755   return (ssl_ != nullptr) ? SSL_get_cipher_name(ssl_) : nullptr;
756 }
757
758 const char *AsyncSSLSocket::getSSLServerName() const {
759 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
760   return (ssl_ != nullptr) ? SSL_get_servername(ssl_, TLSEXT_NAMETYPE_host_name)
761         : nullptr;
762 #else
763   throw AsyncSocketException(AsyncSocketException::NOT_SUPPORTED,
764                             "SNI not supported");
765 #endif
766 }
767
768 const char *AsyncSSLSocket::getSSLServerNameNoThrow() const {
769   try {
770     return getSSLServerName();
771   } catch (AsyncSocketException& ex) {
772     return nullptr;
773   }
774 }
775
776 int AsyncSSLSocket::getSSLVersion() const {
777   return (ssl_ != nullptr) ? SSL_version(ssl_) : 0;
778 }
779
780 int AsyncSSLSocket::getSSLCertSize() const {
781   int certSize = 0;
782   X509 *cert = (ssl_ != nullptr) ? SSL_get_certificate(ssl_) : nullptr;
783   if (cert) {
784     EVP_PKEY *key = X509_get_pubkey(cert);
785     certSize = EVP_PKEY_bits(key);
786     EVP_PKEY_free(key);
787   }
788   return certSize;
789 }
790
791 bool AsyncSSLSocket::willBlock(int ret, int *errorOut) noexcept {
792   int error = *errorOut = SSL_get_error(ssl_, ret);
793   if (error == SSL_ERROR_WANT_READ) {
794     // Register for read event if not already.
795     updateEventRegistration(EventHandler::READ, EventHandler::WRITE);
796     return true;
797   } else if (error == SSL_ERROR_WANT_WRITE) {
798     VLOG(3) << "AsyncSSLSocket(fd=" << fd_
799             << ", state=" << int(state_) << ", sslState="
800             << sslState_ << ", events=" << eventFlags_ << "): "
801             << "SSL_ERROR_WANT_WRITE";
802     // Register for write event if not already.
803     updateEventRegistration(EventHandler::WRITE, EventHandler::READ);
804     return true;
805 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP
806   } else if (error == SSL_ERROR_WANT_SESS_CACHE_LOOKUP) {
807     // We will block but we can't register our own socket.  The callback that
808     // triggered this code will re-call handleAccept at the appropriate time.
809
810     // We can only get here if the linked libssl.so has support for this feature
811     // as well, otherwise SSL_get_error cannot return our error code.
812     sslState_ = STATE_CACHE_LOOKUP;
813
814     // Unregister for all events while blocked here
815     updateEventRegistration(EventHandler::NONE,
816                             EventHandler::READ | EventHandler::WRITE);
817
818     // The timeout (if set) keeps running here
819     return true;
820 #endif
821 #ifdef SSL_ERROR_WANT_RSA_ASYNC_PENDING
822   } else if (error == SSL_ERROR_WANT_RSA_ASYNC_PENDING) {
823     // Our custom openssl function has kicked off an async request to do
824     // modular exponentiation.  When that call returns, a callback will
825     // be invoked that will re-call handleAccept.
826     sslState_ = STATE_RSA_ASYNC_PENDING;
827
828     // Unregister for all events while blocked here
829     updateEventRegistration(
830       EventHandler::NONE,
831       EventHandler::READ | EventHandler::WRITE
832     );
833
834     // The timeout (if set) keeps running here
835     return true;
836 #endif
837   } else {
838     // SSL_ERROR_ZERO_RETURN is processed here so we can get some detail
839     // in the log
840     long lastError = ERR_get_error();
841     VLOG(6) << "AsyncSSLSocket(fd=" << fd_ << ", "
842             << "state=" << state_ << ", "
843             << "sslState=" << sslState_ << ", "
844             << "events=" << std::hex << eventFlags_ << "): "
845             << "SSL error: " << error << ", "
846             << "errno: " << errno << ", "
847             << "ret: " << ret << ", "
848             << "read: " << BIO_number_read(SSL_get_rbio(ssl_)) << ", "
849             << "written: " << BIO_number_written(SSL_get_wbio(ssl_)) << ", "
850             << "func: " << ERR_func_error_string(lastError) << ", "
851             << "reason: " << ERR_reason_error_string(lastError);
852     if (error != SSL_ERROR_SYSCALL) {
853       if (error == SSL_ERROR_SSL) {
854         *errorOut = lastError;
855       }
856       if ((unsigned long)lastError < 0x8000) {
857         errno = ENOSYS;
858       } else {
859         errno = lastError;
860       }
861     }
862     ERR_clear_error();
863     return false;
864   }
865 }
866
867 void AsyncSSLSocket::checkForImmediateRead() noexcept {
868   // openssl may have buffered data that it read from the socket already.
869   // In this case we have to process it immediately, rather than waiting for
870   // the socket to become readable again.
871   if (ssl_ != nullptr && SSL_pending(ssl_) > 0) {
872     AsyncSocket::handleRead();
873   }
874 }
875
876 void
877 AsyncSSLSocket::restartSSLAccept()
878 {
879   VLOG(3) << "AsyncSSLSocket::restartSSLAccept() this=" << this << ", fd=" << fd_
880           << ", state=" << int(state_) << ", "
881           << "sslState=" << sslState_ << ", events=" << eventFlags_;
882   DestructorGuard dg(this);
883   assert(
884     sslState_ == STATE_CACHE_LOOKUP ||
885     sslState_ == STATE_RSA_ASYNC_PENDING ||
886     sslState_ == STATE_ERROR ||
887     sslState_ == STATE_CLOSED
888   );
889   if (sslState_ == STATE_CLOSED) {
890     // I sure hope whoever closed this socket didn't delete it already,
891     // but this is not strictly speaking an error
892     return;
893   }
894   if (sslState_ == STATE_ERROR) {
895     // go straight to fail if timeout expired during lookup
896     AsyncSocketException ex(AsyncSocketException::TIMED_OUT,
897                            "SSL accept timed out");
898     failHandshake(__func__, ex);
899     return;
900   }
901   sslState_ = STATE_ACCEPTING;
902   this->handleAccept();
903 }
904
905 void
906 AsyncSSLSocket::handleAccept() noexcept {
907   VLOG(3) << "AsyncSSLSocket::handleAccept() this=" << this
908           << ", fd=" << fd_ << ", state=" << int(state_) << ", "
909           << "sslState=" << sslState_ << ", events=" << eventFlags_;
910   assert(server_);
911   assert(state_ == StateEnum::ESTABLISHED &&
912          sslState_ == STATE_ACCEPTING);
913   if (!ssl_) {
914     /* lazily create the SSL structure */
915     try {
916       ssl_ = ctx_->createSSL();
917     } catch (std::exception &e) {
918       sslState_ = STATE_ERROR;
919       AsyncSocketException ex(AsyncSocketException::INTERNAL_ERROR,
920                              "error calling SSLContext::createSSL()");
921       LOG(ERROR) << "AsyncSSLSocket::handleAccept(this=" << this
922                  << ", fd=" << fd_ << "): " << e.what();
923       return failHandshake(__func__, ex);
924     }
925     SSL_set_fd(ssl_, fd_);
926     SSL_set_ex_data(ssl_, getSSLExDataIndex(), this);
927
928     applyVerificationOptions(ssl_);
929   }
930
931   if (server_ && parseClientHello_) {
932     SSL_set_msg_callback_arg(ssl_, this);
933     SSL_set_msg_callback(ssl_, &AsyncSSLSocket::clientHelloParsingCallback);
934   }
935
936   errno = 0;
937   int ret = SSL_accept(ssl_);
938   if (ret <= 0) {
939     int error;
940     if (willBlock(ret, &error)) {
941       return;
942     } else {
943       sslState_ = STATE_ERROR;
944       SSLException ex(error, errno);
945       return failHandshake(__func__, ex);
946     }
947   }
948
949   handshakeComplete_ = true;
950   updateEventRegistration(0, EventHandler::READ | EventHandler::WRITE);
951
952   // Move into STATE_ESTABLISHED in the normal case that we are in
953   // STATE_ACCEPTING.
954   sslState_ = STATE_ESTABLISHED;
955
956   VLOG(3) << "AsyncSSLSocket " << this << ": fd " << fd_
957           << " successfully accepted; state=" << int(state_)
958           << ", sslState=" << sslState_ << ", events=" << eventFlags_;
959
960   // Remember the EventBase we are attached to, before we start invoking any
961   // callbacks (since the callbacks may call detachEventBase()).
962   EventBase* originalEventBase = eventBase_;
963
964   // Call the accept callback.
965   invokeHandshakeCB();
966
967   // Note that the accept callback may have changed our state.
968   // (set or unset the read callback, called write(), closed the socket, etc.)
969   // The following code needs to handle these situations correctly.
970   //
971   // If the socket has been closed, readCallback_ and writeReqHead_ will
972   // always be nullptr, so that will prevent us from trying to read or write.
973   //
974   // The main thing to check for is if eventBase_ is still originalEventBase.
975   // If not, we have been detached from this event base, so we shouldn't
976   // perform any more operations.
977   if (eventBase_ != originalEventBase) {
978     return;
979   }
980
981   AsyncSocket::handleInitialReadWrite();
982 }
983
984 void
985 AsyncSSLSocket::handleConnect() noexcept {
986   VLOG(3) <<  "AsyncSSLSocket::handleConnect() this=" << this
987           << ", fd=" << fd_ << ", state=" << int(state_) << ", "
988           << "sslState=" << sslState_ << ", events=" << eventFlags_;
989   assert(!server_);
990   if (state_ < StateEnum::ESTABLISHED) {
991     return AsyncSocket::handleConnect();
992   }
993
994   assert(state_ == StateEnum::ESTABLISHED &&
995          sslState_ == STATE_CONNECTING);
996   assert(ssl_);
997
998   errno = 0;
999   int ret = SSL_connect(ssl_);
1000   if (ret <= 0) {
1001     int error;
1002     if (willBlock(ret, &error)) {
1003       return;
1004     } else {
1005       sslState_ = STATE_ERROR;
1006       SSLException ex(error, errno);
1007       return failHandshake(__func__, ex);
1008     }
1009   }
1010
1011   handshakeComplete_ = true;
1012   updateEventRegistration(0, EventHandler::READ | EventHandler::WRITE);
1013
1014   // Move into STATE_ESTABLISHED in the normal case that we are in
1015   // STATE_CONNECTING.
1016   sslState_ = STATE_ESTABLISHED;
1017
1018   VLOG(3) << "AsyncSSLSocket %p: fd %d successfully connected; "
1019           << "state=" << int(state_) << ", sslState=" << sslState_
1020           << ", events=" << eventFlags_;
1021
1022   // Remember the EventBase we are attached to, before we start invoking any
1023   // callbacks (since the callbacks may call detachEventBase()).
1024   EventBase* originalEventBase = eventBase_;
1025
1026   // Call the handshake callback.
1027   invokeHandshakeCB();
1028
1029   // Note that the connect callback may have changed our state.
1030   // (set or unset the read callback, called write(), closed the socket, etc.)
1031   // The following code needs to handle these situations correctly.
1032   //
1033   // If the socket has been closed, readCallback_ and writeReqHead_ will
1034   // always be nullptr, so that will prevent us from trying to read or write.
1035   //
1036   // The main thing to check for is if eventBase_ is still originalEventBase.
1037   // If not, we have been detached from this event base, so we shouldn't
1038   // perform any more operations.
1039   if (eventBase_ != originalEventBase) {
1040     return;
1041   }
1042
1043   AsyncSocket::handleInitialReadWrite();
1044 }
1045
1046 void
1047 AsyncSSLSocket::handleRead() noexcept {
1048   VLOG(5) << "AsyncSSLSocket::handleRead() this=" << this << ", fd=" << fd_
1049           << ", state=" << int(state_) << ", "
1050           << "sslState=" << sslState_ << ", events=" << eventFlags_;
1051   if (state_ < StateEnum::ESTABLISHED) {
1052     return AsyncSocket::handleRead();
1053   }
1054
1055
1056   if (sslState_ == STATE_ACCEPTING) {
1057     assert(server_);
1058     handleAccept();
1059     return;
1060   }
1061   else if (sslState_ == STATE_CONNECTING) {
1062     assert(!server_);
1063     handleConnect();
1064     return;
1065   }
1066
1067   // Normal read
1068   AsyncSocket::handleRead();
1069 }
1070
1071 ssize_t
1072 AsyncSSLSocket::performRead(void* buf, size_t buflen) {
1073   errno = 0;
1074   ssize_t bytes = SSL_read(ssl_, buf, buflen);
1075   if (server_ && renegotiateAttempted_) {
1076     LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1077                << ", sslstate=" << sslState_ << ", events=" << eventFlags_ << "): "
1078                << "client intitiated SSL renegotiation not permitted";
1079     // We pack our own SSLerr here with a dummy function
1080     errno = ERR_PACK(ERR_LIB_USER, TASYNCSSLSOCKET_F_PERFORM_READ,
1081                      SSL_CLIENT_RENEGOTIATION_ATTEMPT);
1082     ERR_clear_error();
1083     return READ_ERROR;
1084   }
1085   if (bytes <= 0) {
1086     int error = SSL_get_error(ssl_, bytes);
1087     if (error == SSL_ERROR_WANT_READ) {
1088       // The caller will register for read event if not already.
1089       return READ_BLOCKING;
1090     } else if (error == SSL_ERROR_WANT_WRITE) {
1091       // TODO: Even though we are attempting to read data, SSL_read() may
1092       // need to write data if renegotiation is being performed.  We currently
1093       // don't support this and just fail the read.
1094       LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1095                  << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
1096                  << "unsupported SSL renegotiation during read",
1097       errno = ERR_PACK(ERR_LIB_USER, TASYNCSSLSOCKET_F_PERFORM_READ,
1098                        SSL_INVALID_RENEGOTIATION);
1099       ERR_clear_error();
1100       return READ_ERROR;
1101     } else {
1102       // TODO: Fix this code so that it can return a proper error message
1103       // to the callback, rather than relying on AsyncSocket code which
1104       // can't handle SSL errors.
1105       long lastError = ERR_get_error();
1106
1107       VLOG(6) << "AsyncSSLSocket(fd=" << fd_ << ", "
1108               << "state=" << state_ << ", "
1109               << "sslState=" << sslState_ << ", "
1110               << "events=" << std::hex << eventFlags_ << "): "
1111               << "bytes: " << bytes << ", "
1112               << "error: " << error << ", "
1113               << "errno: " << errno << ", "
1114               << "func: " << ERR_func_error_string(lastError) << ", "
1115               << "reason: " << ERR_reason_error_string(lastError);
1116       ERR_clear_error();
1117       if (zero_return(error, bytes)) {
1118         return bytes;
1119       }
1120       if (error != SSL_ERROR_SYSCALL) {
1121         if ((unsigned long)lastError < 0x8000) {
1122           errno = ENOSYS;
1123         } else {
1124           errno = lastError;
1125         }
1126       }
1127       return READ_ERROR;
1128     }
1129   } else {
1130     appBytesReceived_ += bytes;
1131     return bytes;
1132   }
1133 }
1134
1135 void AsyncSSLSocket::handleWrite() noexcept {
1136   VLOG(5) << "AsyncSSLSocket::handleWrite() this=" << this << ", fd=" << fd_
1137           << ", state=" << int(state_) << ", "
1138           << "sslState=" << sslState_ << ", events=" << eventFlags_;
1139   if (state_ < StateEnum::ESTABLISHED) {
1140     return AsyncSocket::handleWrite();
1141   }
1142
1143   if (sslState_ == STATE_ACCEPTING) {
1144     assert(server_);
1145     handleAccept();
1146     return;
1147   }
1148
1149   if (sslState_ == STATE_CONNECTING) {
1150     assert(!server_);
1151     handleConnect();
1152     return;
1153   }
1154
1155   // Normal write
1156   AsyncSocket::handleWrite();
1157 }
1158
1159 ssize_t AsyncSSLSocket::performWrite(const iovec* vec,
1160                                       uint32_t count,
1161                                       WriteFlags flags,
1162                                       uint32_t* countWritten,
1163                                       uint32_t* partialWritten) {
1164   if (sslState_ != STATE_ESTABLISHED) {
1165     LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1166                << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
1167                << "TODO: AsyncSSLSocket currently does not support calling "
1168                << "write() before the handshake has fully completed";
1169       errno = ERR_PACK(ERR_LIB_USER, TASYNCSSLSOCKET_F_PERFORM_WRITE,
1170                        SSL_EARLY_WRITE);
1171       return -1;
1172   }
1173
1174   bool cork = isSet(flags, WriteFlags::CORK);
1175   CorkGuard guard(fd_, count > 1, cork, &corked_);
1176
1177   *countWritten = 0;
1178   *partialWritten = 0;
1179   ssize_t totalWritten = 0;
1180   size_t bytesStolenFromNextBuffer = 0;
1181   for (uint32_t i = 0; i < count; i++) {
1182     const iovec* v = vec + i;
1183     size_t offset = bytesStolenFromNextBuffer;
1184     bytesStolenFromNextBuffer = 0;
1185     size_t len = v->iov_len - offset;
1186     const void* buf;
1187     if (len == 0) {
1188       (*countWritten)++;
1189       continue;
1190     }
1191     buf = ((const char*)v->iov_base) + offset;
1192
1193     ssize_t bytes;
1194     errno = 0;
1195     uint32_t buffersStolen = 0;
1196     if ((len < MIN_WRITE_SIZE) && ((i + 1) < count)) {
1197       // Combine this buffer with part or all of the next buffers in
1198       // order to avoid really small-grained calls to SSL_write().
1199       // Each call to SSL_write() produces a separate record in
1200       // the egress SSL stream, and we've found that some low-end
1201       // mobile clients can't handle receiving an HTTP response
1202       // header and the first part of the response body in two
1203       // separate SSL records (even if those two records are in
1204       // the same TCP packet).
1205       char combinedBuf[MIN_WRITE_SIZE];
1206       memcpy(combinedBuf, buf, len);
1207       do {
1208         // INVARIANT: i + buffersStolen == complete chunks serialized
1209         uint32_t nextIndex = i + buffersStolen + 1;
1210         bytesStolenFromNextBuffer = std::min(vec[nextIndex].iov_len,
1211                                              MIN_WRITE_SIZE - len);
1212         memcpy(combinedBuf + len, vec[nextIndex].iov_base,
1213                bytesStolenFromNextBuffer);
1214         len += bytesStolenFromNextBuffer;
1215         if (bytesStolenFromNextBuffer < vec[nextIndex].iov_len) {
1216           // couldn't steal the whole buffer
1217           break;
1218         } else {
1219           bytesStolenFromNextBuffer = 0;
1220           buffersStolen++;
1221         }
1222       } while ((i + buffersStolen + 1) < count && (len < MIN_WRITE_SIZE));
1223       bytes = eorAwareSSLWrite(
1224         ssl_, combinedBuf, len,
1225         (isSet(flags, WriteFlags::EOR) && i + buffersStolen + 1 == count));
1226
1227     } else {
1228       bytes = eorAwareSSLWrite(ssl_, buf, len,
1229                            (isSet(flags, WriteFlags::EOR) && i + 1 == count));
1230     }
1231
1232     if (bytes <= 0) {
1233       int error = SSL_get_error(ssl_, bytes);
1234       if (error == SSL_ERROR_WANT_WRITE) {
1235         // The caller will register for write event if not already.
1236         *partialWritten = offset;
1237         return totalWritten;
1238       } else if (error == SSL_ERROR_WANT_READ) {
1239         // TODO: Even though we are attempting to write data, SSL_write() may
1240         // need to read data if renegotiation is being performed.  We currently
1241         // don't support this and just fail the write.
1242         LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1243                    << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
1244                    << "unsupported SSL renegotiation during write",
1245         errno = ERR_PACK(ERR_LIB_USER, TASYNCSSLSOCKET_F_PERFORM_WRITE,
1246                          SSL_INVALID_RENEGOTIATION);
1247         ERR_clear_error();
1248         return -1;
1249       } else {
1250         // TODO: Fix this code so that it can return a proper error message
1251         // to the callback, rather than relying on AsyncSocket code which
1252         // can't handle SSL errors.
1253         long lastError = ERR_get_error();
1254         VLOG(3) <<
1255           "ERROR: AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
1256                 << ", sslState=" << sslState_ << ", events=" << eventFlags_ << "): "
1257                 << "SSL error: " << error << ", errno: " << errno
1258                 << ", func: " << ERR_func_error_string(lastError)
1259                 << ", reason: " << ERR_reason_error_string(lastError);
1260         if (error != SSL_ERROR_SYSCALL) {
1261           if ((unsigned long)lastError < 0x8000) {
1262             errno = ENOSYS;
1263           } else {
1264             errno = lastError;
1265           }
1266         }
1267         ERR_clear_error();
1268         if (!zero_return(error, bytes)) {
1269           return -1;
1270         } // else fall through to below to correctly record totalWritten
1271       }
1272     }
1273
1274     totalWritten += bytes;
1275
1276     if (bytes == (ssize_t)len) {
1277       // The full iovec is written.
1278       (*countWritten) += 1 + buffersStolen;
1279       i += buffersStolen;
1280       // continue
1281     } else {
1282       bytes += offset; // adjust bytes to account for all of v
1283       while (bytes >= (ssize_t)v->iov_len) {
1284         // We combined this buf with part or all of the next one, and
1285         // we managed to write all of this buf but not all of the bytes
1286         // from the next one that we'd hoped to write.
1287         bytes -= v->iov_len;
1288         (*countWritten)++;
1289         v = &(vec[++i]);
1290       }
1291       *partialWritten = bytes;
1292       return totalWritten;
1293     }
1294   }
1295
1296   return totalWritten;
1297 }
1298
1299 int AsyncSSLSocket::eorAwareSSLWrite(SSL *ssl, const void *buf, int n,
1300                                       bool eor) {
1301   if (eor && SSL_get_wbio(ssl)->method == &eorAwareBioMethod) {
1302     if (appEorByteNo_) {
1303       // cannot track for more than one app byte EOR
1304       CHECK(appEorByteNo_ == appBytesWritten_ + n);
1305     } else {
1306       appEorByteNo_ = appBytesWritten_ + n;
1307     }
1308
1309     // 1. It is fine to keep updating minEorRawByteNo_.
1310     // 2. It is _min_ in the sense that SSL record will add some overhead.
1311     minEorRawByteNo_ = getRawBytesWritten() + n;
1312   }
1313
1314   n = sslWriteImpl(ssl, buf, n);
1315   if (n > 0) {
1316     appBytesWritten_ += n;
1317     if (appEorByteNo_) {
1318       if (getRawBytesWritten() >= minEorRawByteNo_) {
1319         minEorRawByteNo_ = 0;
1320       }
1321       if(appBytesWritten_ == appEorByteNo_) {
1322         appEorByteNo_ = 0;
1323       } else {
1324         CHECK(appBytesWritten_ < appEorByteNo_);
1325       }
1326     }
1327   }
1328   return n;
1329 }
1330
1331 void
1332 AsyncSSLSocket::sslInfoCallback(const SSL *ssl, int where, int ret) {
1333   AsyncSSLSocket *sslSocket = AsyncSSLSocket::getFromSSL(ssl);
1334   if (sslSocket->handshakeComplete_ && (where & SSL_CB_HANDSHAKE_START)) {
1335     sslSocket->renegotiateAttempted_ = true;
1336   }
1337 }
1338
1339 int AsyncSSLSocket::eorAwareBioWrite(BIO *b, const char *in, int inl) {
1340   int ret;
1341   struct msghdr msg;
1342   struct iovec iov;
1343   int flags = 0;
1344   AsyncSSLSocket *tsslSock;
1345
1346   iov.iov_base = const_cast<char *>(in);
1347   iov.iov_len = inl;
1348   memset(&msg, 0, sizeof(msg));
1349   msg.msg_iov = &iov;
1350   msg.msg_iovlen = 1;
1351
1352   tsslSock =
1353     reinterpret_cast<AsyncSSLSocket*>(BIO_get_app_data(b));
1354   if (tsslSock &&
1355       tsslSock->minEorRawByteNo_ &&
1356       tsslSock->minEorRawByteNo_ <= BIO_number_written(b) + inl) {
1357     flags = MSG_EOR;
1358   }
1359
1360   errno = 0;
1361   ret = sendmsg(b->num, &msg, flags);
1362   BIO_clear_retry_flags(b);
1363   if (ret <= 0) {
1364     if (BIO_sock_should_retry(ret))
1365       BIO_set_retry_write(b);
1366   }
1367   return(ret);
1368 }
1369
1370 int AsyncSSLSocket::sslVerifyCallback(int preverifyOk,
1371                                        X509_STORE_CTX* x509Ctx) {
1372   SSL* ssl = (SSL*) X509_STORE_CTX_get_ex_data(
1373     x509Ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
1374   AsyncSSLSocket* self = AsyncSSLSocket::getFromSSL(ssl);
1375
1376   VLOG(3) <<  "AsyncSSLSocket::sslVerifyCallback() this=" << self << ", "
1377           << "fd=" << self->fd_ << ", preverifyOk=" << preverifyOk;
1378   return (self->handshakeCallback_) ?
1379     self->handshakeCallback_->handshakeVer(self, preverifyOk, x509Ctx) :
1380     preverifyOk;
1381 }
1382
1383 void AsyncSSLSocket::enableClientHelloParsing()  {
1384     parseClientHello_ = true;
1385     clientHelloInfo_.reset(new ClientHelloInfo());
1386 }
1387
1388 void AsyncSSLSocket::resetClientHelloParsing(SSL *ssl)  {
1389   SSL_set_msg_callback(ssl, nullptr);
1390   SSL_set_msg_callback_arg(ssl, nullptr);
1391   clientHelloInfo_->clientHelloBuf_.clear();
1392 }
1393
1394 void
1395 AsyncSSLSocket::clientHelloParsingCallback(int written, int version,
1396     int contentType, const void *buf, size_t len, SSL *ssl, void *arg)
1397 {
1398   AsyncSSLSocket *sock = static_cast<AsyncSSLSocket*>(arg);
1399   if (written != 0) {
1400     sock->resetClientHelloParsing(ssl);
1401     return;
1402   }
1403   if (contentType != SSL3_RT_HANDSHAKE) {
1404     sock->resetClientHelloParsing(ssl);
1405     return;
1406   }
1407   if (len == 0) {
1408     return;
1409   }
1410
1411   auto& clientHelloBuf = sock->clientHelloInfo_->clientHelloBuf_;
1412   clientHelloBuf.append(IOBuf::wrapBuffer(buf, len));
1413   try {
1414     Cursor cursor(clientHelloBuf.front());
1415     if (cursor.read<uint8_t>() != SSL3_MT_CLIENT_HELLO) {
1416       sock->resetClientHelloParsing(ssl);
1417       return;
1418     }
1419
1420     if (cursor.totalLength() < 3) {
1421       clientHelloBuf.trimEnd(len);
1422       clientHelloBuf.append(IOBuf::copyBuffer(buf, len));
1423       return;
1424     }
1425
1426     uint32_t messageLength = cursor.read<uint8_t>();
1427     messageLength <<= 8;
1428     messageLength |= cursor.read<uint8_t>();
1429     messageLength <<= 8;
1430     messageLength |= cursor.read<uint8_t>();
1431     if (cursor.totalLength() < messageLength) {
1432       clientHelloBuf.trimEnd(len);
1433       clientHelloBuf.append(IOBuf::copyBuffer(buf, len));
1434       return;
1435     }
1436
1437     sock->clientHelloInfo_->clientHelloMajorVersion_ = cursor.read<uint8_t>();
1438     sock->clientHelloInfo_->clientHelloMinorVersion_ = cursor.read<uint8_t>();
1439
1440     cursor.skip(4); // gmt_unix_time
1441     cursor.skip(28); // random_bytes
1442
1443     cursor.skip(cursor.read<uint8_t>()); // session_id
1444
1445     uint16_t cipherSuitesLength = cursor.readBE<uint16_t>();
1446     for (int i = 0; i < cipherSuitesLength; i += 2) {
1447       sock->clientHelloInfo_->
1448         clientHelloCipherSuites_.push_back(cursor.readBE<uint16_t>());
1449     }
1450
1451     uint8_t compressionMethodsLength = cursor.read<uint8_t>();
1452     for (int i = 0; i < compressionMethodsLength; ++i) {
1453       sock->clientHelloInfo_->
1454         clientHelloCompressionMethods_.push_back(cursor.readBE<uint8_t>());
1455     }
1456
1457     if (cursor.totalLength() > 0) {
1458       uint16_t extensionsLength = cursor.readBE<uint16_t>();
1459       while (extensionsLength) {
1460         sock->clientHelloInfo_->
1461           clientHelloExtensions_.push_back(cursor.readBE<uint16_t>());
1462         extensionsLength -= 2;
1463         uint16_t extensionDataLength = cursor.readBE<uint16_t>();
1464         extensionsLength -= 2;
1465         cursor.skip(extensionDataLength);
1466         extensionsLength -= extensionDataLength;
1467       }
1468     }
1469   } catch (std::out_of_range& e) {
1470     // we'll use what we found and cleanup below.
1471     VLOG(4) << "AsyncSSLSocket::clientHelloParsingCallback(): "
1472       << "buffer finished unexpectedly." << " AsyncSSLSocket socket=" << sock;
1473   }
1474
1475   sock->resetClientHelloParsing(ssl);
1476 }
1477
1478 } // namespace