rippled
Loading...
Searching...
No Matches
HTTPClientSSLContext.h
1#ifndef XRPL_NET_HTTPCLIENTSSLCONTEXT_H_INCLUDED
2#define XRPL_NET_HTTPCLIENTSSLCONTEXT_H_INCLUDED
3
4#include <xrpl/basics/Log.h>
5#include <xrpl/basics/contract.h>
6#include <xrpl/beast/utility/Journal.h>
7#include <xrpl/net/RegisterSSLCerts.h>
8
9#include <boost/asio.hpp>
10#include <boost/asio/ip/tcp.hpp>
11#include <boost/asio/ssl.hpp>
12#include <boost/format.hpp>
13
14namespace xrpl {
15
17{
18public:
20 std::string const& sslVerifyDir,
21 std::string const& sslVerifyFile,
22 bool sslVerify,
24 boost::asio::ssl::context_base::method method = boost::asio::ssl::context::sslv23)
25 : ssl_context_{method}, j_(j), verify_{sslVerify}
26 {
27 boost::system::error_code ec;
28
29 if (sslVerifyFile.empty())
30 {
32
33 if (ec && sslVerifyDir.empty())
34 Throw<std::runtime_error>(
35 boost::str(boost::format("Failed to set_default_verify_paths: %s") % ec.message()));
36 }
37 else
38 {
39 ssl_context_.load_verify_file(sslVerifyFile);
40 }
41
42 if (!sslVerifyDir.empty())
43 {
44 ssl_context_.add_verify_path(sslVerifyDir, ec);
45
46 if (ec)
47 Throw<std::runtime_error>(boost::str(boost::format("Failed to add verify path: %s") % ec.message()));
48 }
49 }
50
51 boost::asio::ssl::context&
53 {
54 return ssl_context_;
55 }
56
57 bool
58 sslVerify() const
59 {
60 return verify_;
61 }
62
75 template <
76 class T,
77 class = std::enable_if_t<
80 boost::system::error_code
81 preConnectVerify(T& strm, std::string const& host)
82 {
83 boost::system::error_code ec;
84 if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str()))
85 {
86 ec.assign(static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category());
87 }
88 else if (!sslVerify())
89 {
90 strm.set_verify_mode(boost::asio::ssl::verify_none, ec);
91 }
92 return ec;
93 }
94
95 template <
96 class T,
97 class = std::enable_if_t<
107 boost::system::error_code
108 postConnectVerify(T& strm, std::string const& host)
109 {
110 boost::system::error_code ec;
111
112 if (sslVerify())
113 {
114 strm.set_verify_mode(boost::asio::ssl::verify_peer, ec);
115 if (!ec)
116 {
117 strm.set_verify_callback(
118 std::bind(&rfc6125_verify, host, std::placeholders::_1, std::placeholders::_2, j_), ec);
119 }
120 }
121
122 return ec;
123 }
124
134 static bool
135 rfc6125_verify(std::string const& domain, bool preverified, boost::asio::ssl::verify_context& ctx, beast::Journal j)
136 {
137 if (boost::asio::ssl::host_name_verification(domain)(preverified, ctx))
138 return true;
139
140 JLOG(j.warn()) << "Outbound SSL connection to " << domain << " fails certificate verification";
141 return false;
142 }
143
144private:
145 boost::asio::ssl::context ssl_context_;
147 bool const verify_;
148};
149
150} // namespace xrpl
151
152#endif
T bind(T... args)
T c_str(T... args)
A generic endpoint for log messages.
Definition Journal.h:41
Stream warn() const
Definition Journal.h:313
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::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 rfc6125_verify(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 ssl_context_
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::asio::ssl::context & context()
T empty(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
void registerSSLCerts(boost::asio::ssl::context &, boost::system::error_code &, beast::Journal j)
Register default SSL certificates.