rippled
Loading...
Searching...
No Matches
HTTPClientSSLContext.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2019 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_NET_HTTPCLIENTSSLCONTEXT_H_INCLUDED
21#define RIPPLE_NET_HTTPCLIENTSSLCONTEXT_H_INCLUDED
22
23#include <xrpld/core/Config.h>
24#include <xrpld/net/RegisterSSLCerts.h>
25#include <xrpl/basics/Log.h>
26#include <xrpl/basics/contract.h>
27#include <boost/asio.hpp>
28#include <boost/asio/ip/tcp.hpp>
29#include <boost/asio/ssl.hpp>
30#include <boost/format.hpp>
31
32namespace ripple {
33
35{
36public:
38 Config const& config,
40 boost::asio::ssl::context_base::method method =
41 boost::asio::ssl::context::sslv23)
42 : ssl_context_{method}, j_(j), verify_{config.SSL_VERIFY}
43 {
44 boost::system::error_code ec;
45
46 if (config.SSL_VERIFY_FILE.empty())
47 {
49
50 if (ec && config.SSL_VERIFY_DIR.empty())
51 Throw<std::runtime_error>(boost::str(
52 boost::format("Failed to set_default_verify_paths: %s") %
53 ec.message()));
54 }
55 else
56 {
57 ssl_context_.load_verify_file(config.SSL_VERIFY_FILE);
58 }
59
60 if (!config.SSL_VERIFY_DIR.empty())
61 {
62 ssl_context_.add_verify_path(config.SSL_VERIFY_DIR, ec);
63
64 if (ec)
65 Throw<std::runtime_error>(boost::str(
66 boost::format("Failed to add verify path: %s") %
67 ec.message()));
68 }
69 }
70
71 boost::asio::ssl::context&
73 {
74 return ssl_context_;
75 }
76
77 bool
78 sslVerify() const
79 {
80 return verify_;
81 }
82
95 template <
96 class T,
97 class = std::enable_if_t<
99 T,
100 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
101 value ||
103 T,
104 boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
105 value>>
106 boost::system::error_code
107 preConnectVerify(T& strm, std::string const& host)
108 {
109 boost::system::error_code ec;
110 if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str()))
111 {
112 ec.assign(
113 static_cast<int>(::ERR_get_error()),
114 boost::asio::error::get_ssl_category());
115 }
116 else if (!sslVerify())
117 {
118 strm.set_verify_mode(boost::asio::ssl::verify_none, ec);
119 }
120 return ec;
121 }
122
123 template <
124 class T,
125 class = std::enable_if_t<
127 T,
128 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
129 value ||
131 T,
132 boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
133 value>>
141 boost::system::error_code
142 postConnectVerify(T& strm, std::string const& host)
143 {
144 boost::system::error_code ec;
145
146 if (sslVerify())
147 {
148 strm.set_verify_mode(boost::asio::ssl::verify_peer, ec);
149 if (!ec)
150 {
151 strm.set_verify_callback(
152 std::bind(
154 host,
155 std::placeholders::_1,
156 std::placeholders::_2,
157 j_),
158 ec);
159 }
160 }
161
162 return ec;
163 }
164
174 static bool
176 std::string const& domain,
177 bool preverified,
178 boost::asio::ssl::verify_context& ctx,
180 {
181 if (boost::asio::ssl::rfc2818_verification(domain)(preverified, ctx))
182 return true;
183
184 JLOG(j.warn()) << "Outbound SSL connection to " << domain
185 << " fails certificate verification";
186 return false;
187 }
188
189private:
190 boost::asio::ssl::context ssl_context_;
192 const bool verify_;
193};
194
195} // namespace ripple
196
197#endif
T bind(T... args)
T c_str(T... args)
A generic endpoint for log messages.
Definition: Journal.h:59
Stream warn() const
Definition: Journal.h:329
std::string SSL_VERIFY_FILE
Definition: Config.h:223
std::string SSL_VERIFY_DIR
Definition: Config.h:224
static bool rfc2818_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 rfc2818 implementation.
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 ssl_context_
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...
boost::asio::ssl::context & context()
HTTPClientSSLContext(Config const &config, beast::Journal j, boost::asio::ssl::context_base::method method=boost::asio::ssl::context::sslv23)
T empty(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
void registerSSLCerts(boost::asio::ssl::context &ctx, boost::system::error_code &ec, beast::Journal j)
Register default SSL certificates.