Signature of QTcpServer::incomingConnection() changed in Qt5
[quassel.git] / src / core / sslserver.cpp
index 203ec76..87ca452 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-09 by the Quassel Project                          *
+ *   Copyright (C) 2005-2014 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -15,7 +15,7 @@
  *   You should have received a copy of the GNU General Public License     *
  *   along with this program; if not, write to the                         *
  *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
  ***************************************************************************/
 
 #include "sslserver.h"
 #endif
 
 #include <QFile>
-#include <QDebug>
 
 #include "logger.h"
-#include "util.h"
+#include "quassel.h"
 
 #ifdef HAVE_SSL
 
 SslServer::SslServer(QObject *parent)
-  : QTcpServer(parent)
+    : QTcpServer(parent),
+    _isCertValid(false)
 {
-  setCertificate(quasselDir().absolutePath() + "/quasselCert.pem");
+    static bool sslWarningShown = false;
+    if (!setCertificate(Quassel::configDirPath() + "quasselCert.pem")) {
+        if (!sslWarningShown) {
+            quWarning()
+            << "SslServer: Unable to set certificate file\n"
+            << "          Quassel Core will still work, but cannot provide SSL for client connections.\n"
+            << "          Please see http://quassel-irc.org/faq/cert to learn how to enable SSL support.";
+            sslWarningShown = true;
+        }
+    }
 }
 
-QTcpSocket *SslServer::nextPendingConnection() {
-  if(_pendingConnections.isEmpty())
-    return 0;
-  else
-    return _pendingConnections.takeFirst();
+
+QTcpSocket *SslServer::nextPendingConnection()
+{
+    if (_pendingConnections.isEmpty())
+        return 0;
+    else
+        return _pendingConnections.takeFirst();
 }
 
-void SslServer::incomingConnection(int socketDescriptor) {
-  QSslSocket *serverSocket = new QSslSocket(this);
-  if(serverSocket->setSocketDescriptor(socketDescriptor)) {
-    if(certIsValid()) {
-      serverSocket->setLocalCertificate(_cert);
-      serverSocket->setPrivateKey(_key);
+#if QT_VERSION >= 0x050000
+void SslServer::incomingConnection(qintptr socketDescriptor)
+#else
+void SslServer::incomingConnection(int socketDescriptor)
+#endif
+{
+    QSslSocket *serverSocket = new QSslSocket(this);
+    if (serverSocket->setSocketDescriptor(socketDescriptor)) {
+        if (isCertValid()) {
+            serverSocket->setLocalCertificate(_cert);
+            serverSocket->setPrivateKey(_key);
+            serverSocket->addCaCertificates(_ca);
+        }
+        _pendingConnections << serverSocket;
+        emit newConnection();
+    }
+    else {
+        delete serverSocket;
     }
-    _pendingConnections << serverSocket;
-    emit newConnection();
-  } else {
-    delete serverSocket;
-  }
 }
 
-bool SslServer::setCertificate(const QString &path) {
-  QFile certFile(path);
-  certFile.open(QIODevice::ReadOnly);
-  _cert = QSslCertificate(&certFile);
-  certFile.close();
 
-  certFile.open(QIODevice::ReadOnly);
-  _key = QSslKey(&certFile, QSsl::Rsa);
-  certFile.close();
+bool SslServer::setCertificate(const QString &path)
+{
+    _isCertValid = false;
 
-  _certIsValid = !_cert.isNull() && _cert.isValid() && !_key.isNull();
-  if(!_certIsValid) {
-    qWarning() << "SslServer: SSL Certificate is either missing or has a wrong format!\n"
-               << "          Quassel Core will still work, but cannot provide SSL for client connections.\n"
-               << "          Please see http://quassel-irc.org/faq/cert to learn how to enable SSL support.";
-  }
+    if (path.isEmpty())
+        return false;
 
-  return _certIsValid;
+    QFile certFile(path);
+    if (!certFile.exists()) {
+        quWarning() << "SslServer: Certificate file" << qPrintable(path) << "does not exist";
+        return false;
+    }
+
+    if (!certFile.open(QIODevice::ReadOnly)) {
+        quWarning()
+        << "SslServer: Failed to open certificate file" << qPrintable(path)
+        << "error:" << certFile.error();
+        return false;
+    }
+
+    QList<QSslCertificate> certList = QSslCertificate::fromDevice(&certFile);
+
+    if (certList.isEmpty()) {
+        quWarning() << "SslServer: Certificate file doesn't contain a certificate";
+        return false;
+    }
+
+    _cert = certList[0];
+    certList.removeFirst(); // remove server cert
+
+    // store CA and intermediates certs
+    _ca = certList;
+
+    if (!certFile.reset()) {
+        quWarning() << "SslServer: IO error reading certificate file";
+        return false;
+    }
+
+    _key = QSslKey(&certFile, QSsl::Rsa);
+    certFile.close();
+
+    if (_cert.isNull()) {
+        quWarning() << "SslServer:" << qPrintable(path) << "contains no certificate data";
+        return false;
+    }
+    if (!_cert.isValid()) {
+        quWarning() << "SslServer: Invalid certificate (most likely expired)";
+        // We allow the core to offer SSL anyway, so no "return false" here. Client will warn about the cert being invalid.
+    }
+    if (_key.isNull()) {
+        quWarning() << "SslServer:" << qPrintable(path) << "contains no key data";
+        return false;
+    }
+
+    _isCertValid = true;
+
+    return _isCertValid;
 }
 
+
 #endif // HAVE_SSL