[SCM] ktp-auth-handler packaging branch, master, updated. debian/15.12.1-2-282-g080758e

Maximiliano Curia maxy at moszumanska.debian.org
Fri May 27 23:58:55 UTC 2016


Gitweb-URL: http://git.debian.org/?p=pkg-kde/applications/ktp-auth-handler.git;a=commitdiff;h=b553543

The following commit has been merged in the master branch:
commit b55354344d4dd3078a340da78f761c34770552d0
Author: Dan Vrátil <dvratil at redhat.com>
Date:   Tue Feb 5 12:39:34 2013 +0100

    Support TLS channels
    
    Certificates are verified against user's CAs and rules stored
    in KSslCertificateManager.
---
 CMakeLists.txt                |  19 ++--
 kssl/kssl.h                   | 169 +++++++++++++++++++++++++++++++++++
 kssl/ksslcertificatemanager.h |  99 +++++++++++++++++++++
 kssl/ksslinfodialog.h         | 101 +++++++++++++++++++++
 kssl/ksslsettings.h           | 169 +++++++++++++++++++++++++++++++++++
 main.cpp                      |   3 -
 tls-cert-verifier-op.cpp      | 199 ++++++++++++++++++++++++++++++++++++------
 tls-cert-verifier-op.h        |  12 +++
 8 files changed, 730 insertions(+), 41 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 417554a..a12225a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,19 +13,19 @@ find_package (KDE4 4.4.75 REQUIRED)
 find_package (TelepathyQt4 0.8.9 REQUIRED)
 find_package (KTp REQUIRED)
 find_package (QJSON REQUIRED)
+find_package (QCA2 REQUIRED)
 
 include (KDE4Defaults)
 include (MacroLibrary)
 
-add_definitions (${KDE4_DEFINITIONS}
-                 -DQT_NO_CAST_FROM_ASCII
-                 -DQT_NO_KEYWORDS
-)
+add_definitions (${KDE4_DEFINITIONS})
 
 include_directories (${KDE4_INCLUDES}
                      ${TELEPATHY_QT4_INCLUDE_DIR}
                      ${KTP_INCLUDE_DIR}
                      ${QJSON_INCLUDE_DIR}
+                     ${QCA2_INCLUDE_DIR}
+                     ${CMAKE_CURRENT_SOURCE_DIR}/kssl
 )
 
 set(ktp_auth_handler_SRCS
@@ -61,12 +61,13 @@ target_link_libraries(ktp-auth-handler
     ${KDE4_KDEUI_LIBS}
     ${KDE4_KDEWEBKIT_LIBS}
     ${QJSON_LIBRARIES}
+    ${QCA2_LIBRARIES}
 )
 
 configure_file(org.freedesktop.Telepathy.Client.KTp.SASLHandler.service.in
                ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.SASLHandler.service)
-#configure_file(org.freedesktop.Telepathy.Client.KTp.TLSHandler.service.in
-#               ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.TLSHandler.service)
+configure_file(org.freedesktop.Telepathy.Client.KTp.TLSHandler.service.in
+               ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.TLSHandler.service)
 
 configure_file(org.freedesktop.Telepathy.Client.KTp.ConfAuthObserver.service.in
 	${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.ConfAuthObserver.service)
@@ -75,8 +76,8 @@ install(TARGETS ktp-auth-handler DESTINATION ${LIBEXEC_INSTALL_DIR})
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.SASLHandler.service
 	      ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.ConfAuthObserver.service
         DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
-#install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.TLSHandler.service
-#        DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.KTp.TLSHandler.service
+        DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
 install(FILES KTp.SASLHandler.client DESTINATION ${SHARE_INSTALL_PREFIX}/telepathy/clients/)
-#install(FILES KTp.TLSHandler.client DESTINATION ${SHARE_INSTALL_PREFIX}/telepathy/clients/)
+install(FILES KTp.TLSHandler.client DESTINATION ${SHARE_INSTALL_PREFIX}/telepathy/clients/)
 install(FILES KTp.ConfAuthObserver.client DESTINATION ${SHARE_INSTALL_PREFIX}/telepathy/clients/)
diff --git a/kssl/kssl.h b/kssl/kssl.h
new file mode 100644
index 0000000..0d3d294
--- /dev/null
+++ b/kssl/kssl.h
@@ -0,0 +1,169 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000-2005 George Staikos <staikos at kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _KSSL_H
+#define _KSSL_H
+
+#include <ksslsettings.h>
+
+class QIODevice;
+class KSSLPrivate;
+class KSSLSession;
+
+/**
+ * KDE SSL Wrapper Class
+ *
+ * This class implements KDE's SSL support by wrapping OpenSSL.
+ *
+ * @author George Staikos <staikos at kde.org>
+ * @see KExtendedSocket, TCPSlaveBase
+ * @short KDE SSL Class
+ */
+class KIO_EXPORT KSSL {
+public:
+	/**
+	 *  Construct a KSSL object
+	 *
+	 *  @param init Set this to false if you do not want this class to
+	 *         immediately initialize OpenSSL.
+	 */
+	KSSL(bool init = true);
+
+	/**
+	 *  Destroy this KSSL object
+	 *
+	 *  Does not close any socket.
+	 */
+	~KSSL();
+
+	/**
+	 *  Determine if SSL is available and works.
+	 *
+	 *  @return true is SSL is available and usable
+	 */
+	static bool doesSSLWork();
+
+	/**
+	 *  Initialize OpenSSL.
+	 *
+	 *  @return true on success
+	 *
+	 *  This will do nothing if it is already initialized.
+	 *  @see reInitialize
+	 */
+	bool initialize();
+
+	/**
+	 *  This is used for applicationss which do STARTTLS or something
+	 *  similar. It creates a TLS method regardless of the user's settings.
+	 *
+	 *  @return true if TLS is successfully initialized
+	 */
+	bool TLSInit();
+
+	/**
+	 *  Set an SSL session to use.  This deep copies the session so it
+	 *  doesn't have to remain valid.  You need to call it after calling
+	 *  initialize or reInitialize.  The ID is cleared in close().
+	 *
+	 *  @param session A valid session to reuse.  If 0L, it will clear the
+	 *                 session ID in memory.
+	 *
+	 *  @return true on success
+	 */
+	bool setSession(const KSSLSession *session);
+
+	/**
+	 *  Close the SSL session.
+	 */
+	void close();
+
+	/**
+	 *  Reinitialize OpenSSL.
+	 *
+	 *  @return true on success
+	 *
+	 *  This is not generally needed unless you are reusing the KSSL object
+	 *  for a new session.
+	 *  @see initialize
+	 */
+	bool reInitialize();
+
+	/**
+	 *  Trigger a reread of KSSL configuration and reInitialize() KSSL.
+	 *
+	 *  @return true on successful reinitalizations
+	 *
+	 *  If you setAutoReconfig() to false, then this will simply
+	 * reInitialize() and not read in the new configuration.
+	 *  @see setAutoReconfig
+	 */
+	bool reconfig();
+
+	/**
+	 *  Enable or disable automatic reconfiguration on initialize().
+	 *
+	 *  @param ar Set to false in order to disable auto-reloading of the
+	 *         KSSL configuration during initialize().
+	 *
+	 *  By default, KSSL will read its configuration on initialize().  You
+	 *  might want to disable this for performance reasons.
+	 */
+	void setAutoReconfig(bool ar);
+
+	/**
+	 *  This will reseed the pseudo-random number generator with the EGD
+	 *  (entropy gathering daemon) if the EGD is configured and enabled.
+	 *  You don't need to call this yourself normally.
+	 *
+	 *  @return 0 on success
+	 */
+	int seedWithEGD();
+
+	/**
+	 *  Set a new KSSLSettings instance as the settings. This deletes the
+	 *  current instance of KSSLSettings.
+	 *
+	 *  @param settings A new, valid settings object.
+	 *
+	 *  @return true on success
+	 */
+	bool setSettings(KSSLSettings *settings);
+
+	/**
+	 *  One is built by the constructor, so this will only return a NULL
+	 *  pointer if you set one with setSettings().
+	 *
+	 *  @return the current settings instance
+	 */
+	KSSLSettings * settings();
+
+private:
+	static bool m_bSSLWorks;
+	bool m_bInit;
+	bool m_bAutoReconfig;
+	KSSLSettings *m_cfg;
+
+	KSSLPrivate *d;
+};
+
+
+#endif
+
diff --git a/kssl/ksslcertificatemanager.h b/kssl/ksslcertificatemanager.h
new file mode 100644
index 0000000..4942203
--- /dev/null
+++ b/kssl/ksslcertificatemanager.h
@@ -0,0 +1,99 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2007, 2008, 2010 Andreas Hartmetz <ahartmetz at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _INCLUDE_KSSLCERTIFICATEMANAGER_H
+#define _INCLUDE_KSSLCERTIFICATEMANAGER_H
+
+#include "ktcpsocket.h"
+
+#include <QtNetwork/QSslCertificate>
+#include <QtNetwork/QSslError>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QDate>
+
+class QSslCertificate;
+class KSslCertificateRulePrivate;
+class KSslCertificateManagerPrivate;
+
+//### document this... :/
+class KDECORE_EXPORT KSslCertificateRule
+{
+public:
+    KSslCertificateRule(const QSslCertificate &cert = QSslCertificate(),
+                        const QString &hostName = QString());
+    KSslCertificateRule(const KSslCertificateRule &other);
+    ~KSslCertificateRule();
+    KSslCertificateRule &operator=(const KSslCertificateRule &other);
+
+    QSslCertificate certificate() const;
+    QString hostName() const;
+    void setExpiryDateTime(const QDateTime &dateTime);
+    QDateTime expiryDateTime() const;
+    void setRejected(bool rejected);
+    bool isRejected() const;
+    bool isErrorIgnored(KSslError::Error error) const;
+    void setIgnoredErrors(const QList<KSslError::Error> &errors);
+    void setIgnoredErrors(const QList<KSslError> &errors);
+    QList<KSslError::Error> ignoredErrors() const;
+    QList<KSslError::Error> filterErrors(const QList<KSslError::Error> &errors) const;
+    QList<KSslError> filterErrors(const QList<KSslError> &errors) const;
+private:
+    KSslCertificateRulePrivate *const d;
+};
+
+
+//### document this too... :/
+class KDECORE_EXPORT KSslCertificateManager
+{
+public:
+    static KSslCertificateManager *self();
+    void setRule(const KSslCertificateRule &rule);
+    void clearRule(const KSslCertificateRule &rule);
+    void clearRule(const QSslCertificate &cert, const QString &hostName);
+    KSslCertificateRule rule(const QSslCertificate &cert, const QString &hostName) const;
+
+    // do not use, it does nothing!
+#ifndef KDE_NO_DEPRECATED
+    KDE_DEPRECATED void setRootCertificates(const QList<QSslCertificate> &rootCertificates)
+        { Q_UNUSED(rootCertificates) }
+#endif
+    // use caCertificates() instead
+#ifndef KDE_NO_DEPRECATED
+    KDE_DEPRECATED QList<QSslCertificate> rootCertificates() const
+        { return caCertificates(); }
+#endif
+
+    QList<QSslCertificate> caCertificates() const;
+
+    static QList<KSslError> nonIgnorableErrors(const QList<KSslError> &);
+    static QList<KSslError::Error> nonIgnorableErrors(const QList<KSslError::Error> &);
+
+private:
+    friend class KSslCertificateManagerContainer;
+    friend class KSslCertificateManagerPrivate;
+    KSslCertificateManager();
+    ~KSslCertificateManager();
+
+    KSslCertificateManagerPrivate *const d;
+};
+
+
+#endif
diff --git a/kssl/ksslinfodialog.h b/kssl/ksslinfodialog.h
new file mode 100644
index 0000000..b65c225
--- /dev/null
+++ b/kssl/ksslinfodialog.h
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000-2003 George Staikos <staikos at kde.org>
+ * Copyright (C) 2000 Malte Starostik <malte at kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _KSSLINFODIALOG_H
+#define _KSSLINFODIALOG_H
+
+#include <kssl.h>
+#include <kdialog.h>
+
+#include "ktcpsocket.h"
+
+/**
+ * KDE SSL Information Dialog
+ *
+ * This class creates a dialog that can be used to display information about
+ * an SSL session.
+ *
+ * There are NO GUARANTEES that KSslInfoDialog will remain binary compatible/
+ * Contact staikos at kde.org for details if needed.
+ *
+ * @author George Staikos <staikos at kde.org>
+ * @see KSSL
+ * @short KDE SSL Information Dialog
+ */
+class KIO_EXPORT KSslInfoDialog : public KDialog {
+	Q_OBJECT
+public:
+	/**
+	 *  Construct a KSSL Information Dialog
+	 *
+	 *  @param parent the parent widget
+	 */
+	explicit KSslInfoDialog(QWidget *parent = 0);
+
+	/**
+	 *  Destroy this dialog
+	 */
+	virtual ~KSslInfoDialog();
+
+	/**
+	 *  Tell the dialog if the connection has portions that may not be
+	 *  secure (ie. a mixture of secure and insecure frames)
+	 *
+	 *  @param isIt true if security is in question
+	 */
+	void setSecurityInQuestion(bool isIt);
+
+	/**
+	 *  Set information to display about the SSL connection.
+	 *
+	 *  @param certificateChain the certificate chain leading from the certificate
+     *         authority to the peer.
+	 *  @param ip the ip of the remote host
+	 *  @param host the remote hostname
+     *  @param sslProtocol the version of SSL in use (SSLv2, SSLv3, TLSv1)
+	 *  @param cipher the cipher in use
+	 *  @param usedBits the used bits of the key
+	 *  @param bits the key size of the cipher in use
+	 *  @param validationErrors errors validating the certificates, if any
+	 */
+	void setSslInfo(const QList<QSslCertificate> &certificateChain,
+			        const QString &ip, const QString &host,
+			        const QString &sslProtocol, const QString &cipher,
+                    int usedBits, int bits,
+			        const QList<QList<KSslError::Error> > &validationErrors);
+
+    void setMainPartEncrypted(bool);
+    void setAuxiliaryPartsEncrypted(bool);
+
+    static QList<QList<KSslError::Error> > errorsFromString(const QString &s);
+
+private:
+    void updateWhichPartsEncrypted();
+
+	class KSslInfoDialogPrivate;
+	KSslInfoDialogPrivate* const d;
+
+private Q_SLOTS:
+	void launchConfig();
+	void displayFromChain(int);
+};
+
+#endif
diff --git a/kssl/ksslsettings.h b/kssl/ksslsettings.h
new file mode 100644
index 0000000..d4af1d0
--- /dev/null
+++ b/kssl/ksslsettings.h
@@ -0,0 +1,169 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000-2003 George Staikos <staikos at kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _KSSLSETTINGS_H
+#define _KSSLSETTINGS_H
+
+#include <kio/kio_export.h>
+
+#include <QtCore/QString>
+
+#include <kconfig.h>
+
+class KSSLSettingsPrivate;
+
+/**
+ * KDE SSL Settings
+ *
+ * This class contains some of the SSL settings for easy use.
+ *
+ * @author George Staikos <staikos at kde.org>
+ * @see KSSL
+ * @short KDE SSL Settings
+ */
+class KIO_EXPORT KSSLSettings {
+public:
+	/**
+	 *  Construct a KSSL Settings object
+	 *
+	 *  @param readConfig read in the configuration immediately if true
+	 */
+	KSSLSettings(bool readConfig = true);
+
+	/**
+	 *  Destroy this KSSL Settings object
+	 */
+	~KSSLSettings();
+
+	/**
+	 *  Does the user want to be warned on entering SSL mode
+	 *  @return true if the user wants to be warned
+	 */
+	bool warnOnEnter() const;
+
+	/**
+	 *  Change the user's warnOnEnter() setting
+	 *  @param x true if the user is to be warned
+	 *  @see warnOnEnter
+	 */
+	void setWarnOnEnter(bool x);
+	
+	/**
+	 *  Does the user want to be warned on sending unencrypted data
+	 *  @return true if the user wants to be warned
+	 *  @see setWarnOnUnencrypted
+	 */
+	bool warnOnUnencrypted() const;
+
+	/**
+	 *  Change the user's warnOnUnencrypted() setting
+	 *  @param x true if the user is to be warned
+	 *  @see warnOnUnencrypted
+	 */
+	void setWarnOnUnencrypted(bool x);
+
+	/**
+	 *  Does the user want to be warned on leaving SSL mode
+	 *  @return true if the user wants to be warned
+	 */
+	bool warnOnLeave() const;
+
+	/**
+	 *  Change the user's warnOnLeave() setting
+	 *  @param x true if the user is to be warned
+	 *  @see warnOnLeave
+	 */
+	void setWarnOnLeave(bool x);
+	
+	/**
+	 *  Does the user want to be warned during mixed SSL/non-SSL mode
+	 *  @return true if the user wants to be warned
+	 */
+	bool warnOnMixed() const;
+
+	/**
+	 *  Does the user want to use the Entropy Gathering Daemon?
+	 *  @return true if the user wants to use EGD
+	 */
+	bool useEGD() const;
+
+	/**
+	 *  Does the user want to use an entropy file?
+	 *  @return true if the user wants to use an entropy file
+	 */
+	bool useEFile() const;
+  
+	/**
+	 *  Does the user want X.509 client certificates to always be sent when
+	 *  possible?
+	 *  @return true if the user always wants a certificate sent
+	 */
+	bool autoSendX509() const;
+
+	/**
+	 *  Does the user want to be prompted to send X.509 client certificates
+	 *  when possible?
+	 *  @return true if the user wants to be prompted
+	 */
+	bool promptSendX509() const;
+
+	/**
+	 *  Get the OpenSSL cipher list for selecting the list of ciphers to
+	 *  use in a connection.
+	 *  @return the cipher list
+	 */
+	QString getCipherList();
+
+	/**
+	 *  Get the configured path to the entropy gathering daemon or entropy
+	 *  file.
+	 *  @return the path
+	 */
+	QString& getEGDPath();
+
+	/**
+	 *  Load the user's settings.
+	 */
+	void load();
+
+	/**
+	 *  Revert to default settings.
+	 */
+	void defaults();
+
+	/**
+	 *  Save the current settings.
+	 */
+	void save();
+
+private:
+	KConfig *m_cfg;
+	bool m_bWarnOnEnter, m_bWarnOnUnencrypted, m_bWarnOnLeave, m_bWarnOnMixed;
+	bool m_bWarnSelfSigned, m_bWarnRevoked, m_bWarnExpired;
+
+	QList<QString> v3ciphers, v3selectedciphers;
+	QList<int> v3bits;
+
+	KSSLSettingsPrivate* const d;
+};
+
+
+#endif
+
diff --git a/main.cpp b/main.cpp
index 3350658..01e2235 100644
--- a/main.cpp
+++ b/main.cpp
@@ -83,14 +83,11 @@ int main(int argc, char *argv[])
 	    kWarning() << "Could not register the room auth observer!";
     }
 
-
-#if 0
     Tp::SharedPtr<TlsHandler> tlsHandler = Tp::SharedPtr<TlsHandler>(new TlsHandler);
     if (!clientRegistrar->registerClient(
                 Tp::AbstractClientPtr(tlsHandler), QLatin1String("KTp.TLSHandler"))) {
         handlers -= 1;
     }
-#endif
 
     if (!handlers) {
         kDebug() << "No handlers registered. Exiting";
diff --git a/tls-cert-verifier-op.cpp b/tls-cert-verifier-op.cpp
index c94999e..eccfd69 100644
--- a/tls-cert-verifier-op.cpp
+++ b/tls-cert-verifier-op.cpp
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
  *   @author Andre Moreira Magalhaes <andre.magalhaes at collabora.co.uk>
+ * Copyright (C) 2013 Dan Vrátil <dvratil at redhat.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -27,6 +28,12 @@
 
 #include <QSslCertificate>
 #include <QSslKey>
+#include <QSslCipher>
+
+#include "kssl/ksslcertificatemanager.h"
+#include "kssl/ksslinfodialog.h"
+
+#include <QtCrypto/QtCrypto>
 
 TlsCertVerifierOp::TlsCertVerifierOp(const Tp::AccountPtr &account,
         const Tp::ConnectionPtr &connection,
@@ -76,42 +83,20 @@ void TlsCertVerifierOp::gotProperties(Tp::PendingOperation *op)
         kWarning() << "This is not an x509 certificate";
     }
 
+    // Initialize QCA module
+    QCA::Initializer initializer;
+
+    QCA::CertificateChain chain;
     Q_FOREACH (const QByteArray &data, m_certData) {
-        // FIXME How to chech if it is QSsl::Pem or QSsl::Der? QSsl::Der works for kdetalk
-        QList<QSslCertificate> certs = QSslCertificate::fromData(data, QSsl::Der);
-        Q_FOREACH (const QSslCertificate &cert, certs) {
-            kDebug() << cert;
-            kDebug() << "Issuer Organization:" << cert.issuerInfo(QSslCertificate::Organization);
-            kDebug() << "Issuer Common Name:" << cert.issuerInfo(QSslCertificate::CommonName);
-            kDebug() << "Issuer Locality Name:" << cert.issuerInfo(QSslCertificate::LocalityName);
-            kDebug() << "Issuer Organizational Unit Name:" << cert.issuerInfo(QSslCertificate::OrganizationalUnitName);
-            kDebug() << "Issuer Country Name:" << cert.issuerInfo(QSslCertificate::CountryName);
-            kDebug() << "Issuer State or Province Name:" << cert.issuerInfo(QSslCertificate::StateOrProvinceName);
-            kDebug() << "Subject Organization:" << cert.subjectInfo(QSslCertificate::Organization);
-            kDebug() << "Subject Common Name:" << cert.subjectInfo(QSslCertificate::CommonName);
-            kDebug() << "Subject Locality Name:" << cert.subjectInfo(QSslCertificate::LocalityName);
-            kDebug() << "Subject Organizational Unit Name:" << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-            kDebug() << "Subject Country Name:" << cert.subjectInfo(QSslCertificate::CountryName);
-            kDebug() << "Subject State Or Province Name:" << cert.subjectInfo(QSslCertificate::StateOrProvinceName);
-            kDebug() << "Effective Date:" << cert.effectiveDate();
-            kDebug() << "Expiry Date:" << cert.expiryDate();
-            kDebug() << "Public Key:" << cert.publicKey();
-            kDebug() << "Serial Number:" << cert.serialNumber();
-            kDebug() << "Version" << cert.version();
-            kDebug() << "Is Valid?" << cert.isValid();
-        }
+        // FIXME How to check if it is QSsl::Pem or QSsl::Der? QSsl::Der works for kdetalk
+        chain << QCA::Certificate::fromDER(data);
     }
 
-    //TODO Show a nice dialog
-    if (KMessageBox::questionYesNo(0,
-                                   i18n("Accept this certificate from <b>%1?</b><br />%2<br />", m_hostname, QString::fromLatin1(m_certData.first().toHex())),
-                                   i18n("Untrusted certificate")) == KMessageBox::Yes) {
-        // TODO Remember value
+    if (verifyCertChain(chain)) {
         m_authTLSCertificateIface->Accept().waitForFinished();
         setFinished();
     } else {
         Tp::TLSCertificateRejectionList rejections;
-        // TODO Add reason
         m_authTLSCertificateIface->Reject(rejections);
         m_channel->requestClose();
         setFinishedWithError(QLatin1String("Cert.Untrusted"),
@@ -119,4 +104,160 @@ void TlsCertVerifierOp::gotProperties(Tp::PendingOperation *op)
     }
 }
 
+bool TlsCertVerifierOp::verifyCertChain(const QCA::CertificateChain& chain)
+{
+    const QList<QSslCertificate> primary = QSslCertificate::fromData(chain.primary().toDER(), QSsl::Der);
+    KSslCertificateManager *const cm = KSslCertificateManager::self();
+    KSslCertificateRule rule = cm->rule(primary.first(), m_hostname);
+
+    // Find all errors then are not ignored by the rule
+    QList<KSslError> errors;
+    Q_FOREACH(const QCA::Certificate &cert, chain) {
+        QCA::Validity validity = cert.validate(CACollection(), QCA::CertificateCollection(), QCA::UsageTLSClient, QCA::ValidateAll);
+        if (validity == QCA::ValidityGood) {
+            continue;
+        }
+
+        KSslError::Error error = validityToError(validity);
+        if (!rule.ignoredErrors().contains(error)) {
+            errors << KSslError(error);
+        }
+    }
+
+    // If all errors are ignored, just accept
+    if (errors.isEmpty()) {
+        return true;
+    }
+
+    QString message = i18n("The server failed the authenticity check (%1).

", m_hostname);
+    Q_FOREACH(const KSslError &error, errors) {
+        message.append(error.errorString());
+        message.append(QLatin1Char('
'));
+    }
+
+    int msgResult;
+    do {
+        msgResult = KMessageBox::warningYesNoCancel(0,
+                               message,
+                               i18n("Server Authentication"),
+                               KGuiItem(i18n("&Details"), QLatin1String("dialog-information")), // yes
+                               KGuiItem(i18n("Co&ntinue"), QLatin1String("arrow-right")), // no
+                               KGuiItem(i18n("&Cancel"), QLatin1String("dialog-cancel")));
+        if (msgResult == KMessageBox::Yes) {
+            showSslDialog(chain, errors);
+        } else if (msgResult == KMessageBox::Cancel) {
+            return false; // reject
+        }
+        // Fall through on KMessageBox::No
+    } while (msgResult == KMessageBox::Yes);
+
+    // Save the user's choice to ignore the SSL errors.
+    msgResult = KMessageBox::warningYesNo(
+                            0,
+                            i18n("Would you like to accept this "
+                                 "certificate forever without "
+                                 "being prompted?"),
+                            i18n("Server Authentication"),
+                            KGuiItem(i18n("&Forever"), QLatin1String("flag-green")),
+                            KGuiItem(i18n("&Current Session only"), QLatin1String("chronometer")));
+    QDateTime ruleExpiry = QDateTime::currentDateTime();
+    if (msgResult == KMessageBox::Yes) {
+        // Accept forever ("for a very long time")
+        ruleExpiry = ruleExpiry.addYears(1000);
+    } else {
+        // Accept "for a short time", half an hour.
+        ruleExpiry = ruleExpiry.addSecs(30*60);
+    }
+
+    rule.setExpiryDateTime(ruleExpiry);
+    rule.setIgnoredErrors(errors);
+    cm->setRule(rule);
+
+    return true;
+}
+
+void TlsCertVerifierOp::showSslDialog(const QCA::CertificateChain &chain, const QList<KSslError> &errors) const
+{
+    QString errorStr;
+    Q_FOREACH (const KSslError &error, errors) {
+        errorStr += QString::number(static_cast<int>(error.error())) + QLatin1Char('	');
+        errorStr += QLatin1Char('
');
+    }
+    errorStr.chop(1);
+
+    // No way to tell whether QSsl::TlsV1 or QSsl::TlsV1Ssl3
+    KSslCipher cipher = QSslCipher(QLatin1String("TLS"), QSsl::TlsV1);
+    QString sslCipher = cipher.encryptionMethod() + QLatin1Char('
');
+    sslCipher += cipher.authenticationMethod() + QLatin1Char('
');
+    sslCipher += cipher.keyExchangeMethod() + QLatin1Char('
');
+    sslCipher += cipher.digestMethod();
+
+    const QList<QSslCertificate> qchain = chainToList(chain);
+    QPointer<KSslInfoDialog> dialog(new KSslInfoDialog(0));
+    dialog->setSslInfo(qchain,
+                    QString(), // we don't know the IP
+                    m_hostname, // the URL
+                    QLatin1String("TLS"),
+                    sslCipher,
+                    cipher.usedBits(),
+                    cipher.supportedBits(),
+                    KSslInfoDialog::errorsFromString(errorStr));
+
+    dialog->exec();
+    delete dialog;
+}
+
+KSslError::Error TlsCertVerifierOp::validityToError(QCA::Validity validity) const
+{
+    switch (validity) {
+        case QCA::ValidityGood:
+            return KSslError::NoError;
+        case QCA::ErrorRejected:
+            return KSslError::RejectedCertificate;
+        case QCA::ErrorUntrusted:
+            return KSslError::UntrustedCertificate;
+        case QCA::ErrorSignatureFailed:
+            return KSslError::CertificateSignatureFailed;
+        case QCA::ErrorInvalidCA:
+            return KSslError::InvalidCertificateAuthorityCertificate;
+        case QCA::ErrorInvalidPurpose:
+            return KSslError::InvalidCertificatePurpose;
+        case QCA::ErrorSelfSigned:
+            return KSslError::SelfSignedCertificate;
+        case QCA::ErrorRevoked:
+            return KSslError::RevokedCertificate;
+        case QCA::ErrorPathLengthExceeded:
+            return KSslError::PathLengthExceeded;
+        case QCA::ErrorExpired: // fall-through
+        case QCA::ErrorExpiredCA:
+            return KSslError::ExpiredCertificate;
+        case QCA::ErrorValidityUnknown:
+            return KSslError::UnknownError;
+    }
+
+    return KSslError::UnknownError;
+}
+
+QCA::CertificateCollection TlsCertVerifierOp::CACollection() const
+{
+    QList<QSslCertificate> certs = KSslCertificateManager::self()->caCertificates();
+    QCA::CertificateCollection collection;
+
+    Q_FOREACH(const QSslCertificate &cert, certs) {
+        collection.addCertificate(QCA::Certificate::fromDER(cert.toDer()));
+    }
+
+    return collection;
+}
+
+QList< QSslCertificate > TlsCertVerifierOp::chainToList(const QCA::CertificateChain& chain) const
+{
+    QList<QSslCertificate> certs;
+    Q_FOREACH(const QCA::Certificate &cert, chain) {
+        certs << QSslCertificate::fromData(cert.toDER(), QSsl::Der);
+    }
+
+    return certs;
+}
+
 #include "tls-cert-verifier-op.moc"
diff --git a/tls-cert-verifier-op.h b/tls-cert-verifier-op.h
index 121cf41..35f2fb0 100644
--- a/tls-cert-verifier-op.h
+++ b/tls-cert-verifier-op.h
@@ -31,6 +31,11 @@
 // FIXME: Move this to tp-qt4 itself
 #include "types.h"
 
+#include <QtCrypto/QtCrypto>
+#include <QSslError>
+#include <ktcpsocket.h>
+
+class QSslCertificate;
 class TlsCertVerifierOp : public Tp::PendingOperation
 {
     Q_OBJECT
@@ -48,6 +53,13 @@ private Q_SLOTS:
     void gotProperties(Tp::PendingOperation *op);
 
 private:
+    bool verifyCertChain(const QCA::CertificateChain &chain);
+    void showSslDialog(const QCA::CertificateChain &chain, const QList<KSslError> &errors) const;
+    KSslError::Error validityToError(QCA::Validity validity) const;
+
+    QCA::CertificateCollection CACollection() const;
+    QList<QSslCertificate> chainToList(const QCA::CertificateChain &chain) const;
+
     Tp::AccountPtr m_account;
     Tp::ConnectionPtr m_connection;
     Tp::ChannelPtr m_channel;

-- 
ktp-auth-handler packaging



More information about the pkg-kde-commits mailing list