summaryrefslogblamecommitdiffstats
path: root/src/server/net/sslserver.cpp
blob: d968834e2b6a56fc4bb8abf804a82a4ed1172725 (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() : QTcpServer(nullptr), _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();
	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<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 (QList<QSslError>::const_iterator it = errors.begin(); it != errors.end(); it++) {
		qDebug() << it->errorString();
	}

}