folly/folly/io/async/AsyncSSLSocket.cpp

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/io/async/AsyncSSLSocket.h>

#include <fcntl.h>
#include <sys/types.h>

#include <cerrno>
#include <chrono>
#include <memory>
#include <utility>

#include <folly/Format.h>
#include <folly/Indestructible.h>
#include <folly/SocketAddress.h>
#include <folly/SpinLock.h>
#include <folly/io/Cursor.h>
#include <folly/io/IOBuf.h>
#include <folly/io/SocketOptionMap.h>
#include <folly/io/async/EventBase.h>
#include <folly/io/async/ssl/BasicTransportCertificate.h>
#include <folly/lang/Bits.h>
#include <folly/portability/OpenSSL.h>
#include <folly/portability/Sockets.h>
#include <folly/ssl/SSLSession.h>
#include <folly/ssl/SSLSessionManager.h>

shared_ptr;

SpinLock;
Cursor;
SSLSessionUniquePtr;

namespace {
AsyncSSLSocket;
SSLContext;
// For OpenSSL portability API
usingnamespacefolly::ssl;
OpenSSLUtils;

// We have one single dummy SSL context so that we can implement attach
// and detach methods in a thread safe fashion without modifying opnessl.
SSLContext* dummyCtx =;
SpinLock dummyCtxLock;

// If given min write size is less than this, buffer will be allocated on
// stack, otherwise it is allocated on heap
const size_t MAX_STACK_BUF_SIZE =;

void setup_SSL_CTX(SSL_CTX* ctx) {}

// Note: This is a Leaky Meyer's Singleton. The reason we can't use a non-leaky
// thing is because we will be setting this BIO_METHOD* inside BIOs owned by
// various SSL objects which may get callbacks even during teardown. We may
// eventually try to fix this
BIO_METHOD* getSSLBioMethod() {}

void* initsslBioMethod() {}

} // namespace

namespace folly {

class AsyncSSLSocketConnector : public AsyncSocket::ConnectCallback,
                                public AsyncSSLSocket::HandshakeCB {};

AsyncSSLSocket::AsyncSSLSocket(
    shared_ptr<const SSLContext> ctx, EventBase* evb, Options&& options)
    :{}

AsyncSSLSocket::AsyncSSLSocket(
    std::shared_ptr<const folly::SSLContext> ctx,
    AsyncSocket::UniquePtr oldAsyncSocket,
    Options&& options)
    :{}

/**
 * Create a client AsyncSSLSocket
 */
AsyncSSLSocket::AsyncSSLSocket(
    shared_ptr<const SSLContext> ctx,
    EventBase* evb,
    bool deferSecurityNegotiation)
    :{}

/**
 * Create a server/client AsyncSSLSocket
 */
AsyncSSLSocket::AsyncSSLSocket(
    shared_ptr<const SSLContext> ctx,
    EventBase* evb,
    NetworkSocket fd,
    bool server,
    bool deferSecurityNegotiation,
    const SocketAddress* peerAddress)
    :{}

AsyncSSLSocket::AsyncSSLSocket(
    shared_ptr<const SSLContext> ctx,
    AsyncSocket* oldAsyncSocket,
    bool server,
    bool deferSecurityNegotiation)
    :{}

AsyncSSLSocket::AsyncSSLSocket(
    shared_ptr<const SSLContext> ctx,
    AsyncSocket::UniquePtr oldAsyncSocket,
    bool server,
    bool deferSecurityNegotiation)
    :{}

/**
 * Create a client AsyncSSLSocket and allow tlsext_hostname
 * to be sent in Client Hello.
 */
AsyncSSLSocket::AsyncSSLSocket(
    const shared_ptr<const SSLContext>& ctx,
    EventBase* evb,
    const std::string& serverName,
    bool deferSecurityNegotiation)
    :{}

/**
 * Create a client AsyncSSLSocket from an already connected fd
 * and allow tlsext_hostname to be sent in Client Hello.
 */
AsyncSSLSocket::AsyncSSLSocket(
    const shared_ptr<const SSLContext>& ctx,
    EventBase* evb,
    NetworkSocket fd,
    const std::string& serverName,
    bool deferSecurityNegotiation,
    const SocketAddress* peerAddress)
    :{}

AsyncSSLSocket::~AsyncSSLSocket() {}

void AsyncSSLSocket::init() {}

void AsyncSSLSocket::closeNow() {}

void AsyncSSLSocket::shutdownWrite() {}

void AsyncSSLSocket::shutdownWriteNow() {}

bool AsyncSSLSocket::readable() const {}

bool AsyncSSLSocket::good() const {}

// The AsyncTransport definition of 'good' states that the transport is
// ready to perform reads and writes, so sslState_ == UNINIT must report !good.
// connecting can be true when the sslState_ == UNINIT because the AsyncSocket
// is connected but we haven't initiated the call to SSL_connect.
bool AsyncSSLSocket::connecting() const {}

std::string AsyncSSLSocket::getApplicationProtocol() const noexcept {}

std::unique_ptr<IOBuf> AsyncSSLSocket::getExportedKeyingMaterial(
    folly::StringPiece label,
    std::unique_ptr<IOBuf> context,
    uint16_t length) const {}

void AsyncSSLSocket::setSupportedApplicationProtocols(
    const std::vector<std::string>& supportedProtocols) {}

void AsyncSSLSocket::setEorTracking(bool track) {}

size_t AsyncSSLSocket::getRawBytesWritten() const {}

size_t AsyncSSLSocket::getRawBytesReceived() const {}

void AsyncSSLSocket::invalidState(HandshakeCB* callback) {}

void AsyncSSLSocket::sslAccept(
    HandshakeCB* callback,
    std::chrono::milliseconds timeout,
    const SSLContext::SSLVerifyPeerEnum& verifyPeer) {}

void AsyncSSLSocket::attachSSLContext(
    const std::shared_ptr<const SSLContext>& ctx) {}

void AsyncSSLSocket::detachSSLContext() {}

void AsyncSSLSocket::switchServerSSLContext(
    const std::shared_ptr<const SSLContext>& handshakeCtx) {}

bool AsyncSSLSocket::isServerNameMatch() const {}

void AsyncSSLSocket::setServerName(std::string serverName) noexcept {}

void AsyncSSLSocket::timeoutExpired(
    std::chrono::milliseconds timeout) noexcept {}

int AsyncSSLSocket::getSSLExDataIndex() {}

AsyncSSLSocket* AsyncSSLSocket::getFromSSL(const SSL* ssl) {}

void AsyncSSLSocket::failHandshake(
    const char* /* fn */, const AsyncSocketException& ex) {}

void AsyncSSLSocket::invokeHandshakeErr(const AsyncSocketException& ex) {}

void AsyncSSLSocket::invokeHandshakeCB() {}

void AsyncSSLSocket::connect(
    ConnectCallback* callback,
    const folly::SocketAddress& address,
    int timeout,
    const SocketOptionMap& options,
    const folly::SocketAddress& bindAddr,
    const std::string& ifName) noexcept {}

void AsyncSSLSocket::connect(
    ConnectCallback* callback,
    const folly::SocketAddress& address,
    std::chrono::milliseconds connectTimeout,
    std::chrono::milliseconds totalConnectTimeout,
    const SocketOptionMap& options,
    const folly::SocketAddress& bindAddr,
    const std::string& ifName) noexcept {}

void AsyncSSLSocket::cancelConnect() {}

bool AsyncSSLSocket::needsPeerVerification() const {}

bool AsyncSSLSocket::applyVerificationOptions(const ssl::SSLUniquePtr& ssl) {}

bool AsyncSSLSocket::setupSSLBio() {}

void AsyncSSLSocket::sslConn(
    HandshakeCB* callback,
    std::chrono::milliseconds timeout,
    const SSLContext::SSLVerifyPeerEnum& verifyPeer) {}

// This could be called multiple times, during normal ssl connections
// and after TFO fallback.
void AsyncSSLSocket::startSSLConnect() {}

shared_ptr<ssl::SSLSession> AsyncSSLSocket::getSSLSession() {}

const SSL* AsyncSSLSocket::getSSL() const {}

void AsyncSSLSocket::setSSLSession(shared_ptr<ssl::SSLSession> session) {}

void AsyncSSLSocket::setRawSSLSession(SSLSessionUniquePtr session) {}

void AsyncSSLSocket::getSelectedNextProtocol(
    const unsigned char** protoName, unsigned* protoLen) const {}

bool AsyncSSLSocket::getSelectedNextProtocolNoThrow(
    const unsigned char** protoName, unsigned* protoLen) const {}

bool AsyncSSLSocket::getSSLSessionReused() const {}

const char* AsyncSSLSocket::getNegotiatedCipherName() const {}

/* static */
const char* AsyncSSLSocket::getSSLServerNameFromSSL(SSL* ssl) {}

const char* AsyncSSLSocket::getSSLServerName() const {}

const char* AsyncSSLSocket::getSSLServerNameNoThrow() const {}

int AsyncSSLSocket::getSSLVersion() const {}

const char* AsyncSSLSocket::getSSLCertSigAlgName() const {}

int AsyncSSLSocket::getSSLCertSize() const {}

const AsyncTransportCertificate* AsyncSSLSocket::getPeerCertificate() const {}

const AsyncTransportCertificate* AsyncSSLSocket::getSelfCertificate() const {}

bool AsyncSSLSocket::willBlock(
    int ret, int* sslErrorOut, unsigned long* errErrorOut) noexcept {}

void AsyncSSLSocket::checkForImmediateRead() noexcept {}

void AsyncSSLSocket::restartSSLAccept() {}

void AsyncSSLSocket::handleAccept() noexcept {}

const char* AsyncSSLSocket::getNegotiatedGroup() const {}

void AsyncSSLSocket::handleReturnFromSSLAccept(int ret) {}

void AsyncSSLSocket::handleConnect() noexcept {}

void AsyncSSLSocket::invokeConnectErr(const AsyncSocketException& ex) {}

void AsyncSSLSocket::invokeConnectSuccess() {}

void AsyncSSLSocket::scheduleConnectTimeout() {}

void AsyncSSLSocket::handleRead() noexcept {}

AsyncSocket::ReadResult AsyncSSLSocket::performReadSingle(
    void* buf, const size_t buflen) {}

AsyncSocket::ReadResult AsyncSSLSocket::performReadMsg(
    struct ::msghdr& msg, AsyncReader::ReadCallback::ReadMode readMode) {}

void AsyncSSLSocket::handleWrite() noexcept {}

AsyncSocket::WriteResult AsyncSSLSocket::interpretSSLError(int rc, int error) {}

AsyncSocket::WriteResult AsyncSSLSocket::performWrite(
    const iovec* vec,
    uint32_t count,
    WriteFlags flags,
    uint32_t* countWritten,
    uint32_t* partialWritten,
    WriteRequestTag writeTag) {}

void AsyncSSLSocket::sslInfoCallback(const SSL* ssl, int where, int ret) {}

int AsyncSSLSocket::bioWrite(BIO* b, const char* in, int inl) {}

int AsyncSSLSocket::bioRead(BIO* b, char* out, int outl) {}

int AsyncSSLSocket::sslVerifyCallback(
    int preverifyOk, X509_STORE_CTX* x509Ctx) {}

void AsyncSSLSocket::enableByteEvents() {}

void AsyncSSLSocket::enableClientHelloParsing() {}

void AsyncSSLSocket::resetClientHelloParsing(SSL* ssl) {}

void AsyncSSLSocket::parseClientAlpns(
    AsyncSSLSocket* sock,
    folly::io::Cursor& cursor,
    uint16_t& extensionDataLength) {}

void AsyncSSLSocket::clientHelloParsingCallback(
    int written,
    int /* version */,
    int contentType,
    const void* buf,
    size_t len,
    SSL* ssl,
    void* arg) {}

void AsyncSSLSocket::getSSLClientCiphers(
    std::string& clientCiphers, bool convertToString) const {}

std::string AsyncSSLSocket::getSSLClientComprMethods() const {}

std::string AsyncSSLSocket::getSSLClientExts() const {}

std::string AsyncSSLSocket::getSSLClientSigAlgs() const {}

std::string AsyncSSLSocket::getSSLClientSupportedVersions() const {}

std::string AsyncSSLSocket::getSSLAlertsReceived() const {}

void AsyncSSLSocket::setSSLCertVerificationAlert(std::string alert) {}

std::string AsyncSSLSocket::getSSLCertVerificationAlert() const {}

void AsyncSSLSocket::getSSLSharedCiphers(std::string& sharedCiphers) const {}

void AsyncSSLSocket::getSSLServerCiphers(std::string& serverCiphers) const {}

const std::vector<std::string>& AsyncSSLSocket::getClientAlpns() const {}

} // namespace folly