aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/http/http_proxy_ssl.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/actors/http/http_proxy_ssl.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/actors/http/http_proxy_ssl.h')
-rw-r--r--library/cpp/actors/http/http_proxy_ssl.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/library/cpp/actors/http/http_proxy_ssl.h b/library/cpp/actors/http/http_proxy_ssl.h
new file mode 100644
index 0000000000..ffce12997f
--- /dev/null
+++ b/library/cpp/actors/http/http_proxy_ssl.h
@@ -0,0 +1,131 @@
+#pragma once
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/tls1.h>
+
+namespace NHttp {
+
+struct TSslHelpers {
+ struct TSslDestroy {
+ static void Destroy(SSL_CTX* ctx) noexcept {
+ SSL_CTX_free(ctx);
+ }
+
+ static void Destroy(SSL* ssl) noexcept {
+ SSL_free(ssl);
+ }
+
+ static void Destroy(X509* cert) noexcept {
+ X509_free(cert);
+ }
+
+ static void Destroy(EVP_PKEY* pkey) noexcept {
+ EVP_PKEY_free(pkey);
+ }
+
+ static void Destroy(BIO* bio) noexcept {
+ BIO_free(bio);
+ }
+ };
+
+ template <typename T>
+ using TSslHolder = THolder<T, TSslDestroy>;
+
+ static TSslHolder<SSL_CTX> CreateSslCtx(const SSL_METHOD* method) {
+ TSslHolder<SSL_CTX> ctx(SSL_CTX_new(method));
+
+ if (ctx) {
+ SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_SSLv2);
+ SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_SSLv3);
+ SSL_CTX_set_options(ctx.Get(), SSL_OP_MICROSOFT_SESS_ID_BUG);
+ SSL_CTX_set_options(ctx.Get(), SSL_OP_NETSCAPE_CHALLENGE_BUG);
+ }
+
+ return ctx;
+ }
+
+ static TSslHolder<SSL_CTX> CreateClientContext() {
+ return CreateSslCtx(SSLv23_client_method());
+ }
+
+ static TSslHolder<SSL_CTX> CreateServerContext(const TString& certificate, const TString& key) {
+ TSslHolder<SSL_CTX> ctx = CreateSslCtx(SSLv23_server_method());
+ SSL_CTX_set_ecdh_auto(ctx.Get(), 1);
+ int res;
+ res = SSL_CTX_use_certificate_chain_file(ctx.Get(), certificate.c_str());
+ if (res < 0) {
+ // TODO(xenoxeno): more diagnostics?
+ return nullptr;
+ }
+ res = SSL_CTX_use_PrivateKey_file(ctx.Get(), key.c_str(), SSL_FILETYPE_PEM);
+ if (res < 0) {
+ // TODO(xenoxeno): more diagnostics?
+ return nullptr;
+ }
+ return ctx;
+ }
+
+ static bool LoadX509Chain(TSslHolder<SSL_CTX>& ctx, const TString& pem) {
+ TSslHolder<BIO> bio(BIO_new_mem_buf(pem.c_str(), pem.size()));
+ if (bio == nullptr) {
+ return false;
+ }
+ TSslHolder<X509> cert(PEM_read_bio_X509_AUX(bio.Get(), nullptr, nullptr, nullptr));
+ if (cert == nullptr) {
+ return false;
+ }
+ if (SSL_CTX_use_certificate(ctx.Get(), cert.Release()) <= 0) {
+ return false;
+ }
+ SSL_CTX_clear_chain_certs(ctx.Get());
+ while (true) {
+ TSslHolder<X509> ca(PEM_read_bio_X509(bio.Get(), nullptr, nullptr, nullptr));
+ if (ca == nullptr) {
+ break;
+ }
+ if (!SSL_CTX_add0_chain_cert(ctx.Get(), ca.Release())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static bool LoadPrivateKey(TSslHolder<SSL_CTX>& ctx, const TString& pem) {
+ TSslHolder<BIO> bio(BIO_new_mem_buf(pem.c_str(), pem.size()));
+ if (bio == nullptr) {
+ return false;
+ }
+ TSslHolder<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(bio.Get(), nullptr, nullptr, nullptr));
+ if (SSL_CTX_use_PrivateKey(ctx.Get(), pkey.Release()) <= 0) {
+ return false;
+ }
+ return true;
+ }
+
+ static TSslHolder<SSL_CTX> CreateServerContext(const TString& pem) {
+ TSslHolder<SSL_CTX> ctx = CreateSslCtx(SSLv23_server_method());
+ SSL_CTX_set_ecdh_auto(ctx.Get(), 1);
+ if (!LoadX509Chain(ctx, pem)) {
+ return nullptr;
+ }
+ if (!LoadPrivateKey(ctx, pem)) {
+ return nullptr;
+ }
+ return ctx;
+ }
+
+ static TSslHolder<SSL> ConstructSsl(SSL_CTX* ctx, BIO* bio) {
+ TSslHolder<SSL> ssl(SSL_new(ctx));
+
+ if (ssl) {
+ BIO_up_ref(bio); // SSL_set_bio consumes only one reference if rbio and wbio are the same
+ SSL_set_bio(ssl.Get(), bio, bio);
+ }
+
+ return ssl;
+ }
+};
+
+}