The Battle for Wesnoth  1.19.23+dev
tls_root_store.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2021 - 2025
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 <TargetConditionals.h>
23 #include <Security/Security.h>
24 #endif
25 
26 #if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IPHONE)
27 #include "filesystem.hpp"
28 #endif
29 
30 static lg::log_domain log_network("network");
31 #define DBG_NW LOG_STREAM(debug, log_network)
32 #define LOG_NW LOG_STREAM(info, log_network)
33 #define WRN_NW LOG_STREAM(warn, log_network)
34 #define ERR_NW LOG_STREAM(err, log_network)
35 
36 namespace network_asio
37 {
38 
39 void load_tls_root_certs(boost::asio::ssl::context &ctx)
40 {
41 #ifdef _WIN32
42  HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
43  assert(hStore != NULL);
44 
45  X509_STORE *store = X509_STORE_new();
46  PCCERT_CONTEXT pContext = NULL;
47  while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) {
48  X509 *x509 = d2i_X509(NULL,
49  const_cast<const unsigned char**>(&pContext->pbCertEncoded),
50  pContext->cbCertEncoded);
51  if(x509 != NULL) {
52  X509_STORE_add_cert(store, x509);
53  X509_free(x509);
54  }
55  }
56 
57  CertFreeCertificateContext(pContext);
58  CertCloseStore(hStore, 0);
59 
60  SSL_CTX_set_cert_store(ctx.native_handle(), store);
61 #elif defined(__APPLE__) && !TARGET_OS_IPHONE
62  X509_STORE *store = X509_STORE_new();
63  CFArrayRef certs = NULL;
64  // copy all system certs
65  OSStatus os_status = SecTrustCopyAnchorCertificates(&certs);
66 
67  // check for any problems copying the certs
68  if(os_status != 0) {
69  ERR_NW << "Error enumerating certificates.";
70 
71  if (certs != NULL) {
72  CFRelease(certs);
73  }
74  return;
75  }
76 
77  for(CFIndex i = 0; i < CFArrayGetCount(certs); i++) {
78  SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
79 
80  // convert the cert to DER format
81  CFDataRef der_cert = SecCertificateCopyData(cert);
82  if(!der_cert) {
83  ERR_NW << "Error getting a DER representation of a certificate.";
84  continue;
85  }
86 
87  // decode each cert to an openssl X509 object
88  const uint8_t* der_cert_ptr = CFDataGetBytePtr(der_cert);
89  X509* x509_cert = d2i_X509(NULL, &der_cert_ptr, CFDataGetLength(der_cert));
90  if(!x509_cert) {
91  ERR_NW << "Error deciding the X509 certificate.";
92  CFRelease(der_cert);
93  continue;
94  }
95 
96  // Add the X509 openssl object to the verification store
97  if(X509_STORE_add_cert(store, x509_cert) != 1) {
98  CFRelease(der_cert);
99  X509_free(x509_cert);
100  ERR_NW << "Error adding the X509 certificate to the store.";
101  continue;
102  }
103  }
104 
105  CFRelease(certs);
106  SSL_CTX_set_cert_store(ctx.native_handle(), store);
107 #elif (defined(__APPLE__) && TARGET_OS_IPHONE) || defined(__ANDROID__)
108  ctx.load_verify_file(game_config::path + "/certificates/cacert.pem");
109 #else
110  ctx.set_default_verify_paths();
111 #endif
112 }
113 
114 }
Declarations for File-IO.
std::size_t i
Definition: function.cpp:1031
Standard logging facilities (interface).
std::string path
Definition: filesystem.cpp:106
void load_tls_root_certs(boost::asio::ssl::context &ctx)
#define ERR_NW
static lg::log_domain log_network("network")