Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/majordomo/include/majordomo/RestServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ inline int alpn_select_proto_cb(SSL * /*ssl*/, const unsigned char **out, unsign
return SSL_TLSEXT_ERR_OK;
}

inline std::expected<SSL_CTX_Ptr, std::string> create_ssl_ctx(EVP_PKEY *key, X509 *cert) {
inline std::expected<SSL_CTX_Ptr, std::string> create_ssl_ctx(EVP_PKEY *key, std::span<X509_Ptr> cert) {
auto ssl_ctx = SSL_CTX_Ptr(SSL_CTX_new(TLS_server_method()), SSL_CTX_free);
if (!ssl_ctx) {
return std::unexpected(std::format("Could not create SSL/TLS context: {}", ERR_error_string(ERR_get_error(), nullptr)));
Expand All @@ -236,9 +236,16 @@ inline std::expected<SSL_CTX_Ptr, std::string> create_ssl_ctx(EVP_PKEY *key, X50
if (SSL_CTX_use_PrivateKey(ssl_ctx.get(), key) <= 0) {
return std::unexpected(std::format("Could not configure private key"));
}
if (SSL_CTX_use_certificate(ssl_ctx.get(), cert) != 1) {
if (SSL_CTX_use_certificate(ssl_ctx.get(), cert[0].get()) != 1) {
return std::unexpected(std::format("Could not configure certificate file"));
}
if (cert.size() > 1) {
for (std::size_t i = 1; i < cert.size(); ++i) {
if (SSL_CTX_add_extra_chain_cert(ssl_ctx.get(), cert[i].get()) != 1) {
return std::unexpected(std::format("Could not add certificate chain file {}", i));
}
}
}

if (!SSL_CTX_check_private_key(ssl_ctx.get())) {
return std::unexpected("Private key does not match the certificate");
Expand Down Expand Up @@ -2211,7 +2218,7 @@ struct RestServer {
Http3ServerSocket _quicServerSocket;
SSL_CTX_Ptr _sslCtxTcp = SSL_CTX_Ptr(nullptr, SSL_CTX_free);
EVP_PKEY_Ptr _key = EVP_PKEY_Ptr(nullptr, EVP_PKEY_free);
X509_Ptr _cert = X509_Ptr(nullptr, X509_free);
std::vector<X509_Ptr> _cert;
std::shared_ptr<SharedData> _sharedData = std::make_shared<SharedData>();
std::map<int, std::unique_ptr<Http2Session>> _h2Sessions;
std::unordered_map<ngtcp2_cid, std::shared_ptr<Http3Session<RestServer>>> _h3Sessions;
Expand All @@ -2231,7 +2238,7 @@ struct RestServer {
RestServer(RestServer &&) = default;
RestServer &operator=(RestServer &&) = default;

RestServer(SSL_CTX_Ptr sslCtxTcp, EVP_PKEY_Ptr key, X509_Ptr cert)
RestServer(SSL_CTX_Ptr sslCtxTcp, EVP_PKEY_Ptr key, std::vector<X509_Ptr> cert)
: _sslCtxTcp(std::move(sslCtxTcp)), _key(std::move(key)), _cert(std::move(cert)) {
if (_sslCtxTcp) {
SSL_library_init();
Expand All @@ -2241,7 +2248,7 @@ struct RestServer {
}

static std::expected<RestServer, std::string> unencrypted() {
return RestServer(SSL_CTX_Ptr(nullptr, SSL_CTX_free), EVP_PKEY_Ptr(nullptr, EVP_PKEY_free), X509_Ptr(nullptr, X509_free));
return RestServer(SSL_CTX_Ptr(nullptr, SSL_CTX_free), EVP_PKEY_Ptr(nullptr, EVP_PKEY_free), {});
}

static std::expected<RestServer, std::string> sslWithBuffers(std::string_view certBuffer, std::string_view keyBuffer) {
Expand All @@ -2253,7 +2260,7 @@ struct RestServer {
if (!maybeKey) {
return std::unexpected(maybeKey.error());
}
auto maybeSslCtxTcp = create_ssl_ctx(maybeKey->get(), maybeCert->get());
auto maybeSslCtxTcp = create_ssl_ctx(maybeKey->get(), maybeCert.value());
if (!maybeSslCtxTcp) {
return std::unexpected(maybeSslCtxTcp.error());
}
Expand All @@ -2269,7 +2276,7 @@ struct RestServer {
if (!maybeKey) {
return std::unexpected(maybeKey.error());
}
auto maybeSslCtxTcp = create_ssl_ctx(maybeKey->get(), maybeCert->get());
auto maybeSslCtxTcp = create_ssl_ctx(maybeKey->get(), maybeCert.value());
if (!maybeSslCtxTcp) {
return std::unexpected(maybeSslCtxTcp.error());
}
Expand Down
17 changes: 13 additions & 4 deletions src/majordomo/include/majordomo/TlsServerSession_Ossl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class TLSServerContext {
return *this;
}

int init(const opencmw::rest::detail::EVP_PKEY_Ptr &key, const opencmw::rest::detail::X509_Ptr &cert, AppProtocol app_proto) {
int init(const opencmw::rest::detail::EVP_PKEY_Ptr &key, const std::vector<opencmw::rest::detail::X509_Ptr> &cert, AppProtocol app_proto) {
constexpr static unsigned char sid_ctx[] = "ngtcp2 server";

ssl_ctx_ = SSL_CTX_new(TLS_server_method());
Expand Down Expand Up @@ -226,9 +226,18 @@ class TLSServerContext {
return -1;
}

if (SSL_CTX_use_certificate(ssl_ctx_, cert.get()) != 1) {
std::cerr << "SSL_CTX_use_certificate_chain_file: " << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
return -1;
if (!cert.empty()) {
if (SSL_CTX_use_certificate(ssl_ctx_, cert[0].get()) != 1) {
std::cerr << "SSL_CTX_use_certificate_chain_file: " << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
return -1;
}

for (std::size_t i = 1; i < cert.size(); ++i) {
if (SSL_CTX_add_extra_chain_cert(ssl_ctx_, X509_up_ref(cert[i].get()) ? cert[i].get() : nullptr) != 1) {
std::cerr << "Could not add certificate chain file " << i << ": " << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
return -1;
}
}
}

if (SSL_CTX_check_private_key(ssl_ctx_) != 1) {
Expand Down
33 changes: 23 additions & 10 deletions src/rest/include/rest/RestUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,30 +83,43 @@ inline std::expected<X509_STORE_Ptr, std::string> createCertificateStore(std::st
return cert_store;
}

inline std::expected<X509_Ptr, std::string> readServerCertificateFromBuffer(std::string_view X509_ca_bundle) {
inline std::expected<std::vector<X509_Ptr>, std::string> readServerCertificateFromBuffer(std::string_view X509_ca_bundle) {
BIO *certBio = BIO_new(BIO_s_mem());
BIO_write(certBio, X509_ca_bundle.data(), static_cast<int>(X509_ca_bundle.size()));
auto certX509 = X509_Ptr(PEM_read_bio_X509(certBio, nullptr, nullptr, nullptr), X509_free);
std::vector<X509_Ptr> certs;
while (true) {
auto certX509 = X509_Ptr(PEM_read_bio_X509(certBio, nullptr, nullptr, nullptr), X509_free);
if (!certX509) {
break;
}
certs.push_back(std::move(certX509));
}
BIO_free(certBio);
if (!certX509) {
if (certs.empty()) {
return std::unexpected(std::format("failed to read certificate from buffer:\n#---start---\n{}\n#---end---\n", X509_ca_bundle));
}
return certX509;
return certs;
}

inline std::expected<X509_Ptr, std::string> readServerCertificateFromFile(std::filesystem::path fpath) {
inline std::expected<std::vector<X509_Ptr>, std::string> readServerCertificateFromFile(std::filesystem::path fpath) {
auto path = fpath.string();
BIO *certBio
= BIO_new_file(path.data(), "r");
BIO *certBio = BIO_new_file(path.data(), "r");
if (!certBio) {
return std::unexpected(std::format("failed to read certificate from file {}: {}", path, ERR_error_string(ERR_get_error(), nullptr)));
}
auto certX509 = X509_Ptr(PEM_read_bio_X509(certBio, nullptr, nullptr, nullptr), X509_free);
std::vector<X509_Ptr> certs;
while (true) {
auto certX509 = X509_Ptr(PEM_read_bio_X509(certBio, nullptr, nullptr, nullptr), X509_free);
if (!certX509) {
break;
}
certs.push_back(std::move(certX509));
}
BIO_free(certBio);
if (!certX509) {
if (certs.empty()) {
return std::unexpected(std::format("failed to read certificate key from file: {}", path));
}
return certX509;
return certs;
}

inline std::expected<EVP_PKEY_Ptr, std::string> readServerPrivateKeyFromBuffer(std::string_view x509_private_key) {
Expand Down