You can now add a core to the known hosts.
authorMarcus Eggenberger <egs@quassel-irc.org>
Thu, 29 Jan 2009 00:02:45 +0000 (01:02 +0100)
committerMarcus Eggenberger <egs@quassel-irc.org>
Thu, 29 Jan 2009 00:02:45 +0000 (01:02 +0100)
This will supress future warnings about issues with that specific ssl
certificate in combination with the connected host until the cert changes.

src/client/clientsettings.cpp
src/client/clientsettings.h
src/client/clientsyncer.cpp
src/common/util.cpp
src/common/util.h
src/qtui/coreconnectdlg.cpp

index cc8e209..62812fc 100644 (file)
 
 #include <QStringList>
 
-#include "client.h"
+
 #include "clientsettings.h"
+
+#include <QHostAddress>
+#ifdef HAVE_SSL
+#include <QSslSocket>
+#endif
+
+
+#include "client.h"
 #include "quassel.h"
 
 ClientSettings::ClientSettings(QString g) : Settings(g, Quassel::buildInfo().clientApplicationName) {
@@ -140,3 +148,40 @@ void NotificationSettings::setNicksCaseSensitive(bool cs) {
 bool NotificationSettings::nicksCaseSensitive() {
   return localValue("Highlights/NicksCaseSensitive", false).toBool();
 }
+
+
+// ========================================
+//  KnownHostsSettings
+// ========================================
+KnownHostsSettings::KnownHostsSettings()
+  : ClientSettings("KnownHosts")
+{
+}
+
+QByteArray KnownHostsSettings::knownDigest(const QHostAddress &address) {
+  return localValue(address.toString(), QByteArray()).toByteArray();
+}
+
+void KnownHostsSettings::saveKnownHost(const QHostAddress &address, const QByteArray &certDigest) {
+  setLocalValue(address.toString(), certDigest);
+}
+
+bool KnownHostsSettings::isKnownHost(const QHostAddress &address, const QByteArray &certDigest) {
+  return certDigest == localValue(address.toString(), QByteArray()).toByteArray();
+}
+
+#ifdef HAVE_SSL
+QByteArray KnownHostsSettings::knownDigest(const QSslSocket *socket) {
+  return knownDigest(socket->peerAddress());
+}
+
+void KnownHostsSettings::saveKnownHost(const QSslSocket *socket) {
+  Q_ASSERT(socket);
+  saveKnownHost(socket->peerAddress(), socket->peerCertificate().digest());
+}
+
+bool KnownHostsSettings::isKnownHost(const QSslSocket *socket) {
+  Q_ASSERT(socket);
+  return isKnownHost(socket->peerAddress(), socket->peerCertificate().digest());
+#endif
+}
index c927250..aa0f0d6 100644 (file)
 #define CLIENTSETTINGS_H
 
 #include "settings.h"
+
 #include "types.h"
 
+class QHostAddress;
+class QSslSocket;
+
 class ClientSettings : public Settings {
 public:
   virtual ~ClientSettings();
@@ -32,6 +36,10 @@ protected:
   ClientSettings(QString group = "General");
 };
 
+// ========================================
+//  CoreAccountSettings
+// ========================================
+
 // Deriving from CoreAccountSettings:
 // MySettings() : CoreAccountSettings("MyGroup") {};
 // Then use accountValue() / setAccountValue() to retrieve/store data associated to the currently
@@ -67,29 +75,50 @@ private:
   QString _subgroup;
 };
 
+// ========================================
+//  NotificationSettings
+// ========================================
 class NotificationSettings : public ClientSettings {
+public:
+  enum HighlightNickType {
+    NoNick = 0x00,
+    CurrentNick= 0x01,
+    AllNicks = 0x02
+  };
+
+  NotificationSettings();
 
-  public:
-    enum HighlightNickType {
-      NoNick = 0x00,
-      CurrentNick= 0x01,
-      AllNicks = 0x02
-    };
+  inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); }
+  inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); }
+  inline void remove(const QString &key) { removeLocalKey(key); }
 
-    NotificationSettings();
+  void setHighlightList(const QVariantList &highlightList);
+  QVariantList highlightList();
 
-    inline void setValue(const QString &key, const QVariant &data) { setLocalValue(key, data); }
-    inline QVariant value(const QString &key, const QVariant &def = QVariant()) { return localValue(key, def); }
-    inline void remove(const QString &key) { removeLocalKey(key); }
+  void setHighlightNick(HighlightNickType);
+  HighlightNickType highlightNick();
+
+  void setNicksCaseSensitive(bool);
+  bool nicksCaseSensitive();
+};
 
-    void setHighlightList(const QVariantList &highlightList);
-    QVariantList highlightList();
 
-    void setHighlightNick(HighlightNickType);
-    HighlightNickType highlightNick();
+// ========================================
+//  KnownHostsSettings
+// ========================================
+class KnownHostsSettings : public ClientSettings {
+public:
+  KnownHostsSettings();
 
-    void setNicksCaseSensitive(bool);
-    bool nicksCaseSensitive();
+  QByteArray knownDigest(const QHostAddress &address);
+  void saveKnownHost(const QHostAddress &address, const QByteArray &certDigest);
+  bool isKnownHost(const QHostAddress &address, const QByteArray &certDigest);
 
+#ifdef HAVE_SSL
+  QByteArray knownDigest(const QSslSocket *socket);
+  void saveKnownHost(const QSslSocket *socket);
+  bool isKnownHost(const QSslSocket *socket);
+#endif
 };
+
 #endif
index e9d64f3..3b68b5c 100644 (file)
@@ -30,6 +30,7 @@
 #include "networkmodel.h"
 #include "quassel.h"
 #include "signalproxy.h"
+#include "util.h"
 
 ClientSyncer::ClientSyncer(QObject *parent)
   : QObject(parent)
@@ -349,11 +350,17 @@ void ClientSyncer::resetWarningsHandler() {
 
 #ifdef HAVE_SSL
 void ClientSyncer::ignoreSslWarnings(bool permanently) {
-  QAbstractSocket *sock = qobject_cast<QAbstractSocket *>(socket);
+  QSslSocket *sock = qobject_cast<QSslSocket *>(socket);
   if(sock) {
     // ensure that a proper state is displayed and no longer a warning
     emit socketStateChanged(sock->state());
   }
+  if(permanently) {
+    if(!sock)
+      qWarning() << Q_FUNC_INFO << "unable to save cert digest! Socket is either a nullptr or not a QSslSocket";
+    else
+      KnownHostsSettings().saveKnownHost(sock);
+  }
   emit connectionMsg(_coreMsgBuffer["CoreInfo"].toString());
   connectionReady();
 }
@@ -366,15 +373,26 @@ void ClientSyncer::sslSocketEncrypted() {
 }
 
 void ClientSyncer::sslErrors(const QList<QSslError> &errors) {
+  QByteArray knownDigest;
   QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
   if(socket) {
     socket->ignoreSslErrors();
+    knownDigest = KnownHostsSettings().knownDigest(socket);
+    if(knownDigest == socket->peerCertificate().digest()) {
+      connectionReady();
+      return;
+    }
   }
 
   QStringList warnings;
+
   foreach(QSslError err, errors)
     warnings << err.errorString();
 
+  if(!knownDigest.isEmpty()) {
+    warnings << tr("Cert Digest changed! was: %1").arg(QString(prettyDigest(knownDigest)));
+  }
+
   setWarningsHandler(SLOT(ignoreSslWarnings(bool)));
   emit connectionWarnings(warnings);
 }
index 9bc24bc..817790f 100644 (file)
@@ -142,3 +142,14 @@ QString secondsToString(int timeInSeconds) {
     }
     return returnString.join(", ");
 }
+
+QByteArray prettyDigest(const QByteArray &digest) {
+  QByteArray hexDigest = digest.toHex();
+  QByteArray prettyDigest;
+  prettyDigest.fill(':', hexDigest.count() + (hexDigest.count() / 2) - 1);
+
+  for(int i = 0; i * 2 < hexDigest.count(); i++) {
+    prettyDigest.replace(i * 3, 2, hexDigest.mid(i * 2, 2));
+  }
+  return prettyDigest;
+}
index 99032e9..0e205fd 100644 (file)
@@ -67,4 +67,6 @@ QList<T> fromVariantList(const QVariantList &variants) {
   return list;
 }
 
+QByteArray prettyDigest(const QByteArray &digest);
+
 #endif
index 16655ff..e60d4d6 100644 (file)
@@ -36,6 +36,7 @@
 #include "coreconfigwizard.h"
 #include "iconloader.h"
 #include "quassel.h"
+#include "util.h"
 
 CoreConnectDlg::CoreConnectDlg(bool autoconnect, QWidget *parent)
   : QDialog(parent),
@@ -600,6 +601,7 @@ SslCertDisplayDialog::SslCertDisplayDialog(const QString &host, const QSslCertif
   for(int i = 0; i < mailaddresses.count(); i++) {
     additionalLayout->addRow(tr("E-Mail Address %1:").arg(i + 1), new QLabel(mailaddresses[i], this));
   }
+  additionalLayout->addRow(tr("Digest:"), new QLabel(QString(prettyDigest(cert.digest()))));
   mainLayout->addWidget(additionalBox);