From e6bccb1f0d8ca59acb1ffdac74a823c06346e7f3 Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel@molkentin.de>
Date: Mon, 16 Nov 2015 15:02:37 +0100
Subject: [PATCH] Remove legacy platform code in QSslSocket for OS X < 10.5

This avoids manual symbol lookups and makes the code more readable.
Mark identical code.

Also use smart pointers instead of manual memory management.

(Backport of d42d7781f1cd62c3c7c008859507f24a1ff5bb2a to Qt 5.4)

Change-Id: I62820313dce87de6623cdc87b6e1361200ed7822
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>

Conflicts:
	src/network/ssl/qsslsocket_openssl.cpp
---
 src/network/ssl/qsslsocket_openssl.cpp | 81 +++++++++++-----------------------
 src/network/ssl/qsslsocket_p.h         |  6 +--
 2 files changed, 26 insertions(+), 61 deletions(-)

diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 82644c1..415f147 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -76,14 +76,17 @@
 
 #include <string.h>
 
+#ifdef Q_OS_DARWIN
+#  include <private/qcore_mac_p.h>
+#endif
+
+#ifdef Q_OS_OSX
+#  include <Security/Security.h>
+#endif
+
 QT_BEGIN_NAMESPACE
 
-#if defined(Q_OS_MACX)
-#define kSecTrustSettingsDomainSystem 2 // so we do not need to include the header file
-    PtrSecCertificateCopyData QSslSocketPrivate::ptrSecCertificateCopyData = 0;
-    PtrSecTrustSettingsCopyCertificates QSslSocketPrivate::ptrSecTrustSettingsCopyCertificates = 0;
-    PtrSecTrustCopyAnchorCertificates QSslSocketPrivate::ptrSecTrustCopyAnchorCertificates = 0;
-#elif defined(Q_OS_WIN)
+#if defined(Q_OS_WIN)
     PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0;
     PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0;
     PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0;
@@ -509,23 +512,7 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
 
 #ifndef QT_NO_LIBRARY
     //load symbols needed to receive certificates from system store
-#if defined(Q_OS_MACX)
-    QLibrary securityLib("/System/Library/Frameworks/Security.framework/Versions/Current/Security");
-    if (securityLib.load()) {
-        ptrSecCertificateCopyData = (PtrSecCertificateCopyData) securityLib.resolve("SecCertificateCopyData");
-        if (!ptrSecCertificateCopyData)
-            qCWarning(lcSsl, "could not resolve symbols in security library"); // should never happen
-
-        ptrSecTrustSettingsCopyCertificates = (PtrSecTrustSettingsCopyCertificates) securityLib.resolve("SecTrustSettingsCopyCertificates");
-        if (!ptrSecTrustSettingsCopyCertificates) { // method was introduced in Leopard, use legacy method if it's not there
-            ptrSecTrustCopyAnchorCertificates = (PtrSecTrustCopyAnchorCertificates) securityLib.resolve("SecTrustCopyAnchorCertificates");
-            if (!ptrSecTrustCopyAnchorCertificates)
-                qCWarning(lcSsl, "could not resolve symbols in security library"); // should never happen
-        }
-    } else {
-        qCWarning(lcSsl, "could not load security library");
-    }
-#elif defined(Q_OS_WIN)
+#if defined(Q_OS_WIN)
     HINSTANCE hLib = LoadLibraryW(L"Crypt32");
     if (hLib) {
 #if defined(Q_OS_WINCE)
@@ -693,40 +680,22 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
     timer.start();
 #endif
     QList<QSslCertificate> systemCerts;
-#if defined(Q_OS_MACX)
-    CFArrayRef cfCerts;
-    OSStatus status = 1;
-
-    CFDataRef SecCertificateCopyData (
-       SecCertificateRef certificate
-    );
-
-    if (ptrSecCertificateCopyData) {
-        if (ptrSecTrustSettingsCopyCertificates)
-            status = ptrSecTrustSettingsCopyCertificates(kSecTrustSettingsDomainSystem, &cfCerts);
-        else if (ptrSecTrustCopyAnchorCertificates)
-            status = ptrSecTrustCopyAnchorCertificates(&cfCerts);
-        if (!status) {
-            CFIndex size = CFArrayGetCount(cfCerts);
-            for (CFIndex i = 0; i < size; ++i) {
-                SecCertificateRef cfCert = (SecCertificateRef)CFArrayGetValueAtIndex(cfCerts, i);
-                CFDataRef data;
-
-                data = ptrSecCertificateCopyData(cfCert);
-
-                if (data == NULL) {
-                    qCWarning(lcSsl, "error retrieving a CA certificate from the system store");
-                } else {
-                    QByteArray rawCert = QByteArray::fromRawData((const char *)CFDataGetBytePtr(data), CFDataGetLength(data));
-                    systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der));
-                    CFRelease(data);
-                }
+    // note: also check implementation in openssl_mac.cpp
+#if defined(Q_OS_OSX)
+    // SecTrustSettingsCopyCertificates is not defined on iOS.
+    QCFType<CFArrayRef> cfCerts;
+
+    OSStatus status = SecTrustSettingsCopyCertificates(kSecTrustSettingsDomainSystem, &cfCerts);
+    if (status == noErr ) {
+        const CFIndex size = CFArrayGetCount(cfCerts);
+        for (CFIndex i = 0; i < size; ++i) {
+            SecCertificateRef cfCert = (SecCertificateRef)CFArrayGetValueAtIndex(cfCerts, i);
+            QCFType<CFDataRef> derData = SecCertificateCopyData(cfCert);
+            if (derData == NULL) {
+                qWarning("error retrieving a CA certificate from the system store");
+            } else {
+                systemCerts << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
             }
-            CFRelease(cfCerts);
-        }
-        else {
-           // no detailed error handling here
-           qCWarning(lcSsl, "could not retrieve system CA certificates");
         }
     }
 #elif defined(Q_OS_WIN)
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index d651971..17cc7b4 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -151,11 +151,7 @@ public:
     static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName);
     Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
 
-#if defined(Q_OS_MACX)
-    static PtrSecCertificateCopyData ptrSecCertificateCopyData;
-    static PtrSecTrustSettingsCopyCertificates ptrSecTrustSettingsCopyCertificates;
-    static PtrSecTrustCopyAnchorCertificates ptrSecTrustCopyAnchorCertificates;
-#elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
     static PtrCertOpenSystemStoreW ptrCertOpenSystemStoreW;
     static PtrCertFindCertificateInStore ptrCertFindCertificateInStore;
     static PtrCertCloseStore ptrCertCloseStore;
