mirror of
https://github.com/overte-org/overte.git
synced 2025-07-22 21:28:54 +02:00
remove dependency on GnuTLS for later replacement with OpenSSL
This commit is contained in:
parent
9dde480bb2
commit
f1581ef823
18 changed files with 47 additions and 718 deletions
|
@ -39,8 +39,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
||||||
QCoreApplication(argc, argv),
|
QCoreApplication(argc, argv),
|
||||||
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME)
|
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME)
|
||||||
{
|
{
|
||||||
DTLSClientSession::globalInit();
|
|
||||||
|
|
||||||
setOrganizationName("High Fidelity");
|
setOrganizationName("High Fidelity");
|
||||||
setOrganizationDomain("highfidelity.io");
|
setOrganizationDomain("highfidelity.io");
|
||||||
setApplicationName("assignment-client");
|
setApplicationName("assignment-client");
|
||||||
|
@ -106,10 +104,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
||||||
this, &AssignmentClient::handleAuthenticationRequest);
|
this, &AssignmentClient::handleAuthenticationRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssignmentClient::~AssignmentClient() {
|
|
||||||
DTLSClientSession::globalDeinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssignmentClient::sendAssignmentRequest() {
|
void AssignmentClient::sendAssignmentRequest() {
|
||||||
if (!_currentAssignment) {
|
if (!_currentAssignment) {
|
||||||
NodeList::getInstance()->sendAssignment(_requestAssignment);
|
NodeList::getInstance()->sendAssignment(_requestAssignment);
|
||||||
|
|
|
@ -21,7 +21,6 @@ class AssignmentClient : public QCoreApplication {
|
||||||
public:
|
public:
|
||||||
AssignmentClient(int &argc, char **argv);
|
AssignmentClient(int &argc, char **argv);
|
||||||
static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; }
|
static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; }
|
||||||
~AssignmentClient();
|
|
||||||
private slots:
|
private slots:
|
||||||
void sendAssignmentRequest();
|
void sendAssignmentRequest();
|
||||||
void readPendingDatagrams();
|
void readPendingDatagrams();
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
//
|
|
||||||
// DTLSServerSession.cpp
|
|
||||||
// domain-server/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-01.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "DTLSServerSession.h"
|
|
||||||
|
|
||||||
DTLSServerSession::DTLSServerSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
|
||||||
DTLSSession(GNUTLS_SERVER, dtlsSocket, destinationSocket)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
//
|
|
||||||
// DTLSServerSession.h
|
|
||||||
// domain-server/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-01.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_DTLSServerSession_h
|
|
||||||
#define hifi_DTLSServerSession_h
|
|
||||||
|
|
||||||
#include <gnutls/dtls.h>
|
|
||||||
|
|
||||||
#include <DTLSSession.h>
|
|
||||||
|
|
||||||
class DTLSServerSession : public DTLSSession {
|
|
||||||
public:
|
|
||||||
DTLSServerSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_DTLSServerSession_h
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
#include "DomainServerNodeData.h"
|
#include "DomainServerNodeData.h"
|
||||||
#include "DummyDTLSSession.h"
|
|
||||||
|
|
||||||
#include "DomainServer.h"
|
#include "DomainServer.h"
|
||||||
|
|
||||||
|
@ -39,18 +38,12 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
_allAssignments(),
|
_allAssignments(),
|
||||||
_unfulfilledAssignments(),
|
_unfulfilledAssignments(),
|
||||||
_isUsingDTLS(false),
|
_isUsingDTLS(false),
|
||||||
_x509Credentials(NULL),
|
|
||||||
_dhParams(NULL),
|
|
||||||
_priorityCache(NULL),
|
|
||||||
_dtlsSessions(),
|
|
||||||
_oauthProviderURL(),
|
_oauthProviderURL(),
|
||||||
_oauthClientID(),
|
_oauthClientID(),
|
||||||
_hostname(),
|
_hostname(),
|
||||||
_networkReplyUUIDMap(),
|
_networkReplyUUIDMap(),
|
||||||
_sessionAuthenticationHash()
|
_sessionAuthenticationHash()
|
||||||
{
|
{
|
||||||
gnutls_global_init();
|
|
||||||
|
|
||||||
setOrganizationName("High Fidelity");
|
setOrganizationName("High Fidelity");
|
||||||
setOrganizationDomain("highfidelity.io");
|
setOrganizationDomain("highfidelity.io");
|
||||||
setApplicationName("domain-server");
|
setApplicationName("domain-server");
|
||||||
|
@ -64,31 +57,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
qDebug() << "Setting up LimitedNodeList and assignments.";
|
qDebug() << "Setting up LimitedNodeList and assignments.";
|
||||||
setupNodeListAndAssignments();
|
setupNodeListAndAssignments();
|
||||||
|
|
||||||
if (_isUsingDTLS) {
|
|
||||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
|
||||||
|
|
||||||
// connect our socket to read datagrams received on the DTLS socket
|
|
||||||
connect(&nodeList->getDTLSSocket(), &QUdpSocket::readyRead, this, &DomainServer::readAvailableDTLSDatagrams);
|
|
||||||
}
|
|
||||||
|
|
||||||
_networkAccessManager = new QNetworkAccessManager(this);
|
_networkAccessManager = new QNetworkAccessManager(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DomainServer::~DomainServer() {
|
|
||||||
if (_x509Credentials) {
|
|
||||||
gnutls_certificate_free_credentials(*_x509Credentials);
|
|
||||||
gnutls_priority_deinit(*_priorityCache);
|
|
||||||
gnutls_dh_params_deinit(*_dhParams);
|
|
||||||
|
|
||||||
delete _x509Credentials;
|
|
||||||
delete _priorityCache;
|
|
||||||
delete _dhParams;
|
|
||||||
delete _cookieKey;
|
|
||||||
}
|
|
||||||
gnutls_global_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DomainServer::optionallyReadX509KeyAndCertificate() {
|
bool DomainServer::optionallyReadX509KeyAndCertificate() {
|
||||||
const QString X509_CERTIFICATE_OPTION = "cert";
|
const QString X509_CERTIFICATE_OPTION = "cert";
|
||||||
const QString X509_PRIVATE_KEY_OPTION = "key";
|
const QString X509_PRIVATE_KEY_OPTION = "key";
|
||||||
|
@ -100,28 +72,28 @@ bool DomainServer::optionallyReadX509KeyAndCertificate() {
|
||||||
if (!certPath.isEmpty() && !keyPath.isEmpty()) {
|
if (!certPath.isEmpty() && !keyPath.isEmpty()) {
|
||||||
// the user wants to use DTLS to encrypt communication with nodes
|
// the user wants to use DTLS to encrypt communication with nodes
|
||||||
// let's make sure we can load the key and certificate
|
// let's make sure we can load the key and certificate
|
||||||
_x509Credentials = new gnutls_certificate_credentials_t;
|
// _x509Credentials = new gnutls_certificate_credentials_t;
|
||||||
gnutls_certificate_allocate_credentials(_x509Credentials);
|
// gnutls_certificate_allocate_credentials(_x509Credentials);
|
||||||
|
|
||||||
QString keyPassphraseString = QProcessEnvironment::systemEnvironment().value(X509_KEY_PASSPHRASE_ENV);
|
QString keyPassphraseString = QProcessEnvironment::systemEnvironment().value(X509_KEY_PASSPHRASE_ENV);
|
||||||
|
|
||||||
qDebug() << "Reading certificate file at" << certPath << "for DTLS.";
|
qDebug() << "Reading certificate file at" << certPath << "for DTLS.";
|
||||||
qDebug() << "Reading key file at" << keyPath << "for DTLS.";
|
qDebug() << "Reading key file at" << keyPath << "for DTLS.";
|
||||||
|
|
||||||
int gnutlsReturn = gnutls_certificate_set_x509_key_file2(*_x509Credentials,
|
// int gnutlsReturn = gnutls_certificate_set_x509_key_file2(*_x509Credentials,
|
||||||
certPath.toLocal8Bit().constData(),
|
// certPath.toLocal8Bit().constData(),
|
||||||
keyPath.toLocal8Bit().constData(),
|
// keyPath.toLocal8Bit().constData(),
|
||||||
GNUTLS_X509_FMT_PEM,
|
// GNUTLS_X509_FMT_PEM,
|
||||||
keyPassphraseString.toLocal8Bit().constData(),
|
// keyPassphraseString.toLocal8Bit().constData(),
|
||||||
0);
|
// 0);
|
||||||
|
//
|
||||||
|
// if (gnutlsReturn < 0) {
|
||||||
|
// qDebug() << "Unable to load certificate or key file." << "Error" << gnutlsReturn << "- domain-server will now quit.";
|
||||||
|
// QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
if (gnutlsReturn < 0) {
|
// qDebug() << "Successfully read certificate and private key.";
|
||||||
qDebug() << "Unable to load certificate or key file." << "Error" << gnutlsReturn << "- domain-server will now quit.";
|
|
||||||
QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Successfully read certificate and private key.";
|
|
||||||
|
|
||||||
// we need to also pass this certificate and private key to the HTTPS manager
|
// we need to also pass this certificate and private key to the HTTPS manager
|
||||||
// this is used for Oauth callbacks when authorizing users against a data server
|
// this is used for Oauth callbacks when authorizing users against a data server
|
||||||
|
@ -176,39 +148,6 @@ bool DomainServer::optionallySetupOAuth() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DomainServer::optionallySetupDTLS() {
|
|
||||||
if (_x509Credentials) {
|
|
||||||
qDebug() << "Generating Diffie-Hellman parameters.";
|
|
||||||
|
|
||||||
// generate Diffie-Hellman parameters
|
|
||||||
// When short bit length is used, it might be wise to regenerate parameters often.
|
|
||||||
int dhBits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
|
|
||||||
|
|
||||||
_dhParams = new gnutls_dh_params_t;
|
|
||||||
gnutls_dh_params_init(_dhParams);
|
|
||||||
gnutls_dh_params_generate2(*_dhParams, dhBits);
|
|
||||||
|
|
||||||
qDebug() << "Successfully generated Diffie-Hellman parameters.";
|
|
||||||
|
|
||||||
// set the D-H paramters on the X509 credentials
|
|
||||||
gnutls_certificate_set_dh_params(*_x509Credentials, *_dhParams);
|
|
||||||
|
|
||||||
// setup the key used for cookie verification
|
|
||||||
_cookieKey = new gnutls_datum_t;
|
|
||||||
gnutls_key_generate(_cookieKey, GNUTLS_COOKIE_KEY_SIZE);
|
|
||||||
|
|
||||||
_priorityCache = new gnutls_priority_t;
|
|
||||||
const char DTLS_PRIORITY_STRING[] = "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.2:%SERVER_PRECEDENCE";
|
|
||||||
gnutls_priority_init(_priorityCache, DTLS_PRIORITY_STRING, NULL);
|
|
||||||
|
|
||||||
_isUsingDTLS = true;
|
|
||||||
|
|
||||||
qDebug() << "Initial DTLS setup complete.";
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
||||||
|
|
||||||
const QString CUSTOM_PORT_OPTION = "port";
|
const QString CUSTOM_PORT_OPTION = "port";
|
||||||
|
@ -552,8 +491,8 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
|
|
||||||
if (nodeInterestList.size() > 0) {
|
if (nodeInterestList.size() > 0) {
|
||||||
|
|
||||||
DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
|
// DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
|
||||||
int dataMTU = dtlsSession ? (int)gnutls_dtls_get_data_mtu(*dtlsSession->getGnuTLSSession()) : MAX_PACKET_SIZE;
|
int dataMTU = MAX_PACKET_SIZE;
|
||||||
|
|
||||||
if (nodeData->isAuthenticated()) {
|
if (nodeData->isAuthenticated()) {
|
||||||
// if this authenticated node has any interest types, send back those nodes as well
|
// if this authenticated node has any interest types, send back those nodes as well
|
||||||
|
@ -589,11 +528,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
// we need to break here and start a new packet
|
// we need to break here and start a new packet
|
||||||
// so send the current one
|
// so send the current one
|
||||||
|
|
||||||
if (!dtlsSession) {
|
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
|
||||||
} else {
|
|
||||||
dtlsSession->writeDatagram(broadcastPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset the broadcastPacket structure
|
// reset the broadcastPacket structure
|
||||||
broadcastPacket.resize(numBroadcastPacketLeadBytes);
|
broadcastPacket.resize(numBroadcastPacketLeadBytes);
|
||||||
|
@ -607,11 +542,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
}
|
}
|
||||||
|
|
||||||
// always write the last broadcastPacket
|
// always write the last broadcastPacket
|
||||||
if (!dtlsSession) {
|
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
|
||||||
} else {
|
|
||||||
dtlsSession->writeDatagram(broadcastPacket);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,86 +620,6 @@ void DomainServer::readAvailableDatagrams() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::readAvailableDTLSDatagrams() {
|
|
||||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
|
||||||
|
|
||||||
QUdpSocket& dtlsSocket = nodeList->getDTLSSocket();
|
|
||||||
|
|
||||||
static sockaddr senderSockAddr;
|
|
||||||
static socklen_t sockAddrSize = sizeof(senderSockAddr);
|
|
||||||
|
|
||||||
while (dtlsSocket.hasPendingDatagrams()) {
|
|
||||||
// check if we have an active DTLS session for this sender
|
|
||||||
QByteArray peekDatagram(dtlsSocket.pendingDatagramSize(), 0);
|
|
||||||
|
|
||||||
recvfrom(dtlsSocket.socketDescriptor(), peekDatagram.data(), dtlsSocket.pendingDatagramSize(),
|
|
||||||
MSG_PEEK, &senderSockAddr, &sockAddrSize);
|
|
||||||
|
|
||||||
HifiSockAddr senderHifiSockAddr(&senderSockAddr);
|
|
||||||
DTLSServerSession* existingSession = _dtlsSessions.value(senderHifiSockAddr);
|
|
||||||
|
|
||||||
if (existingSession) {
|
|
||||||
if (!existingSession->completedHandshake()) {
|
|
||||||
// check if we have completed handshake with this user
|
|
||||||
int handshakeReturn = gnutls_handshake(*existingSession->getGnuTLSSession());
|
|
||||||
|
|
||||||
if (handshakeReturn == 0) {
|
|
||||||
existingSession->setCompletedHandshake(true);
|
|
||||||
} else if (gnutls_error_is_fatal(handshakeReturn)) {
|
|
||||||
// this was a fatal error handshaking, so remove this session
|
|
||||||
qDebug() << "Fatal error -" << gnutls_strerror(handshakeReturn) << "- during DTLS handshake with"
|
|
||||||
<< senderHifiSockAddr;
|
|
||||||
_dtlsSessions.remove(senderHifiSockAddr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// pull the data from this user off the stack and process it
|
|
||||||
int receivedBytes = gnutls_record_recv(*existingSession->getGnuTLSSession(),
|
|
||||||
peekDatagram.data(), peekDatagram.size());
|
|
||||||
if (receivedBytes > 0) {
|
|
||||||
processDatagram(peekDatagram.left(receivedBytes), senderHifiSockAddr);
|
|
||||||
} else if (gnutls_error_is_fatal(receivedBytes)) {
|
|
||||||
qDebug() << "Fatal error -" << gnutls_strerror(receivedBytes) << "- during DTLS handshake with"
|
|
||||||
<< senderHifiSockAddr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// first we verify the cookie
|
|
||||||
// see http://gnutls.org/manual/html_node/DTLS-sessions.html for why this is required
|
|
||||||
gnutls_dtls_prestate_st prestate;
|
|
||||||
memset(&prestate, 0, sizeof(prestate));
|
|
||||||
int cookieValid = gnutls_dtls_cookie_verify(_cookieKey, &senderSockAddr, sizeof(senderSockAddr),
|
|
||||||
peekDatagram.data(), peekDatagram.size(), &prestate);
|
|
||||||
|
|
||||||
if (cookieValid < 0) {
|
|
||||||
// the cookie sent by the client was not valid
|
|
||||||
// send a valid one
|
|
||||||
DummyDTLSSession tempServerSession(LimitedNodeList::getInstance()->getDTLSSocket(), senderHifiSockAddr);
|
|
||||||
|
|
||||||
gnutls_dtls_cookie_send(_cookieKey, &senderSockAddr, sizeof(senderSockAddr), &prestate,
|
|
||||||
&tempServerSession, DTLSSession::socketPush);
|
|
||||||
|
|
||||||
// acutally pull the peeked data off the network stack so that it gets discarded
|
|
||||||
dtlsSocket.readDatagram(peekDatagram.data(), peekDatagram.size());
|
|
||||||
} else {
|
|
||||||
// cookie valid but no existing session - set up a new session now
|
|
||||||
DTLSServerSession* newServerSession = new DTLSServerSession(LimitedNodeList::getInstance()->getDTLSSocket(),
|
|
||||||
senderHifiSockAddr);
|
|
||||||
gnutls_session_t* gnutlsSession = newServerSession->getGnuTLSSession();
|
|
||||||
|
|
||||||
gnutls_priority_set(*gnutlsSession, *_priorityCache);
|
|
||||||
gnutls_credentials_set(*gnutlsSession, GNUTLS_CRD_CERTIFICATE, *_x509Credentials);
|
|
||||||
gnutls_dtls_prestate_set(*gnutlsSession, &prestate);
|
|
||||||
|
|
||||||
// handshake to begin the session
|
|
||||||
gnutls_handshake(*gnutlsSession);
|
|
||||||
|
|
||||||
qDebug() << "Beginning DTLS session with node at" << senderHifiSockAddr;
|
|
||||||
_dtlsSessions[senderHifiSockAddr] = newServerSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) {
|
void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) {
|
||||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
||||||
|
|
||||||
|
@ -1210,14 +1061,6 @@ void DomainServer::nodeKilled(SharedNodePointer node) {
|
||||||
reinterpret_cast<DomainServerNodeData*>(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID());
|
reinterpret_cast<DomainServerNodeData*>(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isUsingDTLS) {
|
|
||||||
// check if we need to remove a DTLS session from our in-memory hash
|
|
||||||
DTLSServerSession* existingSession = _dtlsSessions.take(nodeData->getSendingSockAddr());
|
|
||||||
if (existingSession) {
|
|
||||||
delete existingSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,15 +26,12 @@
|
||||||
#include <HTTPSConnection.h>
|
#include <HTTPSConnection.h>
|
||||||
#include <LimitedNodeList.h>
|
#include <LimitedNodeList.h>
|
||||||
|
|
||||||
#include "DTLSServerSession.h"
|
|
||||||
|
|
||||||
typedef QSharedPointer<Assignment> SharedAssignmentPointer;
|
typedef QSharedPointer<Assignment> SharedAssignmentPointer;
|
||||||
|
|
||||||
class DomainServer : public QCoreApplication, public HTTPSRequestHandler {
|
class DomainServer : public QCoreApplication, public HTTPSRequestHandler {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DomainServer(int argc, char* argv[]);
|
DomainServer(int argc, char* argv[]);
|
||||||
~DomainServer();
|
|
||||||
|
|
||||||
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
||||||
bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url);
|
bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url);
|
||||||
|
@ -50,11 +47,9 @@ public slots:
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void readAvailableDatagrams();
|
void readAvailableDatagrams();
|
||||||
void readAvailableDTLSDatagrams();
|
|
||||||
private:
|
private:
|
||||||
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
|
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
|
||||||
bool optionallySetupOAuth();
|
bool optionallySetupOAuth();
|
||||||
bool optionallySetupDTLS();
|
|
||||||
bool optionallyReadX509KeyAndCertificate();
|
bool optionallyReadX509KeyAndCertificate();
|
||||||
|
|
||||||
void processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr);
|
void processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr);
|
||||||
|
@ -96,12 +91,6 @@ private:
|
||||||
QVariantMap _argumentVariantMap;
|
QVariantMap _argumentVariantMap;
|
||||||
|
|
||||||
bool _isUsingDTLS;
|
bool _isUsingDTLS;
|
||||||
gnutls_certificate_credentials_t* _x509Credentials;
|
|
||||||
gnutls_dh_params_t* _dhParams;
|
|
||||||
gnutls_datum_t* _cookieKey;
|
|
||||||
gnutls_priority_t* _priorityCache;
|
|
||||||
|
|
||||||
QHash<HifiSockAddr, DTLSServerSession*> _dtlsSessions;
|
|
||||||
|
|
||||||
QNetworkAccessManager* _networkAccessManager;
|
QNetworkAccessManager* _networkAccessManager;
|
||||||
|
|
||||||
|
|
|
@ -173,10 +173,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
_previousScriptLocation(),
|
_previousScriptLocation(),
|
||||||
_runningScriptsWidget(new RunningScriptsWidget(_window)),
|
_runningScriptsWidget(new RunningScriptsWidget(_window)),
|
||||||
_runningScriptsWidgetWasVisible(false)
|
_runningScriptsWidgetWasVisible(false)
|
||||||
{
|
{
|
||||||
// init GnuTLS for DTLS with domain-servers
|
|
||||||
DTLSClientSession::globalInit();
|
|
||||||
|
|
||||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||||
QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
|
QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||||
|
|
||||||
|
@ -431,8 +428,6 @@ Application::~Application() {
|
||||||
delete _glWidget;
|
delete _glWidget;
|
||||||
|
|
||||||
AccountManager::getInstance().destroy();
|
AccountManager::getInstance().destroy();
|
||||||
|
|
||||||
DTLSClientSession::globalDeinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::saveSettings() {
|
void Application::saveSettings() {
|
||||||
|
|
|
@ -28,12 +28,35 @@ OAuthWebViewHandler::OAuthWebViewHandler() :
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char HIGH_FIDELITY_CA[] = "-----BEGIN CERTIFICATE-----\n"
|
||||||
|
"MIID6TCCA1KgAwIBAgIJANlfRkRD9A8bMA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD\n"
|
||||||
|
"VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j\n"
|
||||||
|
"aXNjbzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVy\n"
|
||||||
|
"YXRpb25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEW\n"
|
||||||
|
"E29wc0BoaWdoZmlkZWxpdHkuaW8wHhcNMTQwMzI4MjIzMzM1WhcNMjQwMzI1MjIz\n"
|
||||||
|
"MzM1WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV\n"
|
||||||
|
"BAcTDVNhbiBGcmFuY2lzY28xGzAZBgNVBAoTEkhpZ2ggRmlkZWxpdHksIEluYzET\n"
|
||||||
|
"MBEGA1UECxMKT3BlcmF0aW9uczEYMBYGA1UEAxMPaGlnaGZpZGVsaXR5LmlvMSIw\n"
|
||||||
|
"IAYJKoZIhvcNAQkBFhNvcHNAaGlnaGZpZGVsaXR5LmlvMIGfMA0GCSqGSIb3DQEB\n"
|
||||||
|
"AQUAA4GNADCBiQKBgQDyo1euYiPPEdnvDZnIjWrrP230qUKMSj8SWoIkbTJF2hE8\n"
|
||||||
|
"2eP3YOgbgSGBzZ8EJBxIOuNmj9g9Eg6691hIKFqy5W0BXO38P04Gg+pVBvpHFGBi\n"
|
||||||
|
"wpqGbfsjaUDuYmBeJRcMO0XYkLCRQG+lAQNHoFDdItWAJfC3FwtP3OCDnz8cNwID\n"
|
||||||
|
"AQABo4IBEzCCAQ8wHQYDVR0OBBYEFCSv2kmiGg6VFMnxXzLDNP304cPAMIHfBgNV\n"
|
||||||
|
"HSMEgdcwgdSAFCSv2kmiGg6VFMnxXzLDNP304cPAoYGwpIGtMIGqMQswCQYDVQQG\n"
|
||||||
|
"EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\n"
|
||||||
|
"bzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVyYXRp\n"
|
||||||
|
"b25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEWE29w\n"
|
||||||
|
"c0BoaWdoZmlkZWxpdHkuaW+CCQDZX0ZEQ/QPGzAMBgNVHRMEBTADAQH/MA0GCSqG\n"
|
||||||
|
"SIb3DQEBBQUAA4GBAEkQl3p+lH5vuoCNgyfa67nL0MsBEt+5RSBOgjwCjjASjzou\n"
|
||||||
|
"FTv5w0he2OypgMQb8i/BYtS1lJSFqjPJcSM1Salzrm3xDOK5pOXJ7h6SQLPDVEyf\n"
|
||||||
|
"Hy2/9d/to+99+SOUlvfzfgycgjOc+s/AV7Y+GBd7uzGxUdrN4egCZW1F6/mH\n"
|
||||||
|
"-----END CERTIFICATE-----\n";
|
||||||
|
|
||||||
void OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig() {
|
void OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig() {
|
||||||
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
|
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
|
||||||
|
|
||||||
// add the High Fidelity root CA to the list of trusted CA certificates
|
// add the High Fidelity root CA to the list of trusted CA certificates
|
||||||
QByteArray highFidelityCACertificate(reinterpret_cast<char*>(DTLSSession::highFidelityCADatum()->data),
|
QByteArray highFidelityCACertificate(HIGH_FIDELITY_CA, sizeof(HIGH_FIDELITY_CA));
|
||||||
DTLSSession::highFidelityCADatum()->size);
|
|
||||||
sslConfig.setCaCertificates(sslConfig.caCertificates() + QSslCertificate::fromData(highFidelityCACertificate));
|
sslConfig.setCaCertificates(sslConfig.caCertificates() + QSslCertificate::fromData(highFidelityCACertificate));
|
||||||
|
|
||||||
// set the modified configuration
|
// set the modified configuration
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
//
|
|
||||||
// DTLSClientSession.cpp
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-01.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "DomainHandler.h"
|
|
||||||
|
|
||||||
#include "DTLSClientSession.h"
|
|
||||||
|
|
||||||
gnutls_certificate_credentials_t DTLSClientSession::_x509CACredentials;
|
|
||||||
|
|
||||||
void DTLSClientSession::globalInit() {
|
|
||||||
static bool initialized = false;
|
|
||||||
|
|
||||||
if (!initialized) {
|
|
||||||
gnutls_global_init();
|
|
||||||
gnutls_certificate_allocate_credentials(&_x509CACredentials);
|
|
||||||
|
|
||||||
gnutls_certificate_set_x509_trust_mem(_x509CACredentials, DTLSSession::highFidelityCADatum(), GNUTLS_X509_FMT_PEM);
|
|
||||||
gnutls_certificate_set_verify_function(_x509CACredentials, DTLSClientSession::verifyServerCertificate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DTLSClientSession::globalDeinit() {
|
|
||||||
gnutls_certificate_free_credentials(_x509CACredentials);
|
|
||||||
|
|
||||||
gnutls_global_deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
int DTLSClientSession::verifyServerCertificate(gnutls_session_t session) {
|
|
||||||
unsigned int verifyStatus = 0;
|
|
||||||
|
|
||||||
// grab the hostname from the domain handler that this session is associated with
|
|
||||||
DomainHandler* domainHandler = reinterpret_cast<DomainHandler*>(gnutls_session_get_ptr(session));
|
|
||||||
qDebug() << "Checking for" << domainHandler->getHostname() << "from cert.";
|
|
||||||
|
|
||||||
int certReturn = gnutls_certificate_verify_peers3(session,
|
|
||||||
domainHandler->getHostname().toLocal8Bit().constData(),
|
|
||||||
&verifyStatus);
|
|
||||||
|
|
||||||
if (certReturn < 0) {
|
|
||||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
gnutls_certificate_type_t typeReturn = gnutls_certificate_type_get(session);
|
|
||||||
|
|
||||||
gnutls_datum_t printOut;
|
|
||||||
|
|
||||||
certReturn = gnutls_certificate_verification_status_print(verifyStatus, typeReturn, &printOut, 0);
|
|
||||||
|
|
||||||
if (certReturn < 0) {
|
|
||||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Gnutls certificate verification status:" << reinterpret_cast<char *>(printOut.data);
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
free(printOut.data);
|
|
||||||
#else
|
|
||||||
gnutls_free(printOut.data);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (verifyStatus != 0) {
|
|
||||||
qDebug() << "Server provided certificate for DTLS is not trusted. Can not complete handshake.";
|
|
||||||
return GNUTLS_E_CERTIFICATE_ERROR;
|
|
||||||
} else {
|
|
||||||
// certificate is valid, continue handshaking as normal
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DTLSClientSession::DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
|
||||||
DTLSSession(GNUTLS_CLIENT, dtlsSocket, destinationSocket)
|
|
||||||
{
|
|
||||||
gnutls_priority_set_direct(_gnutlsSession, "PERFORMANCE", NULL);
|
|
||||||
gnutls_credentials_set(_gnutlsSession, GNUTLS_CRD_CERTIFICATE, _x509CACredentials);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
//
|
|
||||||
// DTLSClientSession.h
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-01.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_DTLSClientSession_h
|
|
||||||
#define hifi_DTLSClientSession_h
|
|
||||||
|
|
||||||
#include "DTLSSession.h"
|
|
||||||
|
|
||||||
class DTLSClientSession : public DTLSSession {
|
|
||||||
public:
|
|
||||||
DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
|
||||||
|
|
||||||
static void globalInit();
|
|
||||||
static void globalDeinit();
|
|
||||||
|
|
||||||
static int verifyServerCertificate(gnutls_session_t session);
|
|
||||||
|
|
||||||
static gnutls_certificate_credentials_t _x509CACredentials;
|
|
||||||
static bool _wasGloballyInitialized;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_DTLSClientSession_h
|
|
|
@ -1,145 +0,0 @@
|
||||||
//
|
|
||||||
// DTLSSession.cpp
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-01.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <gnutls/dtls.h>
|
|
||||||
|
|
||||||
#include "NodeList.h"
|
|
||||||
#include "DTLSSession.h"
|
|
||||||
|
|
||||||
int DTLSSession::socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms) {
|
|
||||||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
|
||||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
|
||||||
|
|
||||||
if (dtlsSocket.hasPendingDatagrams()) {
|
|
||||||
// peek the data on stack to see if it belongs to this session
|
|
||||||
static sockaddr senderSockAddr;
|
|
||||||
static socklen_t sockAddrSize = sizeof(senderSockAddr);
|
|
||||||
|
|
||||||
QByteArray peekDatagram(dtlsSocket.pendingDatagramSize(), 0);
|
|
||||||
|
|
||||||
recvfrom(dtlsSocket.socketDescriptor(), peekDatagram.data(), dtlsSocket.pendingDatagramSize(),
|
|
||||||
MSG_PEEK, &senderSockAddr, &sockAddrSize);
|
|
||||||
|
|
||||||
if (HifiSockAddr(&senderSockAddr) == session->_destinationSocket) {
|
|
||||||
// there is data for this session ready to be read
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
// the next data from the dtlsSocket is not for this session
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no data available on the dtlsSocket
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t DTLSSession::socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size) {
|
|
||||||
DTLSSession* session = static_cast<DTLSSession*>(ptr);
|
|
||||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
|
||||||
|
|
||||||
HifiSockAddr pulledSockAddr;
|
|
||||||
qint64 bytesReceived = dtlsSocket.readDatagram(reinterpret_cast<char*>(buffer), size,
|
|
||||||
pulledSockAddr.getAddressPointer(), pulledSockAddr.getPortPointer());
|
|
||||||
if (bytesReceived == -1) {
|
|
||||||
// no data to pull, return -1
|
|
||||||
#if DTLS_VERBOSE_DEBUG
|
|
||||||
qDebug() << "Received no data on call to readDatagram";
|
|
||||||
#endif
|
|
||||||
return bytesReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pulledSockAddr == session->_destinationSocket) {
|
|
||||||
// bytes received from the correct sender, return number of bytes received
|
|
||||||
|
|
||||||
#if DTLS_VERBOSE_DEBUG
|
|
||||||
qDebug() << "Received" << bytesReceived << "on DTLS socket from" << pulledSockAddr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return bytesReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we pulled a packet not matching this session, so output that
|
|
||||||
qDebug() << "Denied connection from" << pulledSockAddr;
|
|
||||||
|
|
||||||
gnutls_transport_set_errno(session->_gnutlsSession, GNUTLS_E_AGAIN);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
gnutls_datum_t* DTLSSession::highFidelityCADatum() {
|
|
||||||
static gnutls_datum_t hifiCADatum;
|
|
||||||
static bool datumInitialized = false;
|
|
||||||
|
|
||||||
static unsigned char HIGHFIDELITY_ROOT_CA_CERT[] =
|
|
||||||
"-----BEGIN CERTIFICATE-----\n"
|
|
||||||
"MIID6TCCA1KgAwIBAgIJANlfRkRD9A8bMA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD\n"
|
|
||||||
"VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j\n"
|
|
||||||
"aXNjbzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVy\n"
|
|
||||||
"YXRpb25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEW\n"
|
|
||||||
"E29wc0BoaWdoZmlkZWxpdHkuaW8wHhcNMTQwMzI4MjIzMzM1WhcNMjQwMzI1MjIz\n"
|
|
||||||
"MzM1WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV\n"
|
|
||||||
"BAcTDVNhbiBGcmFuY2lzY28xGzAZBgNVBAoTEkhpZ2ggRmlkZWxpdHksIEluYzET\n"
|
|
||||||
"MBEGA1UECxMKT3BlcmF0aW9uczEYMBYGA1UEAxMPaGlnaGZpZGVsaXR5LmlvMSIw\n"
|
|
||||||
"IAYJKoZIhvcNAQkBFhNvcHNAaGlnaGZpZGVsaXR5LmlvMIGfMA0GCSqGSIb3DQEB\n"
|
|
||||||
"AQUAA4GNADCBiQKBgQDyo1euYiPPEdnvDZnIjWrrP230qUKMSj8SWoIkbTJF2hE8\n"
|
|
||||||
"2eP3YOgbgSGBzZ8EJBxIOuNmj9g9Eg6691hIKFqy5W0BXO38P04Gg+pVBvpHFGBi\n"
|
|
||||||
"wpqGbfsjaUDuYmBeJRcMO0XYkLCRQG+lAQNHoFDdItWAJfC3FwtP3OCDnz8cNwID\n"
|
|
||||||
"AQABo4IBEzCCAQ8wHQYDVR0OBBYEFCSv2kmiGg6VFMnxXzLDNP304cPAMIHfBgNV\n"
|
|
||||||
"HSMEgdcwgdSAFCSv2kmiGg6VFMnxXzLDNP304cPAoYGwpIGtMIGqMQswCQYDVQQG\n"
|
|
||||||
"EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\n"
|
|
||||||
"bzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVyYXRp\n"
|
|
||||||
"b25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEWE29w\n"
|
|
||||||
"c0BoaWdoZmlkZWxpdHkuaW+CCQDZX0ZEQ/QPGzAMBgNVHRMEBTADAQH/MA0GCSqG\n"
|
|
||||||
"SIb3DQEBBQUAA4GBAEkQl3p+lH5vuoCNgyfa67nL0MsBEt+5RSBOgjwCjjASjzou\n"
|
|
||||||
"FTv5w0he2OypgMQb8i/BYtS1lJSFqjPJcSM1Salzrm3xDOK5pOXJ7h6SQLPDVEyf\n"
|
|
||||||
"Hy2/9d/to+99+SOUlvfzfgycgjOc+s/AV7Y+GBd7uzGxUdrN4egCZW1F6/mH\n"
|
|
||||||
"-----END CERTIFICATE-----\n";
|
|
||||||
|
|
||||||
if (!datumInitialized) {
|
|
||||||
hifiCADatum.data = HIGHFIDELITY_ROOT_CA_CERT;
|
|
||||||
hifiCADatum.size = sizeof(HIGHFIDELITY_ROOT_CA_CERT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return &hifiCADatum;
|
|
||||||
}
|
|
||||||
|
|
||||||
DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) :
|
|
||||||
DummyDTLSSession(dtlsSocket, destinationSocket),
|
|
||||||
_completedHandshake(false)
|
|
||||||
{
|
|
||||||
gnutls_init(&_gnutlsSession, end | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK);
|
|
||||||
|
|
||||||
// see http://gnutls.org/manual/html_node/Datagram-TLS-API.html#gnutls_005fdtls_005fset_005fmtu
|
|
||||||
const unsigned int DTLS_MAX_MTU = 1452;
|
|
||||||
gnutls_dtls_set_mtu(_gnutlsSession, DTLS_MAX_MTU);
|
|
||||||
|
|
||||||
const unsigned int DTLS_HANDSHAKE_RETRANSMISSION_TIMEOUT = DOMAIN_SERVER_CHECK_IN_MSECS;
|
|
||||||
const unsigned int DTLS_TOTAL_CONNECTION_TIMEOUT = 2 * NODE_SILENCE_THRESHOLD_MSECS;
|
|
||||||
gnutls_dtls_set_timeouts(_gnutlsSession, DTLS_HANDSHAKE_RETRANSMISSION_TIMEOUT, DTLS_TOTAL_CONNECTION_TIMEOUT);
|
|
||||||
|
|
||||||
gnutls_transport_set_ptr(_gnutlsSession, this);
|
|
||||||
gnutls_transport_set_push_function(_gnutlsSession, DummyDTLSSession::socketPush);
|
|
||||||
gnutls_transport_set_pull_function(_gnutlsSession, socketPull);
|
|
||||||
gnutls_transport_set_pull_timeout_function(_gnutlsSession, socketPullTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
DTLSSession::~DTLSSession() {
|
|
||||||
gnutls_deinit(_gnutlsSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DTLSSession::setCompletedHandshake(bool completedHandshake) {
|
|
||||||
_completedHandshake = completedHandshake;
|
|
||||||
qDebug() << "Completed DTLS handshake with" << _destinationSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 DTLSSession::writeDatagram(const QByteArray& datagram) {
|
|
||||||
// we don't need to put a hash in this packet, so just send it off
|
|
||||||
return gnutls_record_send(_gnutlsSession, datagram.data(), datagram.size());
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
//
|
|
||||||
// DTLSSession.h
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-01.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_DTLSSession_h
|
|
||||||
#define hifi_DTLSSession_h
|
|
||||||
|
|
||||||
#include <QtNetwork/QUdpSocket>
|
|
||||||
|
|
||||||
#include <gnutls/gnutls.h>
|
|
||||||
|
|
||||||
#include "DummyDTLSSession.h"
|
|
||||||
#include "HifiSockAddr.h"
|
|
||||||
|
|
||||||
class DTLSSession : public DummyDTLSSession {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket);
|
|
||||||
~DTLSSession();
|
|
||||||
|
|
||||||
static int socketPullTimeout(gnutls_transport_ptr_t ptr, unsigned int ms);
|
|
||||||
static ssize_t socketPull(gnutls_transport_ptr_t ptr, void* buffer, size_t size);
|
|
||||||
|
|
||||||
static gnutls_datum_t* highFidelityCADatum();
|
|
||||||
|
|
||||||
qint64 writeDatagram(const QByteArray& datagram);
|
|
||||||
|
|
||||||
gnutls_session_t* getGnuTLSSession() { return &_gnutlsSession; }
|
|
||||||
|
|
||||||
bool completedHandshake() const { return _completedHandshake; }
|
|
||||||
void setCompletedHandshake(bool completedHandshake);
|
|
||||||
protected:
|
|
||||||
gnutls_session_t _gnutlsSession;
|
|
||||||
bool _completedHandshake;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_DTLSSession_h
|
|
|
@ -22,16 +22,11 @@ DomainHandler::DomainHandler(QObject* parent) :
|
||||||
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
|
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
|
||||||
_assignmentUUID(),
|
_assignmentUUID(),
|
||||||
_isConnected(false),
|
_isConnected(false),
|
||||||
_dtlsSession(NULL),
|
|
||||||
_handshakeTimer(NULL)
|
_handshakeTimer(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DomainHandler::~DomainHandler() {
|
|
||||||
delete _dtlsSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DomainHandler::clearConnectionInfo() {
|
void DomainHandler::clearConnectionInfo() {
|
||||||
_uuid = QUuid();
|
_uuid = QUuid();
|
||||||
_isConnected = false;
|
_isConnected = false;
|
||||||
|
@ -41,38 +36,12 @@ void DomainHandler::clearConnectionInfo() {
|
||||||
delete _handshakeTimer;
|
delete _handshakeTimer;
|
||||||
_handshakeTimer = NULL;
|
_handshakeTimer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete _dtlsSession;
|
|
||||||
_dtlsSession = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainHandler::reset() {
|
void DomainHandler::reset() {
|
||||||
clearConnectionInfo();
|
clearConnectionInfo();
|
||||||
_hostname = QString();
|
_hostname = QString();
|
||||||
_sockAddr.setAddress(QHostAddress::Null);
|
_sockAddr.setAddress(QHostAddress::Null);
|
||||||
|
|
||||||
delete _dtlsSession;
|
|
||||||
_dtlsSession = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int DTLS_HANDSHAKE_INTERVAL_MSECS = 100;
|
|
||||||
|
|
||||||
void DomainHandler::initializeDTLSSession() {
|
|
||||||
if (!_dtlsSession) {
|
|
||||||
_dtlsSession = new DTLSClientSession(NodeList::getInstance()->getDTLSSocket(), _sockAddr);
|
|
||||||
|
|
||||||
gnutls_session_set_ptr(*_dtlsSession->getGnuTLSSession(), this);
|
|
||||||
|
|
||||||
// start a timer to complete the handshake process
|
|
||||||
_handshakeTimer = new QTimer(this);
|
|
||||||
connect(_handshakeTimer, &QTimer::timeout, this, &DomainHandler::completeDTLSHandshake);
|
|
||||||
|
|
||||||
// start the handshake right now
|
|
||||||
completeDTLSHandshake();
|
|
||||||
|
|
||||||
// start the timer to finish off the handshake
|
|
||||||
_handshakeTimer->start(DTLS_HANDSHAKE_INTERVAL_MSECS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) {
|
void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) {
|
||||||
|
@ -120,30 +89,6 @@ void DomainHandler::setHostname(const QString& hostname) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainHandler::completeDTLSHandshake() {
|
|
||||||
int handshakeReturn = gnutls_handshake(*_dtlsSession->getGnuTLSSession());
|
|
||||||
|
|
||||||
if (handshakeReturn == 0) {
|
|
||||||
// we've shaken hands, so we're good to go now
|
|
||||||
_dtlsSession->setCompletedHandshake(true);
|
|
||||||
|
|
||||||
_handshakeTimer->stop();
|
|
||||||
delete _handshakeTimer;
|
|
||||||
_handshakeTimer = NULL;
|
|
||||||
|
|
||||||
// emit a signal so NodeList can handle incoming DTLS packets
|
|
||||||
emit completedDTLSHandshake();
|
|
||||||
|
|
||||||
} else if (gnutls_error_is_fatal(handshakeReturn)) {
|
|
||||||
// this was a fatal error handshaking, so remove this session
|
|
||||||
qDebug() << "Fatal error -" << gnutls_strerror(handshakeReturn)
|
|
||||||
<< "- during DTLS handshake with DS at"
|
|
||||||
<< qPrintable((_hostname.isEmpty() ? _sockAddr.getAddress().toString() : _hostname));
|
|
||||||
|
|
||||||
clearConnectionInfo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
|
void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
|
||||||
for (int i = 0; i < hostInfo.addresses().size(); i++) {
|
for (int i = 0; i < hostInfo.addresses().size(); i++) {
|
||||||
if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) {
|
if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) {
|
||||||
|
@ -179,5 +124,5 @@ void DomainHandler::parseDTLSRequirementPacket(const QByteArray& dtlsRequirement
|
||||||
|
|
||||||
_sockAddr.setPort(dtlsPort);
|
_sockAddr.setPort(dtlsPort);
|
||||||
|
|
||||||
initializeDTLSSession();
|
// initializeDTLSSession();
|
||||||
}
|
}
|
|
@ -18,7 +18,6 @@
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
#include <QtNetwork/QHostInfo>
|
#include <QtNetwork/QHostInfo>
|
||||||
|
|
||||||
#include "DTLSClientSession.h"
|
|
||||||
#include "HifiSockAddr.h"
|
#include "HifiSockAddr.h"
|
||||||
|
|
||||||
const QString DEFAULT_DOMAIN_HOSTNAME = "sandbox.highfidelity.io";
|
const QString DEFAULT_DOMAIN_HOSTNAME = "sandbox.highfidelity.io";
|
||||||
|
@ -32,7 +31,6 @@ class DomainHandler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DomainHandler(QObject* parent = 0);
|
DomainHandler(QObject* parent = 0);
|
||||||
~DomainHandler();
|
|
||||||
|
|
||||||
void clearConnectionInfo();
|
void clearConnectionInfo();
|
||||||
|
|
||||||
|
@ -56,29 +54,22 @@ public:
|
||||||
bool isConnected() const { return _isConnected; }
|
bool isConnected() const { return _isConnected; }
|
||||||
void setIsConnected(bool isConnected);
|
void setIsConnected(bool isConnected);
|
||||||
|
|
||||||
DTLSClientSession* getDTLSSession() { return _dtlsSession; }
|
|
||||||
|
|
||||||
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void completeDTLSHandshake();
|
|
||||||
void completedHostnameLookup(const QHostInfo& hostInfo);
|
void completedHostnameLookup(const QHostInfo& hostInfo);
|
||||||
signals:
|
signals:
|
||||||
void hostnameChanged(const QString& hostname);
|
void hostnameChanged(const QString& hostname);
|
||||||
void connectedToDomain(const QString& hostname);
|
void connectedToDomain(const QString& hostname);
|
||||||
void completedDTLSHandshake();
|
|
||||||
void DTLSConnectionLost();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset();
|
void reset();
|
||||||
void initializeDTLSSession();
|
|
||||||
|
|
||||||
QUuid _uuid;
|
QUuid _uuid;
|
||||||
QString _hostname;
|
QString _hostname;
|
||||||
HifiSockAddr _sockAddr;
|
HifiSockAddr _sockAddr;
|
||||||
QUuid _assignmentUUID;
|
QUuid _assignmentUUID;
|
||||||
bool _isConnected;
|
bool _isConnected;
|
||||||
DTLSClientSession* _dtlsSession;
|
|
||||||
QTimer* _handshakeTimer;
|
QTimer* _handshakeTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
//
|
|
||||||
// DummyDTLSSession.cpp
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-04.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "DummyDTLSSession.h"
|
|
||||||
|
|
||||||
ssize_t DummyDTLSSession::socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size) {
|
|
||||||
DummyDTLSSession* session = static_cast<DummyDTLSSession*>(ptr);
|
|
||||||
QUdpSocket& dtlsSocket = session->_dtlsSocket;
|
|
||||||
|
|
||||||
#if DTLS_VERBOSE_DEBUG
|
|
||||||
qDebug() << "Pushing a message of size" << size << "to" << session->_destinationSocket;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return dtlsSocket.writeDatagram(reinterpret_cast<const char*>(buffer), size,
|
|
||||||
session->_destinationSocket.getAddress(), session->_destinationSocket.getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
DummyDTLSSession::DummyDTLSSession(QUdpSocket& dtlsSocket, const HifiSockAddr& destinationSocket) :
|
|
||||||
_dtlsSocket(dtlsSocket),
|
|
||||||
_destinationSocket(destinationSocket)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
//
|
|
||||||
// DummyDTLSSession.h
|
|
||||||
// libraries/networking/src
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 2014-04-04.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_DummyDTLSSession_h
|
|
||||||
#define hifi_DummyDTLSSession_h
|
|
||||||
|
|
||||||
#include <QtNetwork/QUdpSocket>
|
|
||||||
|
|
||||||
#include <gnutls/gnutls.h>
|
|
||||||
|
|
||||||
#include "HifiSockAddr.h"
|
|
||||||
|
|
||||||
#define DTLS_VERBOSE_DEBUG 0
|
|
||||||
|
|
||||||
class DummyDTLSSession : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
DummyDTLSSession(QUdpSocket& dtlsSocket, const HifiSockAddr& destinationSocket);
|
|
||||||
|
|
||||||
static ssize_t socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size);
|
|
||||||
protected:
|
|
||||||
QUdpSocket& _dtlsSocket;
|
|
||||||
HifiSockAddr _destinationSocket;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_DummyDTLSSession_h
|
|
|
@ -68,9 +68,6 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
|
||||||
|
|
||||||
// clear our NodeList when logout is requested
|
// clear our NodeList when logout is requested
|
||||||
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset);
|
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset);
|
||||||
|
|
||||||
// perform a function when DTLS handshake is completed
|
|
||||||
connect(&_domainHandler, &DomainHandler::completedDTLSHandshake, this, &NodeList::completedDTLSHandshake);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
|
qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
|
||||||
|
@ -117,30 +114,6 @@ void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::completedDTLSHandshake() {
|
|
||||||
// at this point, we've got a DTLS socket
|
|
||||||
// make this NodeList the handler of DTLS packets
|
|
||||||
connect(_dtlsSocket, &QUdpSocket::readyRead, this, &NodeList::processAvailableDTLSDatagrams);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeList::processAvailableDTLSDatagrams() {
|
|
||||||
while (_dtlsSocket->hasPendingDatagrams()) {
|
|
||||||
QByteArray dtlsPacket(_dtlsSocket->pendingDatagramSize(), 0);
|
|
||||||
|
|
||||||
// pull the data from this user off the stack and process it
|
|
||||||
int receivedBytes = gnutls_record_recv(*_domainHandler.getDTLSSession()->getGnuTLSSession(),
|
|
||||||
dtlsPacket.data(), dtlsPacket.size());
|
|
||||||
if (receivedBytes > 0) {
|
|
||||||
// successful data receive, hand this off to processNodeData
|
|
||||||
processNodeData(_domainHandler.getSockAddr(), dtlsPacket.left(receivedBytes));
|
|
||||||
} else if (gnutls_error_is_fatal(receivedBytes)) {
|
|
||||||
qDebug() << "Fatal error -" << gnutls_strerror(receivedBytes) << "- receiving DTLS packet from domain-server.";
|
|
||||||
} else {
|
|
||||||
qDebug() << "non fatal receive" << receivedBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
|
void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
|
||||||
switch (packetTypeForPacket(packet)) {
|
switch (packetTypeForPacket(packet)) {
|
||||||
case PacketTypeDomainList: {
|
case PacketTypeDomainList: {
|
||||||
|
@ -365,19 +338,9 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
// send a STUN request to figure it out
|
// send a STUN request to figure it out
|
||||||
sendSTUNRequest();
|
sendSTUNRequest();
|
||||||
} else if (!_domainHandler.getIP().isNull()) {
|
} else if (!_domainHandler.getIP().isNull()) {
|
||||||
|
|
||||||
DTLSClientSession* dtlsSession = _domainHandler.getDTLSSession();
|
|
||||||
bool isUsingDTLS = false;
|
bool isUsingDTLS = false;
|
||||||
|
|
||||||
if (dtlsSession) {
|
|
||||||
if (!dtlsSession->completedHandshake()) {
|
|
||||||
// if the handshake process is not complete then we can't check in, so return
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
isUsingDTLS = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketType domainPacketType = !_domainHandler.isConnected()
|
PacketType domainPacketType = !_domainHandler.isConnected()
|
||||||
? PacketTypeDomainConnectRequest : PacketTypeDomainListRequest;
|
? PacketTypeDomainConnectRequest : PacketTypeDomainListRequest;
|
||||||
|
|
||||||
|
@ -405,8 +368,6 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
|
|
||||||
if (!isUsingDTLS) {
|
if (!isUsingDTLS) {
|
||||||
writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid());
|
writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid());
|
||||||
} else {
|
|
||||||
dtlsSession->writeDatagram(domainServerPacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
|
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
|
||||||
|
|
|
@ -83,8 +83,6 @@ public slots:
|
||||||
void reset();
|
void reset();
|
||||||
void sendDomainServerCheckIn();
|
void sendDomainServerCheckIn();
|
||||||
void pingInactiveNodes();
|
void pingInactiveNodes();
|
||||||
void completedDTLSHandshake();
|
|
||||||
void processAvailableDTLSDatagrams();
|
|
||||||
signals:
|
signals:
|
||||||
void limitOfSilentDomainCheckInsReached();
|
void limitOfSilentDomainCheckInsReached();
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue