Implemented rudimentary SSL support for IRC connections.
authorManuel Nickschas <sputnick@quassel-irc.org>
Thu, 13 Mar 2008 17:38:32 +0000 (17:38 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Thu, 13 Mar 2008 17:38:32 +0000 (17:38 +0000)
SSL errors (untrusted/invalid certs etc) are silently ignored at the moment; proper handling
will come soonish.
You can activate SSL encryption for a given server (not network, as this is a per-server
setting) in the server edit dialog in network settings. Please to be testink this :)

src/core/networkconnection.cpp
src/core/networkconnection.h
src/qtui/settingspages/servereditdlg.ui
version.inc

index fd7e2ba..163f220 100644 (file)
@@ -65,7 +65,12 @@ NetworkConnection::NetworkConnection(Network *network, CoreSession *session) : Q
   connect(network, SIGNAL(autoReconnectIntervalSet(quint32)), this, SLOT(autoReconnectSettingsChanged()));
   connect(network, SIGNAL(autoReconnectRetriesSet(quint16)), this, SLOT(autoReconnectSettingsChanged()));
 
+#ifndef QT_NO_OPENSSL
+  connect(&socket, SIGNAL(encrypted()), this, SLOT(socketEncrypted()));
+  connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
+#endif
   connect(&socket, SIGNAL(connected()), this, SLOT(socketConnected()));
+
   connect(&socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
   connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
   connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
@@ -73,6 +78,8 @@ NetworkConnection::NetworkConnection(Network *network, CoreSession *session) : Q
 
   connect(_ircServerHandler, SIGNAL(nickChanged(const QString &, const QString &)),
          this, SLOT(nickChanged(const QString &, const QString &)));
+
+  network->proxy()->attachSignal(this, SIGNAL(sslErrors(const QVariant &)));
 }
 
 NetworkConnection::~NetworkConnection() {
@@ -206,7 +213,7 @@ void NetworkConnection::connectToIrc(bool reconnecting) {
     }
   }
   _previousConnectionAttemptFailed = false;
-  
+
   QString host = serverList[_lastUsedServerlistIndex].toMap()["Host"].toString();
   quint16 port = serverList[_lastUsedServerlistIndex].toMap()["Port"].toUInt();
   displayStatusMsg(tr("Connecting to %1:%2...").arg(host).arg(port));
@@ -293,7 +300,46 @@ void NetworkConnection::socketError(QAbstractSocket::SocketError) {
   //exit(1);
 }
 
+#ifndef QT_NO_OPENSSL
+
+void NetworkConnection::sslErrors(const QList<QSslError> &errors) {
+  socket.ignoreSslErrors();
+  /* TODO errorhandling
+  QVariantMap errmsg;
+  QVariantList errnums;
+  foreach(QSslError err, errors) errnums << err.error();
+  errmsg["SslErrors"] = errnums;
+  errmsg["SslCert"] = socket.peerCertificate().toPem();
+  errmsg["PeerAddress"] = socket.peerAddress().toString();
+  errmsg["PeerPort"] = socket.peerPort();
+  errmsg["PeerName"] = socket.peerName();
+  emit sslErrors(errmsg);
+  disconnectFromIrc();
+  */
+}
+
+void NetworkConnection::socketEncrypted() {
+  //qDebug() << "encrypted!";
+  socketInitialized();
+}
+
+#endif  // QT_NO_OPENSSL
+
 void NetworkConnection::socketConnected() {
+#ifdef QT_NO_OPENSSL
+  socketInitialized();
+  return;
+#else
+  if(!network()->serverList()[_lastUsedServerlistIndex].toMap()["UseSSL"].toBool()) {
+    socketInitialized();
+    return;
+  }
+  //qDebug() << "starting handshake";
+  socket.startClientEncryption();
+#endif
+}
+
+void NetworkConnection::socketInitialized() {
   //emit connected(networkId());  initialize first!
   Identity *identity = coreSession()->identity(network()->identity());
   if(!identity) {
index 649171d..1a7aafa 100644 (file)
 #include <QAbstractSocket>
 #include <QString>
 #include <QStringList>
-#include <QTcpSocket>
 #include <QTimer>
 
+#ifndef QT_NO_OPENSSL
+# include <QSslSocket>
+# include <QSslError>
+#else
+# include <QTcpSocket>
+#endif
+
 #include "identity.h"
 #include "message.h"
 #include "network.h"
@@ -120,17 +126,30 @@ signals:
   void channelJoined(NetworkId, const QString &channel, const QString &key = QString());
   void channelParted(NetworkId, const QString &channel);
 
+  void sslErrors(const QVariant &errorData);
+
 private slots:
   void socketHasData();
   void socketError(QAbstractSocket::SocketError);
   void socketConnected();
+  void socketInitialized();
   void socketDisconnected();
   void socketStateChanged(QAbstractSocket::SocketState);
   void setConnectionState(Network::ConnectionState);
   void networkInitialized(const QString &currentServer);
 
+#ifndef QT_NO_OPENSSL
+  void socketEncrypted();
+  void sslErrors(const QList<QSslError> &errors);
+#endif
+
 private:
+#ifndef QT_NO_OPENSSL
+  QSslSocket socket;
+#else
   QTcpSocket socket;
+#endif
+
   Network::ConnectionState _connectionState;
 
   Network *_network;
index dec2b54..ef42b8e 100644 (file)
@@ -6,7 +6,7 @@
     <x>0</x>
     <y>0</y>
     <width>264</width>
-    <height>159</height>
+    <height>167</height>
    </rect>
   </property>
   <property name="windowTitle" >
    <item>
     <widget class="QCheckBox" name="useSSL" >
      <property name="enabled" >
-      <bool>false</bool>
+      <bool>true</bool>
      </property>
      <property name="text" >
       <string>Use SSL</string>
      </property>
      <property name="icon" >
-      <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/document-encrypt.png</iconset>
+      <iconset resource="../../icons/icons.qrc" >
+       <normaloff>:/16x16/actions/oxygen/16x16/actions/document-encrypt.png</normaloff>:/16x16/actions/oxygen/16x16/actions/document-encrypt.png</iconset>
      </property>
     </widget>
    </item>
@@ -86,7 +87,7 @@
      <property name="orientation" >
       <enum>Qt::Vertical</enum>
      </property>
-     <property name="sizeHint" >
+     <property name="sizeHint" stdset="0" >
       <size>
        <width>20</width>
        <height>40</height>
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="standardButtons" >
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
      </property>
     </widget>
    </item>
index b924a40..f1cb406 100644 (file)
@@ -5,7 +5,7 @@
 
   quasselVersion = "0.2.0-alpha3-pre";
   quasselDate = "2008-03-13";
-  quasselBuild = 634;
+  quasselBuild = 636;
 
   //! Minimum client build number the core needs
   clientBuildNeeded = 628;