24 #include <sys/types.h> 38 using std::shared_ptr;
47 using std::unique_ptr;
66 const size_t MAX_STACK_BUF_SIZE = 2048;
69 inline bool zero_return(
int error,
int rc) {
70 return (error == SSL_ERROR_ZERO_RETURN || (rc == 0 && errno == 0));
80 X509_up_ref(x509_.get());
92 class AsyncSSLSocketConnector :
public AsyncSocket::ConnectCallback,
93 public AsyncSSLSocket::HandshakeCB {
96 AsyncSSLSocket::ConnectCallback*
callback_;
97 std::chrono::milliseconds timeout_;
98 std::chrono::steady_clock::time_point startTime_;
101 ~AsyncSSLSocketConnector()
override {}
104 AsyncSSLSocketConnector(
105 AsyncSSLSocket* sslSocket,
106 AsyncSocket::ConnectCallback* callback,
107 std::chrono::milliseconds timeout)
108 : sslSocket_(sslSocket),
113 void connectSuccess()
noexcept override {
114 VLOG(7) <<
"client socket connected";
116 std::chrono::milliseconds timeoutLeft{0};
117 if (timeout_ > std::chrono::milliseconds::zero()) {
120 timeoutLeft = std::chrono::duration_cast<std::chrono::milliseconds>(
121 timeout_ - (curTime - startTime_));
122 if (timeoutLeft <= std::chrono::milliseconds::zero()) {
123 AsyncSocketException ex(
126 "SSL connect timed out after {}ms", timeout_.count()));
132 sslSocket_->sslConn(
this, timeoutLeft);
135 void connectErr(
const AsyncSocketException& ex)
noexcept override {
136 VLOG(1) <<
"TCP connect failed: " << ex.what();
141 void handshakeSuc(AsyncSSLSocket* )
noexcept override {
142 VLOG(7) <<
"client handshake success";
144 callback_->connectSuccess();
151 const AsyncSocketException& ex) noexcept
override {
152 VLOG(1) <<
"client handshakeErr: " << ex.what();
157 void fail(
const AsyncSocketException& ex) {
160 AsyncSSLSocket::ConnectCallback* cb =
callback_;
164 sslSocket_->closeNow();
174 void setup_SSL_CTX(SSL_CTX* ctx) {
175 #ifdef SSL_MODE_RELEASE_BUFFERS 178 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE |
179 SSL_MODE_RELEASE_BUFFERS);
182 ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
185 #ifdef SSL_MODE_WRITE_IOVEC 186 SSL_CTX_set_mode(ctx, SSL_CTX_get_mode(ctx) | SSL_MODE_WRITE_IOVEC);
194 static BIO_METHOD* getSSLBioMethod() {
199 void* initsslBioMethod() {
200 auto sslBioMethod = getSSLBioMethod();
223 const shared_ptr<SSLContext>& ctx,
225 bool deferSecurityNegotiation)
228 handshakeTimeout_(this, evb),
229 connectionTimeout_(this, evb) {
231 if (deferSecurityNegotiation) {
240 const shared_ptr<SSLContext>& ctx,
244 bool deferSecurityNegotiation)
253 SSL_CTX_set_info_callback(
256 if (deferSecurityNegotiation) {
262 const shared_ptr<SSLContext>& ctx,
265 bool deferSecurityNegotiation)
274 SSL_CTX_set_info_callback(
277 if (deferSecurityNegotiation) {
282 #if FOLLY_OPENSSL_HAS_SNI 288 const shared_ptr<SSLContext>& ctx,
291 bool deferSecurityNegotiation)
293 tlsextHostname_ = serverName;
301 const shared_ptr<SSLContext>& ctx,
305 bool deferSecurityNegotiation)
307 tlsextHostname_ = serverName;
309 #endif // FOLLY_OPENSSL_HAS_SNI 312 VLOG(3) <<
"actual destruction of AsyncSSLSocket(this=" <<
this 321 static const auto sslBioMethodInitializer = initsslBioMethod();
322 (void)sslBioMethodInitializer;
324 setup_SSL_CTX(
ctx_->getSSLCtx());
329 if (
ssl_ !=
nullptr &&
fd_ != -1) {
330 int rc = SSL_shutdown(
ssl_.get());
332 rc = SSL_shutdown(
ssl_.get());
395 const unsigned char* protoName =
nullptr;
396 unsigned protoLength;
398 return std::string(reinterpret_cast<const char*>(protoName), protoLength);
417 if (!
ssl_ || !(b = SSL_get_wbio(
ssl_.get()))) {
420 BIO*
next = BIO_next(b);
421 while (next !=
nullptr) {
426 return BIO_number_written(b);
431 if (!
ssl_ || !(b = SSL_get_rbio(
ssl_.get()))) {
435 return BIO_number_read(b);
439 LOG(ERROR) <<
"AsyncSSLSocket(this=" <<
this <<
", fd=" <<
fd_ 443 <<
"sslAccept/Connect() called in invalid " 445 <<
", new callback " << callback;
451 "sslAccept() called with socket in invalid state");
455 callback->handshakeErr(
this, ex);
463 std::chrono::milliseconds timeout,
489 if (timeout > std::chrono::milliseconds::zero()) {
499 void AsyncSSLSocket::attachSSLContext(
const std::shared_ptr<SSLContext>& ctx) {
506 DCHECK(ctx->getSSLCtx());
525 auto sslCtx = ctx->getSSLCtx();
530 SSL_set_SSL_CTX(
ssl_.get(), sslCtx);
533 void AsyncSSLSocket::detachSSLContext() {
551 SSL_CTX_free(initialCtx);
556 if (
nullptr == dummyCtx) {
568 #if FOLLY_OPENSSL_HAS_SNI 569 void AsyncSSLSocket::switchServerSSLContext(
570 const std::shared_ptr<SSLContext>& handshakeCtx) {
576 VLOG(6) <<
"fd=" <<
getFd()
577 <<
" renegotation detected when switching SSL_CTX";
580 setup_SSL_CTX(handshakeCtx->getSSLCtx());
581 SSL_CTX_set_info_callback(
583 handshakeCtx_ = handshakeCtx;
584 SSL_set_SSL_CTX(
ssl_.get(), handshakeCtx->getSSLCtx());
587 bool AsyncSSLSocket::isServerNameMatch()
const {
594 SSL_SESSION* ss = SSL_get_session(
ssl_.get());
600 return (tlsextHostname && !tlsextHostname_.compare(tlsextHostname));
603 void AsyncSSLSocket::setServerName(
std::string serverName) noexcept {
607 #endif // FOLLY_OPENSSL_HAS_SNI 610 std::chrono::milliseconds timeout) noexcept {
622 "Fallback connect timed out during TFO");
632 "SSL {} timed out after {}ms",
640 static auto index = SSL_get_ex_new_index(
641 0, (
void*)
"AsyncSSLSocket data index",
nullptr,
nullptr,
nullptr);
688 auto timeoutChrono = std::chrono::milliseconds(
timeout);
689 connect(callback, address, timeoutChrono, timeoutChrono, options, bindAddr);
695 std::chrono::milliseconds connectTimeout,
696 std::chrono::milliseconds totalConnectTimeout,
705 callback =
new AsyncSSLSocketConnector(
this, callback, totalConnectTimeout);
708 callback, address,
int(connectTimeout.count()), options, bindAddr);
712 if (
verifyPeer_ == SSLContext::SSLVerifyPeerEnum::USE_CTX) {
713 return ctx_->needsPeerVerification();
716 verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY ||
717 verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT);
722 if (
verifyPeer_ == SSLContext::SSLVerifyPeerEnum::USE_CTX) {
723 if (
ctx_->needsPeerVerification()) {
726 ctx_->getVerificationMode(),
730 if (
verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY ||
731 verifyPeer_ == SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT) {
741 auto sslBio = BIO_new(getSSLBioMethod());
749 SSL_set_bio(
ssl_.get(), sslBio, sslBio);
755 std::chrono::milliseconds timeout,
780 }
catch (std::exception& e) {
784 "error calling SSLContext::createSSL()");
785 LOG(ERROR) <<
"AsyncSSLSocket::sslConn(this=" <<
this <<
", fd=" <<
fd_ 786 <<
"): " << e.what();
805 #if FOLLY_OPENSSL_HAS_SNI 806 if (tlsextHostname_.size()) {
807 SSL_set_tlsext_host_name(
ssl_.get(), tlsextHostname_.c_str());
831 return SSL_get1_session(
ssl_.get());
846 if (!takeOwnership && session !=
nullptr) {
849 SSL_SESSION_up_ref(session);
854 const unsigned char** protoName,
855 unsigned* protoLen)
const {
863 const unsigned char** protoName,
864 unsigned* protoLen)
const {
865 *protoName =
nullptr;
867 #if FOLLY_OPENSSL_HAS_ALPN 868 SSL_get0_alpn_selected(
ssl_.get(), protoName, protoLen);
877 return SSL_session_reused(
ssl_.get());
883 return (
ssl_ !=
nullptr) ? SSL_get_cipher_name(
ssl_.get()) :
nullptr;
888 if (ssl ==
nullptr) {
891 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 892 return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
899 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 912 return (
ssl_ !=
nullptr) ? SSL_version(
ssl_.get()) : 0;
916 X509* cert = (
ssl_ !=
nullptr) ? SSL_get_certificate(
ssl_.get()) :
nullptr;
918 int nid = X509_get_signature_nid(cert);
919 return OBJ_nid2ln(nid);
926 X509* cert = (
ssl_ !=
nullptr) ? SSL_get_certificate(
ssl_.get()) :
nullptr;
928 EVP_PKEY* key = X509_get_pubkey(cert);
929 certSize = EVP_PKEY_bits(key);
939 if (
ssl_ !=
nullptr) {
940 auto peerX509 = SSL_get_peer_certificate(
ssl_.get());
954 if (
ssl_ !=
nullptr) {
955 auto selfX509 = SSL_get_certificate(
ssl_.get());
958 X509_up_ref(selfX509);
968 return (
ssl_ !=
nullptr) ? SSL_get_certificate(
ssl_.get()) :
nullptr;
974 unsigned long* errErrorOut) noexcept {
976 int error = *sslErrorOut = SSL_get_error(
ssl_.get(), ret);
977 if (error == SSL_ERROR_WANT_READ) {
981 }
else if (error == SSL_ERROR_WANT_WRITE) {
982 VLOG(3) <<
"AsyncSSLSocket(fd=" <<
fd_ <<
", state=" << int(
state_)
984 <<
"SSL_ERROR_WANT_WRITE";
988 #ifdef SSL_ERROR_WANT_SESS_CACHE_LOOKUP 989 }
else if (error == SSL_ERROR_WANT_SESS_CACHE_LOOKUP) {
1005 #ifdef SSL_ERROR_WANT_RSA_ASYNC_PENDING
1006 || error == SSL_ERROR_WANT_RSA_ASYNC_PENDING
1008 #ifdef SSL_ERROR_WANT_ECDSA_ASYNC_PENDING
1009 || error == SSL_ERROR_WANT_ECDSA_ASYNC_PENDING
1011 #ifdef SSL_ERROR_WANT_ASYNC
1012 || error == SSL_ERROR_WANT_ASYNC
1024 #ifdef SSL_ERROR_WANT_ASYNC 1025 if (error == SSL_ERROR_WANT_ASYNC) {
1027 if (SSL_get_all_async_fds(
ssl_.get(), NULL, &numfds) <= 0) {
1028 VLOG(4) <<
"SSL_ERROR_WANT_ASYNC but no async FDs set!";
1032 VLOG(4) <<
"SSL_ERROR_WANT_ASYNC expected exactly 1 async fd, got " 1037 if (SSL_get_all_async_fds(
ssl_.get(), &ofd, &numfds) <= 0) {
1038 VLOG(4) <<
"SSL_ERROR_WANT_ASYNC cant get async fd";
1043 auto asyncPipeReaderPtr = asyncPipeReader.get();
1056 unsigned long lastError = *errErrorOut = ERR_get_error();
1057 VLOG(6) <<
"AsyncSSLSocket(fd=" <<
fd_ <<
", " 1058 <<
"state=" <<
state_ <<
", " 1061 <<
"SSL error: " << error <<
", " 1062 <<
"errno: " << errno <<
", " 1063 <<
"ret: " << ret <<
", " 1064 <<
"read: " << BIO_number_read(SSL_get_rbio(
ssl_.get())) <<
", " 1065 <<
"written: " << BIO_number_written(SSL_get_wbio(
ssl_.get()))
1067 <<
"func: " << ERR_func_error_string(lastError) <<
", " 1068 <<
"reason: " << ERR_reason_error_string(lastError);
1077 if (
ssl_ !=
nullptr && SSL_pending(
ssl_.get()) > 0) {
1085 VLOG(3) <<
"AsyncSSLSocket::restartSSLAccept() this=" <<
this 1086 <<
", fd=" <<
fd_ <<
", state=" << int(
state_) <<
", " 1109 VLOG(3) <<
"AsyncSSLSocket::handleAccept() this=" <<
this <<
", fd=" <<
fd_ 1110 <<
", state=" << int(
state_) <<
", " 1118 }
catch (std::exception& e) {
1122 "error calling SSLContext::createSSL()");
1123 LOG(ERROR) <<
"AsyncSSLSocket::handleAccept(this=" <<
this 1124 <<
", fd=" <<
fd_ <<
"): " << e.what();
1141 SSL_set_msg_callback(
1143 SSL_set_msg_callback_arg(
ssl_.get(),
this);
1146 DCHECK(
ctx_->sslAcceptRunner());
1150 ctx_->sslAcceptRunner()->run(
1151 [
this, dg]() {
return SSL_accept(
ssl_.get()); },
1161 VLOG(3) <<
"SSL_accept returned: " << ret;
1163 unsigned long errError;
1164 int errnoCopy = errno;
1165 if (
willBlock(ret, &sslError, &errError)) {
1181 VLOG(3) <<
"AsyncSSLSocket " <<
this <<
": fd " <<
fd_ 1182 <<
" successfully accepted; state=" << int(
state_)
1210 VLOG(3) <<
"AsyncSSLSocket::handleConnect() this=" <<
this <<
", fd=" <<
fd_ 1211 <<
", state=" << int(
state_) <<
", " 1223 auto originalState =
state_;
1224 int ret = SSL_connect(
ssl_.get());
1227 unsigned long errError;
1228 int errnoCopy = errno;
1229 if (
willBlock(ret, &sslError, &errError)) {
1252 VLOG(3) <<
"AsyncSSLSocket " <<
this <<
": " 1253 <<
"fd " <<
fd_ <<
" successfully connected; " 1284 if (
sslState_ == SSLStateEnum::STATE_CONNECTING) {
1296 if (
sslState_ == SSLStateEnum::STATE_CONNECTING) {
1307 if (
sslState_ == SSLStateEnum::STATE_CONNECTING) {
1320 withAddr(
"failed to schedule AsyncSSLSocket connect timeout"));
1329 #ifdef SSL_MODE_MOVE_BUFFER_OWNERSHIP 1334 ssl_.get(), SSL_get_mode(
ssl_.get()) | SSL_MODE_MOVE_BUFFER_OWNERSHIP);
1358 VLOG(5) <<
"AsyncSSLSocket::handleRead() this=" <<
this <<
", fd=" <<
fd_ 1359 <<
", state=" << int(
state_) <<
", " 1381 VLOG(4) <<
"AsyncSSLSocket::performRead() this=" <<
this <<
", buf=" << *buf
1382 <<
", buflen=" << *buflen;
1390 bytes = SSL_read(
ssl_.get(), *buf, int(*buflen));
1392 #ifdef SSL_MODE_MOVE_BUFFER_OWNERSHIP 1394 bytes = SSL_read_buf(
ssl_.get(), buf, (
int*)offset, (
int*)buflen);
1399 LOG(ERROR) <<
"AsyncSSLSocket(fd=" <<
fd_ <<
", state=" << int(
state_)
1401 <<
"): client intitiated SSL renegotiation not permitted";
1407 int error = SSL_get_error(
ssl_.get(), bytes);
1408 if (error == SSL_ERROR_WANT_READ) {
1410 if (errno == EWOULDBLOCK || errno == EAGAIN) {
1415 }
else if (error == SSL_ERROR_WANT_WRITE) {
1419 LOG(ERROR) <<
"AsyncSSLSocket(fd=" <<
fd_ <<
", state=" << int(
state_)
1421 <<
"): unsupported SSL renegotiation during read";
1426 if (zero_return(error, bytes)) {
1429 auto errError = ERR_get_error();
1430 VLOG(6) <<
"AsyncSSLSocket(fd=" <<
fd_ <<
", " 1431 <<
"state=" <<
state_ <<
", " 1434 <<
"bytes: " << bytes <<
", " 1435 <<
"error: " << error <<
", " 1436 <<
"errno: " << errno <<
", " 1437 <<
"func: " << ERR_func_error_string(errError) <<
", " 1438 <<
"reason: " << ERR_reason_error_string(errError);
1441 std::make_unique<SSLException>(error, errError, bytes, errno));
1450 VLOG(5) <<
"AsyncSSLSocket::handleWrite() this=" <<
this <<
", fd=" <<
fd_ 1451 <<
", state=" << int(
state_) <<
", " 1474 if (error == SSL_ERROR_WANT_READ) {
1478 LOG(ERROR) <<
"AsyncSSLSocket(fd=" <<
fd_ <<
", state=" << int(
state_)
1481 <<
"unsupported SSL renegotiation during write";
1486 if (zero_return(error, rc)) {
1489 auto errError = ERR_get_error();
1490 VLOG(3) <<
"ERROR: AsyncSSLSocket(fd=" <<
fd_ <<
", state=" << int(
state_)
1492 <<
"SSL error: " << error <<
", errno: " << errno
1493 <<
", func: " << ERR_func_error_string(errError)
1494 <<
", reason: " << ERR_reason_error_string(errError);
1497 std::make_unique<SSLException>(error, errError, rc, errno));
1509 vec, count, flags, countWritten, partialWritten);
1512 LOG(ERROR) <<
"AsyncSSLSocket(fd=" <<
fd_ <<
", state=" << int(
state_)
1515 <<
"TODO: AsyncSSLSocket currently does not support calling " 1516 <<
"write() before the handshake has fully completed";
1524 char* combinedBuf{
nullptr};
1527 if (combinedBuf !=
nullptr &&
minWriteSize_ > MAX_STACK_BUF_SIZE) {
1528 delete[] combinedBuf;
1533 *partialWritten = 0;
1534 ssize_t totalWritten = 0;
1535 size_t bytesStolenFromNextBuffer = 0;
1537 const iovec*
v = vec +
i;
1538 size_t offset = bytesStolenFromNextBuffer;
1539 bytesStolenFromNextBuffer = 0;
1540 size_t len = v->iov_len - offset;
1546 buf = ((
const char*)v->iov_base) + offset;
1550 auto sslWriteBuf = buf;
1561 if (combinedBuf ==
nullptr) {
1570 assert(combinedBuf !=
nullptr);
1571 sslWriteBuf = combinedBuf;
1573 memcpy(combinedBuf, buf, len);
1576 uint32_t nextIndex = i + buffersStolen + 1;
1577 bytesStolenFromNextBuffer =
1579 if (bytesStolenFromNextBuffer > 0) {
1580 assert(vec[nextIndex].iov_base !=
nullptr);
1583 vec[nextIndex].iov_base,
1584 bytesStolenFromNextBuffer);
1586 len += bytesStolenFromNextBuffer;
1587 if (bytesStolenFromNextBuffer < vec[nextIndex].iov_len) {
1591 bytesStolenFromNextBuffer = 0;
1594 }
while ((i + buffersStolen + 1) < count && (len <
minWriteSize_));
1598 if (bytesStolenFromNextBuffer == 0) {
1599 while ((i + buffersStolen + 1) < count &&
1600 vec[i + buffersStolen + 1].iov_len == 0) {
1614 int error = SSL_get_error(
ssl_.get(), int(bytes));
1615 if (error == SSL_ERROR_WANT_WRITE) {
1617 *partialWritten =
uint32_t(offset);
1621 if (writeResult.writeReturn < 0) {
1626 totalWritten += bytes;
1628 if (bytes == (ssize_t)len) {
1630 (*countWritten) += 1 + buffersStolen;
1635 while (bytes >= (ssize_t)v->iov_len) {
1639 bytes -= v->iov_len;
1691 if (where & SSL_CB_READ_ALERT) {
1692 const char*
type = SSL_alert_type_string(ret);
1694 const char* desc = SSL_alert_desc_string(ret);
1706 iov.iov_base =
const_cast<char*
>(in);
1707 iov.iov_len = size_t(inl);
1708 memset(&msg, 0,
sizeof(msg));
1719 if (tsslSock->isEorTrackingEnabled() && tsslSock->minEorRawByteNo_ &&
1720 tsslSock->minEorRawByteNo_ <= BIO_number_written(b) + inl) {
1724 if (tsslSock->corkCurrentWrite_) {
1728 int msg_flags = tsslSock->getSendMsgParamsCB()->getFlags(
1730 msg.msg_controllen =
1731 tsslSock->getSendMsgParamsCB()->getAncillaryDataSize(flags);
1734 msg.msg_controllen);
1735 if (msg.msg_controllen != 0) {
1736 msg.msg_control =
reinterpret_cast<char*
>(alloca(msg.msg_controllen));
1737 tsslSock->getSendMsgParamsCB()->getAncillaryData(flags, msg.msg_control);
1740 auto result = tsslSock->sendSocketMessage(
1742 BIO_clear_retry_flags(b);
1743 if (!result.exception && result.writeReturn <= 0) {
1745 BIO_set_retry_write(b);
1748 return int(result.writeReturn);
1755 BIO_clear_retry_flags(b);
1761 if (sslSock->preReceivedData_ && !sslSock->preReceivedData_->empty()) {
1762 VLOG(5) <<
"AsyncSSLSocket::bioRead() this=" << sslSock
1763 <<
", reading pre-received data";
1765 Cursor cursor(sslSock->preReceivedData_.get());
1771 sslSock->preReceivedData_ = queue.
move();
1772 return static_cast<int>(len);
1776 BIO_set_retry_read(b);
1784 X509_STORE_CTX* x509Ctx) {
1785 SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(
1786 x509Ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
1789 VLOG(3) <<
"AsyncSSLSocket::sslVerifyCallback() this=" <<
self <<
", " 1790 <<
"fd=" <<
self->fd_ <<
", preverifyOk=" << preverifyOk;
1791 return (self->handshakeCallback_)
1792 ?
self->handshakeCallback_->handshakeVer(
self, preverifyOk, x509Ctx)
1802 SSL_set_msg_callback(ssl,
nullptr);
1803 SSL_set_msg_callback_arg(ssl,
nullptr);
1820 if (contentType != SSL3_RT_HANDSHAKE) {
1830 Cursor cursor(clientHelloBuf.front());
1831 if (cursor.read<
uint8_t>() != SSL3_MT_CLIENT_HELLO) {
1836 if (cursor.totalLength() < 3) {
1837 clientHelloBuf.trimEnd(len);
1843 messageLength <<= 8;
1844 messageLength |= cursor.read<
uint8_t>();
1845 messageLength <<= 8;
1846 messageLength |= cursor.read<
uint8_t>();
1847 if (cursor.totalLength() < messageLength) {
1848 clientHelloBuf.trimEnd(len);
1859 cursor.skip(cursor.read<
uint8_t>());
1862 for (
int i = 0;
i < cipherSuitesLength;
i += 2) {
1868 for (
int i = 0;
i < compressionMethodsLength; ++
i) {
1873 if (cursor.totalLength() > 0) {
1875 while (extensionsLength) {
1879 extensionsLength -= 2;
1881 extensionsLength -= 2;
1882 extensionsLength -= extensionDataLength;
1886 extensionDataLength -= 2;
1887 while (extensionDataLength) {
1892 extensionDataLength -= 2;
1898 extensionDataLength -= 1;
1899 while (extensionDataLength) {
1902 extensionDataLength -= 2;
1905 cursor.skip(extensionDataLength);
1909 }
catch (std::out_of_range&) {
1911 VLOG(4) <<
"AsyncSSLSocket::clientHelloParsingCallback(): " 1912 <<
"buffer finished unexpectedly." 1913 <<
" AsyncSSLSocket socket=" << sock;
1921 bool convertToString)
const {
1931 for (
auto originalCipherCode :
clientHelloInfo_->clientHelloCipherSuites_) {
1938 bool nameFound = convertToString;
1940 if (convertToString) {
1951 std::array<uint8_t, 2>{
1952 {
static_cast<uint8_t>((originalCipherCode >> 8) & 0xffL),
1953 static_cast<uint8_t>(originalCipherCode & 0x00ffL)}},
1985 sigAlgs.push_back(
':');
1989 sigAlgs.push_back(
',');
1990 sigAlgs.append(folly::to<std::string>(
2011 ret.append(folly::to<std::string>(alert.first,
": ", alert.second));
2026 char ciphersBuffer[1024];
2027 ciphersBuffer[0] =
'\0';
2028 SSL_get_shared_ciphers(
ssl_.get(), ciphersBuffer,
sizeof(ciphersBuffer) - 1);
2029 sharedCiphers = ciphersBuffer;
2033 serverCiphers = SSL_get_cipher_list(
ssl_.get(), 0);
2036 while ((cipher = SSL_get_cipher_list(
ssl_.get(),
i)) !=
nullptr) {
2037 serverCiphers.append(
":");
2038 serverCiphers.append(cipher);
void applyVerificationOptions(const ssl::SSLUniquePtr &ssl)
static std::string getCommonName(X509 *x509)
bool good() const override
size_t getRawBytesReceived() const override
void checkForImmediateRead() noexceptoverride
static SSL_CTX * getSSLInitialCtx(SSL *ssl)
bool sessionResumptionAttempted_
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
ReadResult performRead(void **buf, size_t *buflen, size_t *offset) override
void invokeHandshakeErr(const AsyncSocketException &ex)
bool connecting() const override
static bool setCustomBioReadMethod(BIO_METHOD *bioMeth, int(*meth)(BIO *, char *, int))
virtual int getVerificationMode()
void enableClientHelloParsing()
std::unique_ptr< ReadCallback > asyncOperationFinishCallback_
std::string withAddr(const std::string &s)
std::unique_ptr< X509, X509Deleter > X509UniquePtr
void handleRead() noexceptoverride
WriteResult interpretSSLError(int rc, int error)
bool connecting() const override
static std::unique_ptr< IOBuf > wrapBuffer(const void *buf, std::size_t capacity)
static UniquePtr newReader(Args &&...args)
static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX *ctx)
static int bioRead(BIO *b, char *out, int outl)
static const char * getSSLServerNameFromSSL(SSL *ssl)
std::string sformat(StringPiece fmt, Args &&...args)
virtual WriteResult performWrite(const iovec *vec, uint32_t count, WriteFlags flags, uint32_t *countWritten, uint32_t *partialWritten)
folly::SSLContext::SSLVerifyPeerEnum verifyPeer_
std::unique_ptr< const AsyncTransportCertificate > peerCertData_
void setEorTracking(bool track) override
void connect(ConnectCallback *callback, const folly::SocketAddress &address, int timeout=0, const OptionMap &options=emptyOptionMap, const folly::SocketAddress &bindAddr=anyAddress()) noexceptoverride
const char * getSSLCertSigAlgName() const
size_t getRawBytesWritten() const override
bool willBlock(int ret, int *sslErrorOut, unsigned long *errErrorOut) noexcept
std::string getSSLClientComprMethods() const
std::string getSSLClientSupportedVersions() const
const AsyncTransportCertificate * getPeerCertificate() const override
const X509 * getSelfCert() const override
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
static void * getBioAppData(BIO *b)
virtual void sslAccept(HandshakeCB *callback, std::chrono::milliseconds timeout=std::chrono::milliseconds::zero(), const folly::SSLContext::SSLVerifyPeerEnum &verifyPeer=folly::SSLContext::SSLVerifyPeerEnum::USE_CTX)
virtual void handleConnect() noexcept
WriteResult performWrite(const iovec *vec, uint32_t count, WriteFlags flags, uint32_t *countWritten, uint32_t *partialWritten) override
bool renegotiateAttempted_
SpinLockGuardImpl< SpinLock > SpinLockGuard
virtual bool isBufferMovable() noexcept
virtual void sslConn(HandshakeCB *callback, std::chrono::milliseconds timeout=std::chrono::milliseconds::zero(), const folly::SSLContext::SSLVerifyPeerEnum &verifyPeer=folly::SSLContext::SSLVerifyPeerEnum::USE_CTX)
std::chrono::milliseconds handshakeConnectTimeout_
SSL_SESSION * sslSession_
const char * getSSLServerName() const
std::unique_ptr< folly::IOBuf > move()
bool bufferMovableEnabled_
void shutdownWrite() override
std::string sslVerificationAlert_
size_t pullAtMost(void *buf, size_t len)
—— Concurrent Priority Queue Implementation ——
EventBase * eventBase_
The EventBase.
~AsyncSSLSocket() override
requires E e noexcept(noexcept(s.error(std::move(e))))
bool updateEventRegistration()
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
std::shared_ptr< FizzServerContext > ctx_
Timeout handshakeTimeout_
std::chrono::milliseconds connectTimeout_
bool isSet(WriteFlags a, WriteFlags b)
virtual void connect(ConnectCallback *callback, const folly::SocketAddress &address, int timeout=0, const OptionMap &options=emptyOptionMap, const folly::SocketAddress &bindAddr=anyAddress()) noexcept
bool needsPeerVerification() const
std::shared_ptr< folly::SSLContext > ctx_
void scheduleConnectTimeout() override
void setReadCB(ReadCallback *callback) override
virtual void handleRead() noexcept
void handleWrite() noexceptoverride
static void setSSLInitialCtx(SSL *ssl, SSL_CTX *ctx)
std::chrono::milliseconds totalConnectTimeout_
std::map< OptionKey, int > OptionMap
SSL_CTX * getSSLCtx() const
static void setBioFd(BIO *b, int fd, int flags)
size_t appBytesReceived_
Num of bytes received from socket.
static const size_t maxAncillaryDataSize
void invokeConnectSuccess() override
virtual void getReadBuffer(void **bufReturn, size_t *lenReturn)=0
AsyncSSLSocket::UniquePtr sslSocket_
uint16_t eventFlags_
EventBase::HandlerFlags settings.
void handleReturnFromSSLAccept(int ret)
GuardImpl guard(ErrorHandler &&handler)
std::string getSSLCertVerificationAlert() const
void setEorTracking(bool track) override
bool good() const override
static void clientHelloParsingCallback(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
std::unique_ptr< const AsyncTransportCertificate > selfCertData_
static int getBioFd(BIO *b, int *fd)
void invokeConnectErr(const AsyncSocketException &ex) override
void timeoutExpired() noexcept
Timeout connectionTimeout_
static bool setCustomBioWriteMethod(BIO_METHOD *bioMeth, int(*meth)(BIO *, const char *, int))
virtual int getFd() const
bool isEorTrackingEnabled() const override
void getSSLClientCiphers(std::string &clientCiphers, bool convertToString=true) const
static BioMethodUniquePtr newSocketBioMethod()
void setBufferMovableEnabled(bool enabled)
virtual ReadResult performRead(void **buf, size_t *buflen, size_t *offset)
virtual bool getSSLSessionReused() const
virtual void handleWrite() noexcept
void getSSLSharedCiphers(std::string &sharedCiphers) const
void dcheckIsInEventBaseThread() const
const char * SSL_SESSION_get0_hostname(const SSL_SESSION *s)
virtual void handshakeSuc(AsyncSSLSocket *sock) noexcept=0
void prepareReadBuffer(void **buf, size_t *buflen) override
virtual void scheduleConnectTimeout()
static int getBioShouldRetryWrite(int ret)
void handleConnect() noexceptoverride
virtual void handshakeErr(AsyncSSLSocket *sock, const AsyncSocketException &ex) noexcept=0
void setSSLCertVerificationAlert(std::string alert)
ReadCallback * readCallback_
ReadCallback.
virtual bool getSelectedNextProtocolNoThrow(const unsigned char **protoName, unsigned *protoLen) const
std::vector< std::pair< char, StringPiece > > alertsReceived_
std::unique_ptr< ssl::ClientHelloInfo > clientHelloInfo_
std::string getSSLClientExts() const
void setReadCB(ReadCallback *callback) override
void getSSLServerCiphers(std::string &serverCiphers) const
AsyncSSLSocket(const std::shared_ptr< folly::SSLContext > &ctx, EventBase *evb, bool deferSecurityNegotiation=false)
std::chrono::steady_clock::time_point handshakeEndTime_
std::string getSSLClientSigAlgs() const
SSL_SESSION * getSSLSession()
StateEnum state_
StateEnum describing current state.
int bind(NetworkSocket s, const sockaddr *name, socklen_t namelen)
void resetClientHelloParsing(SSL *ssl)
virtual void invokeConnectSuccess()
EventBase * getEventBase() const override
static void setBioAppData(BIO *b, void *ptr)
void trimStart(size_t amount)
int fd_
The socket file descriptor.
void setSSLSession(SSL_SESSION *session, bool takeOwnership=false)
void join(const Delim &delimiter, Iterator begin, Iterator end, String &output)
HandshakeCB * handshakeCallback_
std::string getSSLAlertsReceived() const
folly::Function< void()> callback_
void failHandshake(const char *fn, const AsyncSocketException &ex)
int eorAwareSSLWrite(const ssl::SSLUniquePtr &ssl, const void *buf, int n, bool eor)
void invalidState(HandshakeCB *callback)
std::chrono::steady_clock::time_point handshakeStartTime_
virtual void checkForImmediateRead() noexcept
bool scheduleTimeout(TimeoutManager::timeout_type timeout)
ssize_t recv(NetworkSocket s, void *buf, size_t len, int flags)
std::string getApplicationProtocol() const noexceptoverride
virtual void handleInitialReadWrite() noexcept
const SSL * getSSL() const
const AsyncTransportCertificate * getSelfCertificate() const override
Range< const char * > StringPiece
bool hexlify(const InputString &input, OutputString &output, bool append_output)
static int bioWrite(BIO *b, const char *in, int inl)
int getSSLCertSize() const
static std::unique_ptr< IOBuf > copyBuffer(const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
int getSSLVersion() const
virtual const char * getNegotiatedCipherName() const
void shutdownWriteNow() override
static void sslInfoCallback(const SSL *ssl, int type, int val)
size_t appBytesWritten_
Num of bytes written to socket.
static AsyncSSLSocket * getFromSSL(const SSL *ssl)
static const std::string & getCipherName(uint16_t cipherCode)
std::unique_ptr< AsyncSocket, Destructor > UniquePtr
static int getSSLExDataIndex()
virtual void invokeConnectErr(const AsyncSocketException &ex)
const char * getSSLServerNameNoThrow() const
ConnectCallback * connectCallback_
ConnectCallback.
virtual int sslWriteImpl(SSL *ssl, const void *buf, int n)
virtual void getSelectedNextProtocol(const unsigned char **protoName, unsigned *protoLen) const
void handleAccept() noexcept
std::unique_ptr< SSL, SSLDeleter > SSLUniquePtr
constexpr detail::First first