summaryrefslogtreecommitdiffstats
path: root/src/network/ssl
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-08-14 09:05:42 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2013-08-14 09:06:31 +0200
commit5c23199d4e8ff21661dfa5aacc13149178e78cab (patch)
tree322aee61581d7c85f1ccb65e47d1e79eba1ba6c9 /src/network/ssl
parent252bad7c589e03d3e12df02354b00a84d8e3159a (diff)
parentc8d9b17367cfdcb034d11f8a168ca4ae3993e7c3 (diff)
Merge remote-tracking branch 'origin/stable' into dev
Conflicts: configure mkspecs/macx-xcode/Info.plist.app mkspecs/macx-xcode/Info.plist.lib qmake/doc/qmake.qdocconf src/corelib/global/qglobal.h tests/auto/other/exceptionsafety/exceptionsafety.pro tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp Change-Id: I3c769a4a82dc2e99a12c69123fbf17613fd2ac2a
Diffstat (limited to 'src/network/ssl')
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp67
-rw-r--r--src/network/ssl/qsslsocket_openssl_android.cpp179
-rw-r--r--src/network/ssl/qsslsocket_p.h3
-rw-r--r--src/network/ssl/ssl.pri2
4 files changed, 222 insertions, 29 deletions
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 69181f40b4..e94df10fed 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -522,6 +522,8 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
} else {
qWarning("could not load crypt32 library"); // should never happen
}
+#elif defined(Q_OS_QNX)
+ s_loadRootCertsOnDemand = true;
#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
// check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
QList<QByteArray> dirs = unixRootCertDirectories();
@@ -686,41 +688,48 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
}
#elif defined(Q_OS_UNIX)
QSet<QString> certFiles;
-# ifdef Q_OS_ANDROID
- QList<QByteArray> directories;
- directories << qgetenv("MINISTRO_SSL_CERTS_PATH"); // Set by Ministro
-# else
- QList<QByteArray> directories = unixRootCertDirectories();
-# endif
QDir currentDir;
QStringList nameFilters;
-# ifdef Q_OS_ANDROID
- nameFilters << QLatin1String("*.der");
-#else
+ QList<QByteArray> directories;
+ QSsl::EncodingFormat platformEncodingFormat;
+# ifndef Q_OS_ANDROID
+ directories = unixRootCertDirectories();
nameFilters << QLatin1String("*.pem") << QLatin1String("*.crt");
-# endif
- currentDir.setNameFilters(nameFilters);
- for (int a = 0; a < directories.count(); a++) {
- currentDir.setPath(QLatin1String(directories.at(a)));
- QDirIterator it(currentDir);
- while(it.hasNext()) {
- it.next();
- // use canonical path here to not load the same certificate twice if symlinked
- certFiles.insert(it.fileInfo().canonicalFilePath());
- }
- }
- QSetIterator<QString> it(certFiles);
- while(it.hasNext()) {
-# ifdef Q_OS_ANDROID
- systemCerts.append(QSslCertificate::fromPath(it.next(), QSsl::Der));
+ platformEncodingFormat = QSsl::Pem;
# else
- systemCerts.append(QSslCertificate::fromPath(it.next(), QSsl::Pem));
-# endif
- }
+ // Q_OS_ANDROID
+ QByteArray ministroPath = qgetenv("MINISTRO_SSL_CERTS_PATH"); // Set by Ministro
+ directories << ministroPath;
+ nameFilters << QLatin1String("*.der");
+ platformEncodingFormat = QSsl::Der;
+# ifndef Q_OS_ANDROID_NO_SDK
+ if (ministroPath.isEmpty()) {
+ QList<QByteArray> certificateData = fetchSslCertificateData();
+ for (int i = 0; i < certificateData.size(); ++i) {
+ systemCerts.append(QSslCertificate::fromData(certificateData.at(i), QSsl::Der));
+ }
+ } else
+# endif //Q_OS_ANDROID_NO_SDK
+# endif //Q_OS_ANDROID
+ {
+ currentDir.setNameFilters(nameFilters);
+ for (int a = 0; a < directories.count(); a++) {
+ currentDir.setPath(QLatin1String(directories.at(a)));
+ QDirIterator it(currentDir);
+ while (it.hasNext()) {
+ it.next();
+ // use canonical path here to not load the same certificate twice if symlinked
+ certFiles.insert(it.fileInfo().canonicalFilePath());
+ }
+ }
+ QSetIterator<QString> it(certFiles);
+ while (it.hasNext())
+ systemCerts.append(QSslCertificate::fromPath(it.next(), platformEncodingFormat));
# ifndef Q_OS_ANDROID
- systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva
- systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss
+ systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva
+ systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss
# endif
+ }
#endif
#ifdef QSSLSOCKET_DEBUG
qDebug() << "systemCaCertificates retrieval time " << timer.elapsed() << "ms";
diff --git a/src/network/ssl/qsslsocket_openssl_android.cpp b/src/network/ssl/qsslsocket_openssl_android.cpp
new file mode 100644
index 0000000000..fa612a75a6
--- /dev/null
+++ b/src/network/ssl/qsslsocket_openssl_android.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** In addition, as a special exception, the copyright holders listed above give
+** permission to link the code of its release of Qt with the OpenSSL project's
+** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
+** same license as the original version), and distribute the linked executables.
+**
+** You must comply with the GNU General Public License version 2 in all
+** respects for all of the code used other than the "OpenSSL" code. If you
+** modify this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version of this file.
+**
+****************************************************************************/
+
+#include "qsslsocket_openssl_p.h"
+
+
+
+#include <jni.h>
+#include <android/log.h>
+
+static JavaVM *javaVM = 0;
+static jclass appClass;
+
+static jmethodID getSslCertificatesMethodID;
+
+struct AttachedJNIEnv
+{
+ AttachedJNIEnv()
+ {
+ attached = false;
+ if (javaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) {
+ if (javaVM->AttachCurrentThread(&jniEnv, NULL) < 0) {
+ __android_log_print(ANDROID_LOG_ERROR, "Qt", "AttachCurrentThread failed");
+ jniEnv = 0;
+ return;
+ }
+ attached = true;
+ }
+ }
+
+ ~AttachedJNIEnv()
+ {
+ if (attached)
+ javaVM->DetachCurrentThread();
+ }
+ bool attached;
+ JNIEnv *jniEnv;
+};
+
+static const char logTag[] = "Qt";
+static const char classErrorMsg[] = "Can't find class \"%s\"";
+static const char methodErrorMsg[] = "Can't find method \"%s%s\"";
+
+
+#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
+clazz = env->FindClass(CLASS_NAME); \
+if (!clazz) { \
+ __android_log_print(ANDROID_LOG_FATAL, logTag, classErrorMsg, CLASS_NAME); \
+ return JNI_FALSE; \
+}
+
+#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
+VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \
+if (!VAR) { \
+ __android_log_print(ANDROID_LOG_FATAL, logTag, methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \
+ return JNI_FALSE; \
+}
+
+static bool registerNatives(JNIEnv *env)
+{
+ jclass clazz;
+ FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative");
+ appClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+#if 0 //we don't call C++ functions from Java at this time
+ if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives failed");
+ return JNI_FALSE;
+ }
+#endif
+
+ GET_AND_CHECK_STATIC_METHOD(getSslCertificatesMethodID, appClass, "getSSLCertificates", "()[[B");
+
+ return true;
+}
+
+Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/)
+{
+ typedef union {
+ JNIEnv *nativeEnvironment;
+ void *venv;
+ } UnionJNIEnvToVoid;
+
+ __android_log_print(ANDROID_LOG_INFO, logTag, "Network start");
+ UnionJNIEnvToVoid uenv;
+ uenv.venv = NULL;
+ javaVM = 0;
+
+ if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed");
+ return -1;
+ }
+ JNIEnv *env = uenv.nativeEnvironment;
+ if (!registerNatives(env)) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "registerNatives failed");
+ return -1;
+ }
+
+ javaVM = vm;
+ return JNI_VERSION_1_4;
+}
+
+QList<QByteArray> QSslSocketPrivate::fetchSslCertificateData()
+{
+ QList<QByteArray> certificateData;
+ AttachedJNIEnv env;
+
+ if (env.jniEnv) {
+ jobjectArray jcertificates =
+ static_cast<jobjectArray>(env.jniEnv->CallStaticObjectMethod(appClass, getSslCertificatesMethodID));
+ jint nCertificates = env.jniEnv->GetArrayLength(jcertificates);
+
+ for (int i = 0; i < nCertificates; ++i) {
+ jbyteArray jCert = static_cast<jbyteArray>(env.jniEnv->GetObjectArrayElement(jcertificates, i));
+
+ const uint sz = env.jniEnv->GetArrayLength(jCert);
+ jbyte *buffer = env.jniEnv->GetByteArrayElements(jCert, 0);
+ certificateData.append(QByteArray(reinterpret_cast<char*>(buffer), sz));
+
+ env.jniEnv->ReleaseByteArrayElements(jCert, buffer, JNI_ABORT); // don't copy back the elements
+ env.jniEnv->DeleteLocalRef(jCert);
+ }
+ }
+
+ return certificateData;
+}
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 4fed101a80..6281753225 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -197,6 +197,9 @@ public:
private:
static bool ensureLibraryLoaded();
static void ensureCiphersAndCertsLoaded();
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
+ static QList<QByteArray> fetchSslCertificateData();
+#endif
static bool s_libraryLoaded;
static bool s_loadedCiphersAndCerts;
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
index 1d8c8e1ab7..0fe231357b 100644
--- a/src/network/ssl/ssl.pri
+++ b/src/network/ssl/ssl.pri
@@ -28,6 +28,8 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
ssl/qsslcertificateextension.cpp \
ssl/qsslcontext.cpp
+android:!android-no-sdk: SOURCES += ssl/qsslsocket_openssl_android.cpp
+
# Add optional SSL libs
# Static linking of OpenSSL with msvc:
# - Binaries http://slproweb.com/products/Win32OpenSSL.html