mirror of
https://github.com/nextcloud/desktop.git
synced 2024-12-15 18:21:35 +03:00
36967122db
Also get rid of the list of different version. We always only support one Qt version for macOS and Windows, and the list of patches will be based on that supported version.
276 lines
10 KiB
Diff
276 lines
10 KiB
Diff
From 9d1120db0973ea7741b13a6555b20ae61f6d037e Mon Sep 17 00:00:00 2001
|
|
From: Daniel Molkentin <danimo@owncloud.com>
|
|
Date: Wed, 25 Nov 2015 12:37:27 +0100
|
|
Subject: [PATCH] QSslSocket: evaluate CAs in all keychain categories
|
|
|
|
This will make sure that certs in the domainUser (login),
|
|
and domainAdmin (per machine) keychain are being picked up
|
|
in systemCaCertificates() in addition to the (usually immutable)
|
|
DomainSystem keychain.
|
|
|
|
Also consider the trust settings on OS X: If a certificate
|
|
is either fully trusted or trusted for the purpose of SSL,
|
|
it will be accepted.
|
|
|
|
[ChangeLog][Platform Specific Changes] OS X now accepts trusted
|
|
certificates from the login and system keychains.
|
|
|
|
(Backport of fe3a84138e266c425f11353f7d8dc28a588af89e)
|
|
|
|
Task-number: QTBUG-32898
|
|
Change-Id: Ia23083d5af74388eeee31ba07239735cbbe64368
|
|
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
|
|
---
|
|
src/network/ssl/qsslsocket.cpp | 4 +
|
|
src/network/ssl/qsslsocket_mac_shared.cpp | 148 ++++++++++++++++++++++++++++++
|
|
src/network/ssl/qsslsocket_openssl.cpp | 30 +-----
|
|
src/network/ssl/ssl.pri | 4 +-
|
|
4 files changed, 158 insertions(+), 28 deletions(-)
|
|
create mode 100644 src/network/ssl/qsslsocket_mac_shared.cpp
|
|
|
|
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
|
|
index 549906a..7b202b0 100644
|
|
--- a/src/network/ssl/qsslsocket.cpp
|
|
+++ b/src/network/ssl/qsslsocket.cpp
|
|
@@ -1508,6 +1508,10 @@ QList<QSslCertificate> QSslSocket::defaultCaCertificates()
|
|
returned by defaultCaCertificates(). You can replace that database
|
|
with your own with setDefaultCaCertificates().
|
|
|
|
+ \note: On OS X, only certificates that are either trusted for all
|
|
+ purposes or trusted for the purpose of SSL in the keychain will be
|
|
+ returned.
|
|
+
|
|
\sa caCertificates(), defaultCaCertificates(), setDefaultCaCertificates()
|
|
*/
|
|
QList<QSslCertificate> QSslSocket::systemCaCertificates()
|
|
diff --git a/src/network/ssl/qsslsocket_mac_shared.cpp b/src/network/ssl/qsslsocket_mac_shared.cpp
|
|
new file mode 100644
|
|
index 0000000..60fea4c
|
|
--- /dev/null
|
|
+++ b/src/network/ssl/qsslsocket_mac_shared.cpp
|
|
@@ -0,0 +1,148 @@
|
|
+/****************************************************************************
|
|
+**
|
|
+** Copyright (C) 2015 The Qt Company Ltd.
|
|
+** Copyright (C) 2015 ownCloud Inc
|
|
+** Contact: http://www.qt.io/licensing/
|
|
+**
|
|
+** This file is part of the QtNetwork module of the Qt Toolkit.
|
|
+**
|
|
+** $QT_BEGIN_LICENSE:LGPL21$
|
|
+** Commercial License Usage
|
|
+** Licensees holding valid commercial Qt licenses may use this file in
|
|
+** accordance with the commercial license agreement provided with the
|
|
+** Software or, alternatively, in accordance with the terms contained in
|
|
+** a written agreement between you and The Qt Company. For licensing terms
|
|
+** and conditions see http://www.qt.io/terms-conditions. For further
|
|
+** information use the contact form at http://www.qt.io/contact-us.
|
|
+**
|
|
+** GNU Lesser General Public License Usage
|
|
+** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
+** General Public License version 2.1 or version 3 as published by the Free
|
|
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
+** following information to ensure the GNU Lesser General Public License
|
|
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
+**
|
|
+** As a special exception, The Qt Company gives you certain additional
|
|
+** rights. These rights are described in The Qt Company LGPL Exception
|
|
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
+**
|
|
+** $QT_END_LICENSE$
|
|
+**
|
|
+****************************************************************************/
|
|
+
|
|
+//#define QSSLSOCKET_DEBUG
|
|
+//#define QT_DECRYPT_SSL_TRAFFIC
|
|
+
|
|
+#include "qsslsocket.h"
|
|
+
|
|
+#ifndef QT_NO_OPENSSL
|
|
+# include "qsslsocket_openssl_p.h"
|
|
+# include "qsslsocket_openssl_symbols_p.h"
|
|
+#endif
|
|
+
|
|
+#include "qsslcertificate_p.h"
|
|
+
|
|
+#ifdef Q_OS_DARWIN
|
|
+# include <private/qcore_mac_p.h>
|
|
+#endif
|
|
+
|
|
+#include <QtCore/qdebug.h>
|
|
+
|
|
+#ifdef Q_OS_OSX
|
|
+# include <Security/Security.h>
|
|
+#endif
|
|
+
|
|
+
|
|
+QT_BEGIN_NAMESPACE
|
|
+
|
|
+#ifdef Q_OS_OSX
|
|
+namespace {
|
|
+
|
|
+bool hasTrustedSslServerPolicy(SecPolicyRef policy, CFDictionaryRef props) {
|
|
+ QCFType<CFDictionaryRef> policyProps = SecPolicyCopyProperties(policy);
|
|
+ // only accept certificates with policies for SSL server validation for now
|
|
+ if (CFEqual(CFDictionaryGetValue(policyProps, kSecPolicyOid), kSecPolicyAppleSSL)) {
|
|
+ CFBooleanRef policyClient;
|
|
+ if (CFDictionaryGetValueIfPresent(policyProps, kSecPolicyClient, reinterpret_cast<const void**>(&policyClient)) &&
|
|
+ CFEqual(policyClient, kCFBooleanTrue)) {
|
|
+ return false; // no client certs
|
|
+ }
|
|
+ if (!CFDictionaryContainsKey(props, kSecTrustSettingsResult)) {
|
|
+ // as per the docs, no trust settings result implies full trust
|
|
+ return true;
|
|
+ }
|
|
+ CFNumberRef number = static_cast<CFNumberRef>(CFDictionaryGetValue(props, kSecTrustSettingsResult));
|
|
+ SecTrustSettingsResult settingsResult;
|
|
+ CFNumberGetValue(number, kCFNumberSInt32Type, &settingsResult);
|
|
+ switch (settingsResult) {
|
|
+ case kSecTrustSettingsResultTrustRoot:
|
|
+ case kSecTrustSettingsResultTrustAsRoot:
|
|
+ return true;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool isCaCertificateTrusted(SecCertificateRef cfCert, int domain)
|
|
+{
|
|
+ QCFType<CFArrayRef> cfTrustSettings;
|
|
+ OSStatus status = SecTrustSettingsCopyTrustSettings(cfCert, domain, &cfTrustSettings);
|
|
+ if (status == noErr) {
|
|
+ CFIndex size = CFArrayGetCount(cfTrustSettings);
|
|
+ // if empty, trust for everything (as per the Security Framework documentation)
|
|
+ if (size == 0) {
|
|
+ return true;
|
|
+ } else {
|
|
+ for (CFIndex i = 0; i < size; ++i) {
|
|
+ CFDictionaryRef props = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(cfTrustSettings, i));
|
|
+ if (CFDictionaryContainsKey(props, kSecTrustSettingsPolicy)) {
|
|
+ if (hasTrustedSslServerPolicy((SecPolicyRef)CFDictionaryGetValue(props, kSecTrustSettingsPolicy), props))
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ qWarning("Error receiving trust for a CA certificate");
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+} // anon namespace
|
|
+#endif // Q_OS_OSX
|
|
+
|
|
+QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
|
|
+{
|
|
+ ensureInitialized();
|
|
+
|
|
+ QList<QSslCertificate> systemCerts;
|
|
+ // SecTrustSettingsCopyCertificates is not defined on iOS.
|
|
+#ifdef Q_OS_OSX
|
|
+ QCFType<CFArrayRef> cfCerts;
|
|
+ // iterate through all enum members, order:
|
|
+ // kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem
|
|
+ for (int dom = kSecTrustSettingsDomainUser; dom <= kSecTrustSettingsDomainSystem; dom++) {
|
|
+ OSStatus status = SecTrustSettingsCopyCertificates(dom, &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 (::isCaCertificateTrusted(cfCert, dom)) {
|
|
+ if (derData == NULL) {
|
|
+ qWarning("Error retrieving a CA certificate from the system store");
|
|
+ } else {
|
|
+ systemCerts << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ return systemCerts;
|
|
+}
|
|
+
|
|
+QT_END_NAMESPACE
|
|
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
|
|
index 415f147..7a3cb42 100644
|
|
--- a/src/network/ssl/qsslsocket_openssl.cpp
|
|
+++ b/src/network/ssl/qsslsocket_openssl.cpp
|
|
@@ -76,14 +76,6 @@
|
|
|
|
#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_WIN)
|
|
@@ -672,6 +664,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves()
|
|
setDefaultSupportedEllipticCurves(curves);
|
|
}
|
|
|
|
+#ifndef Q_OS_DARWIN // Apple implementation in qsslsocket_mac_shared.cpp
|
|
QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
|
|
{
|
|
ensureInitialized();
|
|
@@ -680,25 +673,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
|
|
timer.start();
|
|
#endif
|
|
QList<QSslCertificate> systemCerts;
|
|
- // 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);
|
|
- }
|
|
- }
|
|
- }
|
|
-#elif defined(Q_OS_WIN)
|
|
+#if defined(Q_OS_WIN)
|
|
if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
|
|
HCERTSTORE hSystemStore;
|
|
#if defined(Q_OS_WINCE)
|
|
@@ -775,6 +750,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
|
|
|
|
return systemCerts;
|
|
}
|
|
+#endif // Q_OS_DARWIN
|
|
|
|
void QSslSocketBackendPrivate::startClientEncryption()
|
|
{
|
|
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
|
|
index 29c47cd..8eb605b 100644
|
|
--- a/src/network/ssl/ssl.pri
|
|
+++ b/src/network/ssl/ssl.pri
|
|
@@ -62,7 +62,9 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
|
|
ssl/qsslsocket_openssl.cpp \
|
|
ssl/qsslsocket_openssl_symbols.cpp
|
|
|
|
-android:!android-no-sdk: SOURCES += ssl/qsslsocket_openssl_android.cpp
|
|
+ darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp
|
|
+
|
|
+ android:!android-no-sdk: SOURCES += ssl/qsslsocket_openssl_android.cpp
|
|
|
|
# Add optional SSL libs
|
|
# Static linking of OpenSSL with msvc:
|