xrpld
Loading...
Searching...
No Matches
HTTPClientSSLContext.h
1#pragma once
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/contract.h>
5#include <xrpl/beast/utility/Journal.h>
6#include <xrpl/net/RegisterSSLCerts.h>
7
8#include <boost/asio.hpp>
9#include <boost/asio/ip/tcp.hpp>
10#include <boost/asio/ssl.hpp>
11
12#include <openssl/err.h>
13#include <openssl/tls1.h>
14
15#include <format>
16#include <stdexcept>
17#include <string>
18#include <type_traits>
19
20namespace xrpl {
21
23{
24public:
26 std::string const& sslVerifyDir,
27 std::string const& sslVerifyFile,
28 bool sslVerify,
30 boost::asio::ssl::context_base::method method = boost::asio::ssl::context::sslv23)
31 : sslContext_{method}, j_(j), verify_{sslVerify}
32 {
33 boost::system::error_code ec;
34
35 if (sslVerifyFile.empty())
36 {
37 registerSSLCerts(sslContext_, ec, j_);
38
39 if (ec && sslVerifyDir.empty())
40 {
41 Throw<std::runtime_error>(
42 std::format("Failed to set_default_verify_paths: {}", ec.message()));
43 }
44 }
45 else
46 {
47 sslContext_.load_verify_file(sslVerifyFile);
48 }
49
50 if (!sslVerifyDir.empty())
51 {
52 sslContext_.add_verify_path(sslVerifyDir, ec);
53
54 if (ec)
55 {
56 Throw<std::runtime_error>(
57 std::format("Failed to add verify path: {}", ec.message()));
58 }
59 }
60 }
61
62 boost::asio::ssl::context&
64 {
65 return sslContext_;
66 }
67
68 [[nodiscard]] bool
69 sslVerify() const
70 {
71 return verify_;
72 }
73
86 template <class T>
87 boost::system::error_code
88 preConnectVerify(T& strm, std::string const& host)
89 requires(
92 {
93 boost::system::error_code ec;
94 if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str()))
95 {
96 ec.assign(static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category());
97 }
98 else if (!sslVerify())
99 {
100 strm.set_verify_mode(boost::asio::ssl::verify_none, ec);
101 }
102 return ec;
103 }
104
105 template <class T>
113 boost::system::error_code
114 postConnectVerify(T& strm, std::string const& host)
115 requires(
118 {
119 boost::system::error_code ec;
120
121 if (sslVerify())
122 {
123 strm.set_verify_mode(boost::asio::ssl::verify_peer, ec);
124 if (!ec)
125 {
126 strm.set_verify_callback(
127 [host, j = j_](bool preverified, boost::asio::ssl::verify_context& ctx) {
128 return rfc6125Verify(host, preverified, ctx, j);
129 },
130 ec);
131 }
132 }
133
134 return ec;
135 }
136
146 static bool
148 std::string const& domain,
149 bool preverified,
150 boost::asio::ssl::verify_context& ctx,
152 {
153 if (boost::asio::ssl::host_name_verification(domain)(preverified, ctx))
154 return true;
155
156 JLOG(j.warn()) << "Outbound SSL connection to " << domain
157 << " fails certificate verification";
158 return false;
159 }
160
161private:
162 boost::asio::ssl::context sslContext_;
164 bool const verify_;
165};
166
167} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Stream warn() const
Definition Journal.h:356
boost::system::error_code postConnectVerify(T &strm, std::string const &host)
invoked after connect/async_connect but before sending data on an ssl stream - to setup name verifica...
static bool rfc6125Verify(std::string const &domain, bool preverified, boost::asio::ssl::verify_context &ctx, beast::Journal j)
callback invoked for name verification - just passes through to the asio host_name_verification (rfc6...
boost::asio::ssl::context sslContext_
HTTPClientSSLContext(std::string const &sslVerifyDir, std::string const &sslVerifyFile, bool sslVerify, beast::Journal j, boost::asio::ssl::context_base::method method=boost::asio::ssl::context::sslv23)
boost::system::error_code preConnectVerify(T &strm, std::string const &host)
invoked before connect/async_connect on an ssl stream to setup name verification.
boost::asio::ssl::context & context()
T empty(T... args)
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5