blob: 9e2ce575003a3a651eeb9629d2397825c2b3f907 [file] [log] [blame]
#include <https/BufferedSocket.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <memory>
struct SSLSocket
: public BufferedSocket,
public std::enable_shared_from_this<SSLSocket> {
static void Init();
enum {
// Client only.
FLAG_DONT_CHECK_PEER_CERTIFICATE = 1,
};
explicit SSLSocket(
std::shared_ptr<RunLoop> rl,
int sock,
const std::string &certificate_pem_path,
const std::string &private_key_pem_path,
uint32_t flags = 0);
explicit SSLSocket(
std::shared_ptr<RunLoop> rl,
int sock,
uint32_t flags = 0,
const std::optional<std::string> &trusted_pem_path = std::nullopt);
~SSLSocket() override;
SSLSocket(const SSLSocket &) = delete;
SSLSocket &operator=(const SSLSocket &) = delete;
void postRecv(RunLoop::AsyncFunction fn) override;
void postSend(RunLoop::AsyncFunction fn) override;
ssize_t recvfrom(
void *data,
size_t size,
sockaddr *address,
socklen_t *addressLen) override;
ssize_t sendto(
const void *data,
size_t size,
const sockaddr *addr,
socklen_t addrLen) override;
void postFlush(RunLoop::AsyncFunction fn) override;
private:
enum class Mode {
CONNECT,
ACCEPT,
};
Mode mMode;
uint32_t mFlags;
std::unique_ptr<SSL_CTX, std::function<void(SSL_CTX *)>> mCtx;
std::unique_ptr<SSL, std::function<void(SSL *)>> mSSL;
// These are owned by the SSL object.
BIO *mBioR;
BIO *mBioW;
bool mEOS;
int mFinalErrno;
bool mRecvPending;
RunLoop::AsyncFunction mRecvCallback;
bool mSendPending;
std::vector<uint8_t> mOutBuffer;
// This is as yet unencrypted data that has yet to be submitted to SSL_write.
std::vector<uint8_t> mOutBufferPlain;
RunLoop::AsyncFunction mFlushFn;
explicit SSLSocket(
std::shared_ptr<RunLoop> rl, Mode mode, int sock, uint32_t flags);
void handleIncomingData();
void sendRecvCallback();
void queueOutputDataFromSSL();
void queueOutputData(const void *data, size_t size);
void sendOutputData();
void drainOutputBufferPlain();
bool isPeerCertificateValid();
static SSL_CTX *CreateSSLContext();
bool useCertificate(const std::string &path);
bool usePrivateKey(const std::string &path);
bool useTrustedCertificates(const std::string &path);
};