http_proxy_ssl.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #pragma once
  2. #include <openssl/bio.h>
  3. #include <openssl/ssl.h>
  4. #include <openssl/err.h>
  5. #include <openssl/tls1.h>
  6. namespace NHttp {
  7. struct TSslHelpers {
  8. struct TSslDestroy {
  9. static void Destroy(SSL_CTX* ctx) noexcept {
  10. SSL_CTX_free(ctx);
  11. }
  12. static void Destroy(SSL* ssl) noexcept {
  13. SSL_free(ssl);
  14. }
  15. static void Destroy(X509* cert) noexcept {
  16. X509_free(cert);
  17. }
  18. static void Destroy(EVP_PKEY* pkey) noexcept {
  19. EVP_PKEY_free(pkey);
  20. }
  21. static void Destroy(BIO* bio) noexcept {
  22. BIO_free(bio);
  23. }
  24. };
  25. template <typename T>
  26. using TSslHolder = THolder<T, TSslDestroy>;
  27. static TSslHolder<SSL_CTX> CreateSslCtx(const SSL_METHOD* method) {
  28. TSslHolder<SSL_CTX> ctx(SSL_CTX_new(method));
  29. if (ctx) {
  30. SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_SSLv2);
  31. SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_SSLv3);
  32. SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_TLSv1);
  33. SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_TLSv1_1);
  34. SSL_CTX_set_options(ctx.Get(), SSL_OP_MICROSOFT_SESS_ID_BUG);
  35. SSL_CTX_set_options(ctx.Get(), SSL_OP_NETSCAPE_CHALLENGE_BUG);
  36. }
  37. return ctx;
  38. }
  39. static TSslHolder<SSL_CTX> CreateClientContext() {
  40. return CreateSslCtx(SSLv23_client_method());
  41. }
  42. static TSslHolder<SSL_CTX> CreateServerContext(const TString& certificate, const TString& key) {
  43. TSslHolder<SSL_CTX> ctx = CreateSslCtx(SSLv23_server_method());
  44. SSL_CTX_set_ecdh_auto(ctx.Get(), 1);
  45. int res;
  46. res = SSL_CTX_use_certificate_chain_file(ctx.Get(), certificate.c_str());
  47. if (res < 0) {
  48. // TODO(xenoxeno): more diagnostics?
  49. return nullptr;
  50. }
  51. res = SSL_CTX_use_PrivateKey_file(ctx.Get(), key.c_str(), SSL_FILETYPE_PEM);
  52. if (res < 0) {
  53. // TODO(xenoxeno): more diagnostics?
  54. return nullptr;
  55. }
  56. return ctx;
  57. }
  58. static bool LoadX509Chain(TSslHolder<SSL_CTX>& ctx, const TString& pem) {
  59. TSslHolder<BIO> bio(BIO_new_mem_buf(pem.c_str(), pem.size()));
  60. if (bio == nullptr) {
  61. return false;
  62. }
  63. TSslHolder<X509> cert(PEM_read_bio_X509_AUX(bio.Get(), nullptr, nullptr, nullptr));
  64. if (cert == nullptr) {
  65. return false;
  66. }
  67. if (SSL_CTX_use_certificate(ctx.Get(), cert.Release()) <= 0) {
  68. return false;
  69. }
  70. SSL_CTX_clear_chain_certs(ctx.Get());
  71. while (true) {
  72. TSslHolder<X509> ca(PEM_read_bio_X509(bio.Get(), nullptr, nullptr, nullptr));
  73. if (ca == nullptr) {
  74. break;
  75. }
  76. if (!SSL_CTX_add0_chain_cert(ctx.Get(), ca.Release())) {
  77. return false;
  78. }
  79. }
  80. return true;
  81. }
  82. static bool LoadPrivateKey(TSslHolder<SSL_CTX>& ctx, const TString& pem) {
  83. TSslHolder<BIO> bio(BIO_new_mem_buf(pem.c_str(), pem.size()));
  84. if (bio == nullptr) {
  85. return false;
  86. }
  87. TSslHolder<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(bio.Get(), nullptr, nullptr, nullptr));
  88. if (SSL_CTX_use_PrivateKey(ctx.Get(), pkey.Release()) <= 0) {
  89. return false;
  90. }
  91. return true;
  92. }
  93. static TSslHolder<SSL_CTX> CreateServerContext(const TString& pem) {
  94. TSslHolder<SSL_CTX> ctx = CreateSslCtx(SSLv23_server_method());
  95. SSL_CTX_set_ecdh_auto(ctx.Get(), 1);
  96. if (!LoadX509Chain(ctx, pem)) {
  97. return nullptr;
  98. }
  99. if (!LoadPrivateKey(ctx, pem)) {
  100. return nullptr;
  101. }
  102. return ctx;
  103. }
  104. static TSslHolder<SSL> ConstructSsl(SSL_CTX* ctx, BIO* bio) {
  105. TSslHolder<SSL> ssl(SSL_new(ctx));
  106. if (ssl) {
  107. BIO_up_ref(bio); // SSL_set_bio consumes only one reference if rbio and wbio are the same
  108. SSL_set_bio(ssl.Get(), bio, bio);
  109. }
  110. return ssl;
  111. }
  112. };
  113. }