rippled
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 <ripple/basics/contract.h>
24 #include <ripple/basics/Log.h>
25 #include <ripple/core/Config.h>
26 #include <ripple/net/RegisterSSLCerts.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 
32 namespace ripple {
33 
35 {
36 public:
37 
38  explicit
40  Config const& config,
42  boost::asio::ssl::context_base::method method =
43  boost::asio::ssl::context::sslv23)
44  : ssl_context_ {method}
45  , j_(j)
46  , verify_ {config.SSL_VERIFY}
47  {
48  boost::system::error_code ec;
49 
50  if (config.SSL_VERIFY_FILE.empty ())
51  {
53 
54  if (ec && config.SSL_VERIFY_DIR.empty ())
55  Throw<std::runtime_error> (
56  boost::str (boost::format (
57  "Failed to set_default_verify_paths: %s") %
58  ec.message ()));
59  }
60  else
61  {
62  ssl_context_.load_verify_file (config.SSL_VERIFY_FILE);
63  }
64 
65  if (! config.SSL_VERIFY_DIR.empty ())
66  {
67  ssl_context_.add_verify_path (config.SSL_VERIFY_DIR, ec);
68 
69  if (ec)
70  Throw<std::runtime_error> (
71  boost::str (boost::format (
72  "Failed to add verify path: %s") % ec.message ()));
73  }
74  }
75 
76  boost::asio::ssl::context& context()
77  {
78  return ssl_context_;
79  }
80 
81  bool sslVerify() const
82  {
83  return verify_;
84  }
85 
98  template<class T,
99  class = std::enable_if_t<
102  >
103  >
104  boost::system::error_code
106  T& strm,
107  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(static_cast<int>(
113  ::ERR_get_error()), boost::asio::error::get_ssl_category());
114  }
115  else if (!sslVerify())
116  {
117  strm.set_verify_mode(boost::asio::ssl::verify_none, ec);
118  }
119  return ec;
120 
121  }
122 
123  template<class T,
124  class = std::enable_if_t<
127  >
128  >
136  boost::system::error_code
138  T& strm,
139  std::string const& host)
140  {
141  boost::system::error_code ec;
142 
143  if (sslVerify())
144  {
145  strm.set_verify_mode (boost::asio::ssl::verify_peer, ec);
146  if (!ec)
147  {
148  strm.set_verify_callback (
149  std::bind (&rfc2818_verify, host,
150  std::placeholders::_1, std::placeholders::_2, j_), ec);
151  }
152  }
153 
154  return ec;
155  }
156 
166  static
167  bool
169  std::string const& domain,
170  bool preverified,
171  boost::asio::ssl::verify_context& ctx,
172  beast::Journal j)
173  {
174  if (boost::asio::ssl::rfc2818_verification (domain) (preverified, ctx))
175  return true;
176 
177  JLOG (j.warn()) <<
178  "Outbound SSL connection to " << domain <<
179  " fails certificate verification";
180  return false;
181  }
182 
183 private:
184  boost::asio::ssl::context ssl_context_;
186  const bool verify_;
187 };
188 
189 } // ripple
190 
191 #endif
ripple::HTTPClientSSLContext::rfc2818_verify
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.
Definition: HTTPClientSSLContext.h:168
std::is_same
std::bind
T bind(T... args)
ripple::registerSSLCerts
void registerSSLCerts(boost::asio::ssl::context &ctx, boost::system::error_code &ec, beast::Journal j)
Register default SSL certificates.
Definition: RegisterSSLCerts.cpp:35
ripple::HTTPClientSSLContext::sslVerify
bool sslVerify() const
Definition: HTTPClientSSLContext.h:81
std::string
STL class.
ripple::HTTPClientSSLContext::verify_
const bool verify_
Definition: HTTPClientSSLContext.h:186
ripple::HTTPClientSSLContext::context
boost::asio::ssl::context & context()
Definition: HTTPClientSSLContext.h:76
ripple::HTTPClientSSLContext::j_
const beast::Journal j_
Definition: HTTPClientSSLContext.h:185
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
ripple::HTTPClientSSLContext::preConnectVerify
boost::system::error_code preConnectVerify(T &strm, std::string const &host)
invoked before connect/async_connect on an ssl stream to setup name verification.
Definition: HTTPClientSSLContext.h:105
ripple::HTTPClientSSLContext::ssl_context_
boost::asio::ssl::context ssl_context_
Definition: HTTPClientSSLContext.h:184
std::enable_if_t
ripple::Config
Definition: Config.h:67
std::string::c_str
T c_str(T... args)
ripple::HTTPClientSSLContext::postConnectVerify
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...
Definition: HTTPClientSSLContext.h:137
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
ripple::HTTPClientSSLContext::HTTPClientSSLContext
HTTPClientSSLContext(Config const &config, beast::Journal j, boost::asio::ssl::context_base::method method=boost::asio::ssl::context::sslv23)
Definition: HTTPClientSSLContext.h:39
ripple::HTTPClientSSLContext
Definition: HTTPClientSSLContext.h:34
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29