summaryrefslogblamecommitdiffstats
path: root/src/server/net/sslserver.cpp
blob: 2dfa84cdb83c7dc2b0bf780a9f579fed42a960de (plain) (tree)


















                                                                                
                 
                        
                   
 


                                          
 


                                                 
                                                                                    










                                                                                



                       
                       

                                       

                                    
                         

 



                               
                                                            
 
                                 

                             
                                                                        


                                             
                                               

                       
                                                     
                                                                                                                            


                                                                
                                                         
                                                                  
                                                                                   
                                                                                               
                                                                     







                                                                                                
                   
                                                      
                
                                                                              



                                            
                                                         
 
                                                                 

                                                
         
 

 
/*
 # 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 <QtNetwork/QSslCipher>
#include <QtNetwork/QSslSocket>
#include <QTimer>
#include "certmanager.h"
#include <unistd.h>

SslServer::SslServer(QObject *parent)
		: QTcpServer(parent)
		, _timer(new QTimer(this))
{
	connect(_timer, &QTimer::timeout, [=]() {
		if (_pending.empty())
			return;
		const qint64 deadline = QDateTime::currentMSecsSinceEpoch() - 10000;
		QMutableHashIterator<QSslSocket*, qint64> 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();
	auto keys = _pending.keys();
	for (QSslSocket *sock : keys) {
		sock->deleteLater();
	}
	_pending.clear();
}

/**
 * Handle incomming connection.
 * @param socketDescriptor
 */
void SslServer::incomingConnection(qintptr socketDescriptor)
{
	static int certFails = 0;
	QSslKey key;
	QSslCertificate cert;
	if (!CertManager::getPrivateKeyAndCert("manager2", key, cert)) {
		if (++certFails > 5) {
			CertManager::fatal();
		}
		::close(int(socketDescriptor));
		return;
	}
	auto *serverSocket = new QSslSocket(nullptr);
	connect(serverSocket, QOverload<const QList<QSslError> &>::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<QSslError>& errors)
{
	qDebug() << "Client caused sslErrors before connection:";
	for (const auto & error : errors) {
		qDebug() << error.errorString();
	}

}