/* # 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 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 & errors ) { for (QList::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 &)), this, SLOT(ssl_Error(const QList &)) ); _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 &)), this, SLOT(ssl_Error(const QList &)) ); _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; }