10#include <boost/container/flat_set.hpp>
13#include <CoreFoundation/CoreFoundation.h>
14#include <Security/Security.h>
20static void add_macos_root_cas(boost::asio::ssl::context& ctx) {
21 boost::container::flat_set<std::string> trusted_certs;
22 boost::container::flat_set<std::string> untrusted_certs;
24 SecTrustSettingsDomain
domains[] = { kSecTrustSettingsDomainSystem,
25 kSecTrustSettingsDomainAdmin,
26 kSecTrustSettingsDomainUser };
30 for (
unsigned int i = 0; i < number_domains; i++) {
32 OSStatus err = SecTrustSettingsCopyCertificates(
domains[i], &certs);
36 for(CFIndex
j = 0;
j < CFArrayGetCount(certs); ++
j) {
37 CFArrayRef trustSettings =
nullptr;
38 SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs,
j);
42 bool untrusted{
false}, trust_as_root{i == 0}, trust_root{
false};
44 for (
unsigned int k = i; k < number_domains; k++) {
45 CFArrayRef domainTrustSettings =
nullptr;
46 err = SecTrustSettingsCopyTrustSettings(cert,
domains[k], &domainTrustSettings);
47 if (err == errSecSuccess && domainTrustSettings !=
nullptr) {
49 CFRelease(trustSettings);
50 trustSettings = domainTrustSettings;
53 if(trustSettings ==
nullptr)
55 if(CFArrayGetCount(trustSettings) == 0)
57 else for(CFIndex k = 0; k < CFArrayGetCount(trustSettings); k++) {
59 CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, k);
60 if(CFDictionaryGetValueIfPresent(tSetting, kSecTrustSettingsResult, (
const void**)&cfNum)){
62 CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result);
63 if(result == kSecTrustSettingsResultDeny)
65 else if (result == kSecTrustSettingsResultTrustAsRoot)
67 else if (result == kSecTrustSettingsResultTrustRoot)
71 CFRelease(trustSettings);
76 CFErrorRef errRef =
nullptr;
77 CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef);
78 if(errRef !=
nullptr) {
82 CFDataRef issuerName = SecCertificateCopyNormalizedIssuerContent(cert, &errRef);
83 if(errRef !=
nullptr) {
84 CFRelease(subjectName);
88 Boolean equal = CFEqual(subjectName, issuerName);
89 CFRelease(subjectName);
90 CFRelease(issuerName);
96 err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour,
nullptr, &certAsPEM);
100 if(!trust_root && !trust_as_root)
101 untrusted_certs.emplace((
const char*)CFDataGetBytePtr(certAsPEM), CFDataGetLength(certAsPEM));
103 trusted_certs.emplace((
const char*)CFDataGetBytePtr(certAsPEM), CFDataGetLength(certAsPEM));
104 CFRelease(certAsPEM);
109 for(
const auto& untrusted : untrusted_certs)
110 trusted_certs.erase(untrusted);
111 boost::system::error_code
dummy;
112 for(
const auto& trusted : trusted_certs)
113 ctx.add_certificate_authority(boost::asio::const_buffer(trusted.data(), trusted.size()), dummy);
118#if defined( __APPLE__ )
119 add_macos_root_cas(ctx);
120#elif defined( _WIN32 )
121 FC_THROW(
"HTTPS on Windows not supported");
123 ctx.set_default_verify_paths();
Defines exception's used by fc.
constexpr enabler dummy
An instance to use in EnableIf.
void add_platform_root_cas_to_context(boost::asio::ssl::context &ctx)