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
26#include <xrpl/basics/Log.h>
27#include <xrpl/basics/contract.h>
28
29#include <boost/asio.hpp>
30#include <boost/asio/ip/tcp.hpp>
31#include <boost/asio/ssl.hpp>
32#include <boost/format.hpp>
33
34namespace ripple {
35
37{
38public:
40 Config const& config,
42 boost::asio::ssl::context_base::method method =
43 boost::asio::ssl::context::sslv23)
44 : ssl_context_{method}, j_(j), verify_{config.SSL_VERIFY}
45 {
46 boost::system::error_code ec;
47
48 if (config.SSL_VERIFY_FILE.empty())
49 {
51
52 if (ec && config.SSL_VERIFY_DIR.empty())
53 Throw<std::runtime_error>(boost::str(
54 boost::format("Failed to set_default_verify_paths: %s") %
55 ec.message()));
56 }
57 else
58 {
59 ssl_context_.load_verify_file(config.SSL_VERIFY_FILE);
60 }
61
62 if (!config.SSL_VERIFY_DIR.empty())
63 {
64 ssl_context_.add_verify_path(config.SSL_VERIFY_DIR, ec);
65
66 if (ec)
67 Throw<std::runtime_error>(boost::str(
68 boost::format("Failed to add verify path: %s") %
69 ec.message()));
70 }
71 }
72
73 boost::asio::ssl::context&
75 {
76 return ssl_context_;
77 }
78
79 bool
80 sslVerify() const
81 {
82 return verify_;
83 }
84
97 template <
98 class T,
99 class = std::enable_if_t<
101 T,
102 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
103 value ||
105 T,
106 boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
107 value>>
108 boost::system::error_code
109 preConnectVerify(T& strm, std::string const& host)
110 {
111 boost::system::error_code ec;
112 if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str()))
113 {
114 ec.assign(
115 static_cast<int>(::ERR_get_error()),
116 boost::asio::error::get_ssl_category());
117 }
118 else if (!sslVerify())
119 {
120 strm.set_verify_mode(boost::asio::ssl::verify_none, ec);
121 }
122 return ec;
123 }
124
125 template <
126 class T,
127 class = std::enable_if_t<
129 T,
130 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
131 value ||
133 T,
134 boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
135 value>>
143 boost::system::error_code
144 postConnectVerify(T& strm, std::string const& host)
145 {
146 boost::system::error_code ec;
147
148 if (sslVerify())
149 {
150 strm.set_verify_mode(boost::asio::ssl::verify_peer, ec);
151 if (!ec)
152 {
153 strm.set_verify_callback(
154 std::bind(
156 host,
157 std::placeholders::_1,
158 std::placeholders::_2,
159 j_),
160 ec);
161 }
162 }
163
164 return ec;
165 }
166
176 static bool
178 std::string const& domain,
179 bool preverified,
180 boost::asio::ssl::verify_context& ctx,
182 {
183 if (boost::asio::ssl::rfc2818_verification(domain)(preverified, ctx))
184 return true;
185
186 JLOG(j.warn()) << "Outbound SSL connection to " << domain
187 << " fails certificate verification";
188 return false;
189 }
190
191private:
192 boost::asio::ssl::context ssl_context_;
194 bool const verify_;
195};
196
197} // namespace ripple
198
199#endif
T bind(T... args)
T c_str(T... args)
A generic endpoint for log messages.
Definition: Journal.h:60
Stream warn() const
Definition: Journal.h:340
std::string SSL_VERIFY_FILE
Definition: Config.h:216
std::string SSL_VERIFY_DIR
Definition: Config.h:217
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:25
void registerSSLCerts(boost::asio::ssl::context &ctx, boost::system::error_code &ec, beast::Journal j)
Register default SSL certificates.