/* # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your suggestions, praise, or complaints to feedback@openslx.org # # General information about OpenSLX can be found at http://openslx.org/ # ----------------------------------------------------------------------------- # src/net/SslServer.cpp # - provide QTcpServer-like behaviour for SSL # ----------------------------------------------------------------------------- */ #include "sslserver.h" #include #include #include #include "certmanager.h" #include SslServer::SslServer() : QTcpServer(nullptr), _timer(new QTimer(this)) { connect(_timer, &QTimer::timeout, [=]() { if (_pending.empty()) return; const qint64 deadline = QDateTime::currentMSecsSinceEpoch() - 10000; QMutableHashIterator it(_pending); while (it.hasNext()) { // Remove lingering connections after 10s it.next(); if (it.value() < deadline) { it.key()->blockSignals(true); it.key()->deleteLater(); it.remove(); } } }); _timer->start(10000); } SslServer::~SslServer() { _timer->stop(); for (QSslSocket *sock : _pending.keys()) { sock->deleteLater(); } } /** * Handle incomming connection. * @param socketDescriptor */ void SslServer::incomingConnection(qintptr socketDescriptor) { static int certFails = 0; QSslKey key; QSslCertificate cert; if (!CertManager::getPrivateKeyAndCert("manager", key, cert)) { if (++certFails > 5) { CertManager::fatal(); } ::close(int(socketDescriptor)); return; } QSslSocket *serverSocket = new QSslSocket(nullptr); connect(serverSocket, QOverload &>::of(&QSslSocket::sslErrors), this, &SslServer::sslErrors); serverSocket->setPrivateKey(key); serverSocket->setLocalCertificate(cert); serverSocket->setPeerVerifyMode(QSslSocket::VerifyNone); serverSocket->setProtocol(QSsl::SecureProtocols); if (serverSocket->setSocketDescriptor(socketDescriptor)) { _pending.insert(serverSocket, QDateTime::currentMSecsSinceEpoch()); // Once the connection is successfully encrypted, raise our newConnection event connect(serverSocket, &QSslSocket::encrypted, [=]() { serverSocket->disconnect(this); if (_pending.remove(serverSocket) == 0) { // Should never happen, so better log... qDebug() << "Encryption event for socket that is not pending!?"; } else { this->addPendingConnection(serverSocket); emit newConnection(); } }); serverSocket->startServerEncryption(); } else { qDebug() << "Failed to setSocketDescriptor on new SSL Socket"; serverSocket->deleteLater(); } } void SslServer::sslErrors(const QList& errors) { qDebug() << "Client caused sslErrors before connection:"; for (QList::const_iterator it = errors.begin(); it != errors.end(); it++) { qDebug() << it->errorString(); } }