rippled
RegisterSSLCerts.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2017 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 #include <ripple/net/RegisterSSLCerts.h>
20 #include <boost/predef.h>
21 
22 #if BOOST_OS_WINDOWS
23 #include <boost/asio/ssl/error.hpp>
24 #include <boost/system/error_code.hpp>
25 #include <memory>
26 #include <openssl/err.h>
27 #include <openssl/ssl.h>
28 #include <openssl/x509.h>
29 #include <wincrypt.h>
30 #endif
31 
32 namespace ripple {
33 
34 void
36  boost::asio::ssl::context& ctx,
37  boost::system::error_code& ec,
39 {
40 #if BOOST_OS_WINDOWS
41  auto certStoreDelete = [](void* h) {
42  if (h != nullptr)
43  CertCloseStore(h, 0);
44  };
45  std::unique_ptr<void, decltype(certStoreDelete)> hStore{
46  CertOpenSystemStore(0, "ROOT"), certStoreDelete};
47 
48  if (!hStore)
49  {
50  ec = boost::system::error_code(
51  GetLastError(), boost::system::system_category());
52  return;
53  }
54 
55  ERR_clear_error();
56 
57  std::unique_ptr<X509_STORE, decltype(X509_STORE_free)*> store{
58  X509_STORE_new(), X509_STORE_free};
59 
60  if (!store)
61  {
62  ec = boost::system::error_code(
63  static_cast<int>(::ERR_get_error()),
64  boost::asio::error::get_ssl_category());
65  return;
66  }
67 
68  auto warn = [&](std::string const& mesg) {
69  // Buffer based on asio recommended size
70  char buf[256];
71  ::ERR_error_string_n(ec.value(), buf, sizeof(buf));
72  JLOG(j.warn()) << mesg << " " << buf;
73  ::ERR_clear_error();
74  };
75 
76  PCCERT_CONTEXT pContext = NULL;
77  while ((pContext = CertEnumCertificatesInStore(hStore.get(), pContext)) !=
78  NULL)
79  {
80  const unsigned char* pbCertEncoded = pContext->pbCertEncoded;
81  std::unique_ptr<X509, decltype(X509_free)*> x509{
82  d2i_X509(NULL, &pbCertEncoded, pContext->cbCertEncoded), X509_free};
83  if (!x509)
84  {
85  warn("Error decoding certificate");
86  continue;
87  }
88 
89  if (X509_STORE_add_cert(store.get(), x509.get()) != 1)
90  {
91  warn("Error adding certificate");
92  }
93  else
94  {
95  // Successfully adding to the store took ownership
96  x509.release();
97  }
98  }
99 
100  // This takes ownership of the store
101  SSL_CTX_set_cert_store(ctx.native_handle(), store.release());
102 
103 #else
104  ctx.set_default_verify_paths(ec);
105 #endif
106 }
107 
108 } // namespace ripple
109 
110 // There is a very unpleasant interaction between <wincrypt> and
111 // openssl x509 types (namely the former has macros that stomp
112 // on the latter), these undefs allow this TU to be safely used in
113 // unity builds without messing up subsequent TUs.
114 #if BOOST_OS_WINDOWS
115 #undef X509_NAME
116 #undef X509_EXTENSIONS
117 #undef X509_CERT_PAIR
118 #undef PKCS7_ISSUER_AND_SERIAL
119 #undef OCSP_REQUEST
120 #undef OCSP_RESPONSE
121 #endif
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
std::string
STL class.
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
memory
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::unique_ptr
STL class.