summaryrefslogblamecommitdiffstats
path: root/src/net/pvsDiscoveredServer.cpp
blob: dae27b0b4d897325826e0f3402ec3fc71ed2e9c8 (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/pvsDiscoveredServer.cpp
#    - represents an entry in the list of available servers
#	 - handles some extra things like validating the identity of the remote host
# -----------------------------------------------------------------------------
*/

#include "pvsDiscoveredServer.h"
#include "src/util/serviceDiscoveryUtil.h"
#include <QtNetwork/QSslKey>

PVSDiscoveredServer::PVSDiscoveredServer(QObject* parent, QHostAddress host, int port, QByteArray fingerprint, QString name)
    : QObject(parent)
{
	_validated = false;
	_socket = NULL;
	_host = host;
	_port = port;
	_fingerprint = fingerprint;
	_name = name;
	_lastUpdate = QDateTime::currentDateTime();
	_lastCheck = QDateTime::fromTime_t(1000000);
	this->validateCertificate();
}

PVSDiscoveredServer::~PVSDiscoveredServer() {
	delete _socket;
}

void PVSDiscoveredServer::ssl_Error( const QList<QSslError> & errors )
{
	for (QList<QSslError>::const_iterator it = errors.begin(); it != errors.end(); it++)
	{
		QSslError err = *it;
		if (err.error() == QSslError::HostNameMismatch) continue; // We don't pay attention to hostnames for validation
		if (err.error() == QSslError::SelfSignedCertificate) {
			continue; // Also, this will always be the case; we check the fingerprint later
		}
		// http://doc.trolltech.com/4.7//qsslerror.html#SslError-enum
		qDebug("Unhandled SSL Error %i: %s", err.error(), qPrintable(err.errorString()));
		return;
	}
	_socket->ignoreSslErrors();
}

void PVSDiscoveredServer::sock_dataArrival()
{
    if (_socket == NULL) return;

    char charbuff[2000];
    while (_socket->bytesAvailable())
    {
        _socket->read(charbuff, 2000);
    }
}

void PVSDiscoveredServer::sock_connected()
{
    QByteArray cert = _socket->peerCertificate().digest(QCryptographicHash::Sha1);
    if (_socket->peerCertificate().isNull())
    {
    	qDebug("**** WARNING - PEER CERTIFICATE IS NULL ****");
    }
    else
    {
        qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::Organization)));
        qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::CommonName)));
        qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::LocalityName)));
        qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::OrganizationalUnitName)));
        qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::CountryName)));
        qDebug("%s", qPrintable(_socket->peerCertificate().subjectInfo(QSslCertificate::StateOrProvinceName)));
    }
    if (cert == _fingerprint && !_validated)
    {
        _validated = true;
        emit validated(this);
        qDebug("Validated certificate of %s :)", qPrintable(_socket->peerAddress().toString()));
    }
    else
    {
        qDebug("Certificate of %s is invalid :(", qPrintable(_socket->peerAddress().toString()));
        QByteArray is, should;
        is = cert.toBase64();
        should = _fingerprint.toBase64();
        qDebug("Is %s and should be %s", is.data(), should.data());
    }
    _socket->disconnectFromHost();
}

void PVSDiscoveredServer::validateCertificate()
{
	if (_validated) return; // Nothing to do, this one is legit
	QDateTime now = QDateTime::currentDateTime();
	if (_lastCheck.secsTo(now) < 30) return; // Too soon!
	if (_host.isNull() || _port < 1 || _port > 65535) return; // Invalid
	if (_socket != NULL) {
		disconnect(_socket, SIGNAL(connected()), this, SLOT(sock_connected()));
		disconnect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
		disconnect(_socket, SIGNAL(sslErrors(const QList<QSslError> &)),
				this, SLOT(ssl_Error(const QList<QSslError> &))
				);
		_socket->abort();
		_socket->deleteLater();
	}
	_socket = new QSslSocket(this);
	_socket->setProtocol(QSsl::SslV3);
	_socket->setPeerVerifyMode(QSslSocket::VerifyPeer);
	connect(_socket, SIGNAL(encrypted()), this, SLOT(sock_connected()));
	connect(_socket, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
	connect(_socket, SIGNAL(sslErrors(const QList<QSslError> &)),
			this, SLOT(ssl_Error(const QList<QSslError> &))
			);
	_socket->connectToHostEncrypted(_host.toString(), _port);
	_lastCheck = now;
}

bool PVSDiscoveredServer::hasFingerprint(QByteArray &fingerprint)
{
	return _fingerprint == fingerprint;
}

bool PVSDiscoveredServer::hasHost(QHostAddress &host)
{
	return _host == host;
}

void PVSDiscoveredServer::update(int port)
{
    _port = port;
    _lastUpdate = QDateTime::currentDateTime();
}

int PVSDiscoveredServer::getAge()
{
    return _lastUpdate.secsTo(QDateTime::currentDateTime());
}

QString PVSDiscoveredServer::getName()
{
	return _name;
}