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 <xrpl/basics/Log.h>
24#include <xrpl/basics/contract.h>
25#include <xrpl/beast/utility/Journal.h>
26#include <xrpl/net/RegisterSSLCerts.h>
27
28#include <boost/asio.hpp>
29#include <boost/asio/ip/tcp.hpp>
30#include <boost/asio/ssl.hpp>
31#include <boost/format.hpp>
32
33namespace ripple {
34
36{
37public:
39 std::string const& sslVerifyDir,
40 std::string const& sslVerifyFile,
41 bool sslVerify,
43 boost::asio::ssl::context_base::method method =
44 boost::asio::ssl::context::sslv23)
45 : ssl_context_{method}, j_(j), verify_{sslVerify}
46 {
47 boost::system::error_code ec;
48
49 if (sslVerifyFile.empty())
50 {
52
53 if (ec && sslVerifyDir.empty())
54 Throw<std::runtime_error>(boost::str(
55 boost::format("Failed to set_default_verify_paths: %s") %
56 ec.message()));
57 }
58 else
59 {
60 ssl_context_.load_verify_file(sslVerifyFile);
61 }
62
63 if (!sslVerifyDir.empty())
64 {
65 ssl_context_.add_verify_path(sslVerifyDir, ec);
66
67 if (ec)
68 Throw<std::runtime_error>(boost::str(
69 boost::format("Failed to add verify path: %s") %
70 ec.message()));
71 }
72 }
73
74 boost::asio::ssl::context&
76 {
77 return ssl_context_;
78 }
79
80 bool
81 sslVerify() const
82 {
83 return verify_;
84 }
85
98 template <
99 class T,
100 class = std::enable_if_t<
102 T,
103 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
104 value ||
106 T,
107 boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
108 value>>
109 boost::system::error_code
110 preConnectVerify(T& strm, std::string const& host)
111 {
112 boost::system::error_code ec;
113 if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str()))
114 {
115 ec.assign(
116 static_cast<int>(::ERR_get_error()),
117 boost::asio::error::get_ssl_category());
118 }
119 else if (!sslVerify())
120 {
121 strm.set_verify_mode(boost::asio::ssl::verify_none, ec);
122 }
123 return ec;
124 }
125
126 template <
127 class T,
128 class = std::enable_if_t<
130 T,
131 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
132 value ||
134 T,
135 boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
136 value>>
144 boost::system::error_code
145 postConnectVerify(T& strm, std::string const& host)
146 {
147 boost::system::error_code ec;
148
149 if (sslVerify())
150 {
151 strm.set_verify_mode(boost::asio::ssl::verify_peer, ec);
152 if (!ec)
153 {
154 strm.set_verify_callback(
155 std::bind(
157 host,
158 std::placeholders::_1,
159 std::placeholders::_2,
160 j_),
161 ec);
162 }
163 }
164
165 return ec;
166 }
167
177 static bool
179 std::string const& domain,
180 bool preverified,
181 boost::asio::ssl::verify_context& ctx,
183 {
184 if (boost::asio::ssl::host_name_verification(domain)(preverified, ctx))
185 return true;
186
187 JLOG(j.warn()) << "Outbound SSL connection to " << domain
188 << " fails certificate verification";
189 return false;
190 }
191
192private:
193 boost::asio::ssl::context ssl_context_;
195 bool const verify_;
196};
197
198} // namespace ripple
199
200#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
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 ssl_context_
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::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()
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 &, boost::system::error_code &, beast::Journal j)
Register default SSL certificates.