6#include <QtNetwork/private/qtlsbackend_p.h>
8#include <QtNetwork/qsslcertificate.h>
10#include <QtCore/qloggingcategory.h>
11#include <QtCore/qglobal.h>
12#include <QtCore/qdebug.h>
17#include <QtCore/private/qcore_mac_p.h>
19#include <CoreFoundation/CFArray.h>
20#include <Security/Security.h>
31bool hasTrustedSslServerPolicy(SecPolicyRef policy, CFDictionaryRef props) {
32 QCFType<CFDictionaryRef> policyProps = SecPolicyCopyProperties(policy);
34 if (CFEqual(CFDictionaryGetValue(policyProps, kSecPolicyOid), kSecPolicyAppleSSL)) {
35 CFBooleanRef policyClient;
36 if (CFDictionaryGetValueIfPresent(policyProps, kSecPolicyClient,
reinterpret_cast<
const void**>(&policyClient)) &&
37 CFEqual(policyClient, kCFBooleanTrue)) {
40 if (!CFDictionaryContainsKey(props, kSecTrustSettingsResult)) {
44 CFNumberRef number =
static_cast<CFNumberRef>(CFDictionaryGetValue(props, kSecTrustSettingsResult));
45 SecTrustSettingsResult settingsResult;
46 CFNumberGetValue(number, kCFNumberSInt32Type, &settingsResult);
47 switch (settingsResult) {
48 case kSecTrustSettingsResultTrustRoot:
49 case kSecTrustSettingsResultTrustAsRoot:
58bool isCaCertificateTrusted(SecCertificateRef cfCert,
int domain)
60 QCFType<CFArrayRef> cfTrustSettings;
61 OSStatus status = SecTrustSettingsCopyTrustSettings(cfCert, SecTrustSettingsDomain(domain), &cfTrustSettings);
62 if (status == noErr) {
63 CFIndex size = CFArrayGetCount(cfTrustSettings);
68 for (CFIndex i = 0; i < size; ++i) {
69 CFDictionaryRef props =
static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(cfTrustSettings, i));
70 if (CFDictionaryContainsKey(props, kSecTrustSettingsPolicy)) {
71 if (hasTrustedSslServerPolicy((SecPolicyRef)CFDictionaryGetValue(props, kSecTrustSettingsPolicy), props))
81bool canDERBeParsed(CFDataRef derData,
const QSslCertificate &qtCert)
88 auto checkDer = [](CFDataRef derData,
const char *source)
93 const auto cfLength = CFDataGetLength(derData);
95 qCWarning(lcX509) << source <<
"returned faulty DER data with invalid length.";
99 QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(
nullptr, derData);
101 qCWarning(lcX509) << source <<
"returned faulty DER data which cannot be parsed back.";
107 if (!checkDer(derData,
"SecCertificateCopyData")) {
108 qCDebug(lcX509) <<
"Faulty QSslCertificate is:" << qtCert;
113 if (qtCert.isNull()) {
114 qCWarning(lcX509,
"QSslCertificate failed to parse DER");
118 const QCFType<CFDataRef> qtDerData = qtCert.toDer().toCFData();
119 if (!checkDer(qtDerData,
"QSslCertificate")) {
120 qCWarning(lcX509) <<
"Faulty QSslCertificate is:" << qtCert;
133 QList<QSslCertificate> systemCerts;
138 for (
int dom = kSecTrustSettingsDomainUser; dom <=
int(kSecTrustSettingsDomainSystem); dom++) {
139 QCFType<CFArrayRef> cfCerts;
140 OSStatus status = SecTrustSettingsCopyCertificates(SecTrustSettingsDomain(dom), &cfCerts);
141 if (status == noErr) {
142 const CFIndex size = CFArrayGetCount(cfCerts);
143 for (CFIndex i = 0; i < size; ++i) {
144 SecCertificateRef cfCert = (SecCertificateRef)CFArrayGetValueAtIndex(cfCerts, i);
145 QCFType<CFDataRef> derData = SecCertificateCopyData(cfCert);
146 if (isCaCertificateTrusted(cfCert, dom)) {
148 const auto newCert = QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
149 if (!canDERBeParsed(derData, newCert)) {
154 systemCerts << newCert;
158 qCWarning(lcX509,
"SecCertificateCopyData returned invalid DER data (nullptr).");
Namespace containing onternal types that TLS backends implement.
QList< QSslCertificate > systemCaCertificates()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")