rippled
Loading...
Searching...
No Matches
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 <xrpld/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
32namespace ripple {
33
34void
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
A generic endpoint for log messages.
Definition: Journal.h:59
Stream warn() const
Definition: Journal.h:329
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.