The Battle for Wesnoth  1.19.0-dev
tls_root_store.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2021 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "tls_root_store.hpp"
16 
17 #include "log.hpp"
18 
19 #ifdef _WIN32
20 #include <wincrypt.h>
21 #elif defined(__APPLE__)
22 #include <Security/Security.h>
23 #endif
24 
25 static lg::log_domain log_network("network");
26 #define DBG_NW LOG_STREAM(debug, log_network)
27 #define LOG_NW LOG_STREAM(info, log_network)
28 #define WRN_NW LOG_STREAM(warn, log_network)
29 #define ERR_NW LOG_STREAM(err, log_network)
30 
31 namespace network_asio
32 {
33 
34 void load_tls_root_certs(boost::asio::ssl::context &ctx)
35 {
36 #ifdef _WIN32
37  HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
38  assert(hStore != NULL);
39 
40  X509_STORE *store = X509_STORE_new();
41  PCCERT_CONTEXT pContext = NULL;
42  while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) {
43  X509 *x509 = d2i_X509(NULL,
44  const_cast<const unsigned char**>(&pContext->pbCertEncoded),
45  pContext->cbCertEncoded);
46  if(x509 != NULL) {
47  X509_STORE_add_cert(store, x509);
48  X509_free(x509);
49  }
50  }
51 
52  CertFreeCertificateContext(pContext);
53  CertCloseStore(hStore, 0);
54 
55  SSL_CTX_set_cert_store(ctx.native_handle(), store);
56 #elif defined(__APPLE__)
57  X509_STORE *store = X509_STORE_new();
58  CFArrayRef certs = NULL;
59  // copy all system certs
60  OSStatus os_status = SecTrustCopyAnchorCertificates(&certs);
61 
62  // check for any problems copying the certs
63  if(os_status != 0) {
64  ERR_NW << "Error enumerating certificates.";
65 
66  if (certs != NULL) {
67  CFRelease(certs);
68  }
69  return;
70  }
71 
72  for(CFIndex i = 0; i < CFArrayGetCount(certs); i++) {
73  SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
74 
75  // convert the cert to DER format
76  CFDataRef der_cert = SecCertificateCopyData(cert);
77  if(!der_cert) {
78  ERR_NW << "Error getting a DER representation of a certificate.";
79  continue;
80  }
81 
82  // decode each cert to an openssl X509 object
83  const uint8_t* der_cert_ptr = CFDataGetBytePtr(der_cert);
84  X509* x509_cert = d2i_X509(NULL, &der_cert_ptr, CFDataGetLength(der_cert));
85  if(!x509_cert) {
86  ERR_NW << "Error deciding the X509 certificate.";
87  CFRelease(der_cert);
88  continue;
89  }
90 
91  // Add the X509 openssl object to the verification store
92  if(X509_STORE_add_cert(store, x509_cert) != 1) {
93  CFRelease(der_cert);
94  X509_free(x509_cert);
95  ERR_NW << "Error adding the X509 certificate to the store.";
96  continue;
97  }
98  }
99 
100  CFRelease(certs);
101  SSL_CTX_set_cert_store(ctx.native_handle(), store);
102 #else
103  ctx.set_default_verify_paths();
104 #endif
105 }
106 
107 }
std::size_t i
Definition: function.cpp:968
Standard logging facilities (interface).
void load_tls_root_certs(boost::asio::ssl::context &ctx)
#define ERR_NW
static lg::log_domain log_network("network")