Skip to content

Commit

Permalink
New function SSLServer::update_certs. Allows to update certificates w…
Browse files Browse the repository at this point in the history
…hile server is running (#1827)

* New function SSLServer::update_certs. Allows to update certificates while server is running

* New function SSLServer::update_certs. Added unit test

---------

Co-authored-by: CEU\schielke <[email protected]>
  • Loading branch information
RainerSchielke and CEU\schielke committed Jun 3, 2024
1 parent 98cc1ec commit d440316
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
16 changes: 16 additions & 0 deletions httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1819,6 +1819,9 @@ class SSLServer : public Server {
bool is_valid() const override;

SSL_CTX *ssl_context() const;

void update_certs (X509 *cert, EVP_PKEY *private_key,
X509_STORE *client_ca_cert_store = nullptr);

private:
bool process_and_close_socket(socket_t sock) override;
Expand Down Expand Up @@ -8753,6 +8756,19 @@ inline bool SSLServer::is_valid() const { return ctx_; }

inline SSL_CTX *SSLServer::ssl_context() const { return ctx_; }

inline void SSLServer::update_certs (X509 *cert, EVP_PKEY *private_key,
X509_STORE *client_ca_cert_store) {

std::lock_guard<std::mutex> guard(ctx_mutex_);

SSL_CTX_use_certificate (ctx_, cert);
SSL_CTX_use_PrivateKey (ctx_, private_key);

if (client_ca_cert_store != nullptr) {
SSL_CTX_set_cert_store (ctx_, client_ca_cert_store);
}
}

inline bool SSLServer::process_and_close_socket(socket_t sock) {
auto ssl = detail::ssl_new(
sock, ctx_, ctx_mutex_,
Expand Down
58 changes: 58 additions & 0 deletions test/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,64 @@ TEST(BindServerTest, BindAndListenSeparatelySSLEncryptedKey) {
}
#endif

#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
X509* readCertificate (const std::string& strFileName) {
std::ifstream inStream (strFileName);
std::string strCertPEM ((std::istreambuf_iterator<char>(inStream)), std::istreambuf_iterator<char>());

if (strCertPEM.empty ()) return (nullptr);

BIO* pbCert = BIO_new (BIO_s_mem ());
BIO_write (pbCert, strCertPEM.c_str (), (int)strCertPEM.size ());
X509* pCert = PEM_read_bio_X509 (pbCert, NULL, 0, NULL);
BIO_free (pbCert);

return (pCert);
}

EVP_PKEY* readPrivateKey (const std::string& strFileName) {
std::ifstream inStream (strFileName);
std::string strPrivateKeyPEM ((std::istreambuf_iterator<char>(inStream)), std::istreambuf_iterator<char>());

if (strPrivateKeyPEM.empty ()) return (nullptr);

BIO* pbPrivKey = BIO_new (BIO_s_mem ());
BIO_write (pbPrivKey, strPrivateKeyPEM.c_str (), (int) strPrivateKeyPEM.size ());
EVP_PKEY* pPrivateKey = PEM_read_bio_PrivateKey (pbPrivKey, NULL, NULL, NULL);
BIO_free (pbPrivKey);

return (pPrivateKey);
}

TEST(BindServerTest, UpdateCerts) {
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, CLIENT_CA_CERT_FILE);
int port = svr.bind_to_any_port("0.0.0.0");
ASSERT_TRUE(svr.is_valid());
ASSERT_TRUE(port > 0);

X509* cert = readCertificate (SERVER_CERT_FILE);
X509* ca_cert = readCertificate (CLIENT_CA_CERT_FILE);
EVP_PKEY* key = readPrivateKey (SERVER_PRIVATE_KEY_FILE);

ASSERT_TRUE(cert != nullptr);
ASSERT_TRUE(ca_cert != nullptr);
ASSERT_TRUE(key != nullptr);

X509_STORE* cert_store = X509_STORE_new ();

X509_STORE_add_cert (cert_store, ca_cert);

svr.update_certs (cert, key, cert_store);

ASSERT_TRUE(svr.is_valid());
svr.stop();

X509_free (cert);
X509_free (ca_cert);
EVP_PKEY_free (key);
}
#endif

TEST(ErrorHandlerTest, ContentLength) {
Server svr;

Expand Down

0 comments on commit d440316

Please sign in to comment.