From b5b4edc999639c60bd3ca97cfc0d7f3354466c19 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 1 Apr 2014 16:47:45 -0700 Subject: [PATCH] add notion of server and client DTLSSessions --- domain-server/src/DTLSServerSession.cpp | 15 ++++++++++ domain-server/src/DTLSServerSession.h | 19 ++++++++++++ domain-server/src/DomainServer.cpp | 34 ++++++++++++++++++---- domain-server/src/DomainServer.h | 4 +++ domain-server/src/DomainServerNodeData.cpp | 3 +- domain-server/src/DomainServerNodeData.h | 5 ++++ libraries/shared/src/DTLSClientSession.cpp | 15 ++++++++++ libraries/shared/src/DTLSClientSession.h | 19 ++++++++++++ libraries/shared/src/DTLSSession.cpp | 20 ++----------- libraries/shared/src/DTLSSession.h | 9 ++++-- libraries/shared/src/DomainHandler.cpp | 2 +- libraries/shared/src/DomainHandler.h | 4 +-- libraries/shared/src/HifiSockAddr.cpp | 19 +++++++++++- libraries/shared/src/HifiSockAddr.h | 3 ++ 14 files changed, 141 insertions(+), 30 deletions(-) create mode 100644 domain-server/src/DTLSServerSession.cpp create mode 100644 domain-server/src/DTLSServerSession.h create mode 100644 libraries/shared/src/DTLSClientSession.cpp create mode 100644 libraries/shared/src/DTLSClientSession.h diff --git a/domain-server/src/DTLSServerSession.cpp b/domain-server/src/DTLSServerSession.cpp new file mode 100644 index 0000000000..994b196357 --- /dev/null +++ b/domain-server/src/DTLSServerSession.cpp @@ -0,0 +1,15 @@ +// +// DTLSServerSession.cpp +// hifi +// +// Created by Stephen Birarda on 2014-04-01. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include "DTLSServerSession.h" + +DTLSServerSession::DTLSServerSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) : + DTLSSession(GNUTLS_SERVER, dtlsSocket, destinationSocket) +{ + +} \ No newline at end of file diff --git a/domain-server/src/DTLSServerSession.h b/domain-server/src/DTLSServerSession.h new file mode 100644 index 0000000000..5bdb0f9e91 --- /dev/null +++ b/domain-server/src/DTLSServerSession.h @@ -0,0 +1,19 @@ +// +// DTLSServerSession.h +// hifi +// +// Created by Stephen Birarda on 2014-04-01. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__DTLSServerSession__ +#define __hifi__DTLSServerSession__ + +#include + +class DTLSServerSession : public DTLSSession { +public: + DTLSServerSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket); +}; + +#endif /* defined(__hifi__DTLSServerSession__) */ diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 60df41007d..ba2f2791bd 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -6,8 +6,6 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include - #include #include #include @@ -393,8 +391,12 @@ void DomainServer::addNodeToNodeListAndConfirmConnection(const QByteArray& packe SharedNodePointer newNode = LimitedNodeList::getInstance()->addOrUpdateNode(nodeUUID, nodeType, publicSockAddr, localSockAddr); - // when the newNode is created the linked data is also created, if this was a static assignment set the UUID - reinterpret_cast(newNode->getLinkedData())->setStaticAssignmentUUID(assignmentUUID); + // when the newNode is created the linked data is also created + // if this was a static assignment set the UUID, set the sendingSockAddr + DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); + + nodeData->setStaticAssignmentUUID(assignmentUUID); + nodeData->setSendingSockAddr(senderSockAddr); if (!authJsonObject.isEmpty()) { // pull the connection secret from the authJsonObject and set it as the connection secret for this node @@ -533,7 +535,6 @@ void DomainServer::readAvailableDatagrams() { HifiSockAddr senderSockAddr; QByteArray receivedPacket; - static QByteArray assignmentPacket = byteArrayWithPopulatedHeader(PacketTypeCreateAssignment); static int numAssignmentPacketHeaderBytes = assignmentPacket.size(); @@ -603,7 +604,30 @@ 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); + + DTLSSession* existingSession = _dtlsSessions.value(HifiSockAddr(&senderSockAddr)); + + qDebug() << "Checking for a session with" << HifiSockAddr(&senderSockAddr); + + if (existingSession) { + // use GnuTLS to receive the encrypted data + } else { + // no existing session - set up a new session now + } + } } void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 7ee6d7374e..a69df5dec0 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -23,6 +23,8 @@ #include #include +#include "DTLSServerSession.h" + typedef QSharedPointer SharedAssignmentPointer; class DomainServer : public QCoreApplication, public HTTPRequestHandler { @@ -88,6 +90,8 @@ private: gnutls_certificate_credentials_t* _x509Credentials; gnutls_dh_params_t* _dhParams; gnutls_priority_t* _priorityCache; + + QHash _dtlsSessions; }; #endif /* defined(__hifi__DomainServer__) */ diff --git a/domain-server/src/DomainServerNodeData.cpp b/domain-server/src/DomainServerNodeData.cpp index f1e08e3bc4..6e94a8a330 100644 --- a/domain-server/src/DomainServerNodeData.cpp +++ b/domain-server/src/DomainServerNodeData.cpp @@ -17,7 +17,8 @@ DomainServerNodeData::DomainServerNodeData() : _sessionSecretHash(), _staticAssignmentUUID(), - _statsJSONObject() + _statsJSONObject(), + _sendingSockAddr() { } diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h index 20531839f4..40516a70aa 100644 --- a/domain-server/src/DomainServerNodeData.h +++ b/domain-server/src/DomainServerNodeData.h @@ -12,6 +12,7 @@ #include #include +#include #include class DomainServerNodeData : public NodeData { @@ -26,6 +27,9 @@ public: void setStaticAssignmentUUID(const QUuid& staticAssignmentUUID) { _staticAssignmentUUID = staticAssignmentUUID; } const QUuid& getStaticAssignmentUUID() const { return _staticAssignmentUUID; } + void setSendingSockAddr(const HifiSockAddr& sendingSockAddr) { _sendingSockAddr = sendingSockAddr; } + const HifiSockAddr& getSendingSockAddr() { return _sendingSockAddr; } + QHash& getSessionSecretHash() { return _sessionSecretHash; } private: QJsonObject mergeJSONStatsFromNewObject(const QJsonObject& newObject, QJsonObject destinationObject); @@ -33,6 +37,7 @@ private: QHash _sessionSecretHash; QUuid _staticAssignmentUUID; QJsonObject _statsJSONObject; + HifiSockAddr _sendingSockAddr; }; #endif /* defined(__hifi__DomainServerNodeData__) */ diff --git a/libraries/shared/src/DTLSClientSession.cpp b/libraries/shared/src/DTLSClientSession.cpp new file mode 100644 index 0000000000..30ca536c9e --- /dev/null +++ b/libraries/shared/src/DTLSClientSession.cpp @@ -0,0 +1,15 @@ +// +// DTLSClientSession.cpp +// hifi +// +// Created by Stephen Birarda on 2014-04-01. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#include "DTLSClientSession.h" + +DTLSClientSession::DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) : + DTLSSession(GNUTLS_CLIENT, dtlsSocket, destinationSocket) +{ + +} \ No newline at end of file diff --git a/libraries/shared/src/DTLSClientSession.h b/libraries/shared/src/DTLSClientSession.h new file mode 100644 index 0000000000..93cd51cb9a --- /dev/null +++ b/libraries/shared/src/DTLSClientSession.h @@ -0,0 +1,19 @@ +// +// DTLSClientSession.h +// hifi +// +// Created by Stephen Birarda on 2014-04-01. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__DTLSClientSession__ +#define __hifi__DTLSClientSession__ + +#include "DTLSSession.h" + +class DTLSClientSession : public DTLSSession { +public: + DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket); +}; + +#endif /* defined(__hifi__DTLSClientSession__) */ diff --git a/libraries/shared/src/DTLSSession.cpp b/libraries/shared/src/DTLSSession.cpp index 90558034a7..6113019cf9 100644 --- a/libraries/shared/src/DTLSSession.cpp +++ b/libraries/shared/src/DTLSSession.cpp @@ -34,7 +34,7 @@ ssize_t DTLSSession::socketPush(gnutls_transport_ptr_t ptr, const void* buffer, session->_destinationSocket.getAddress(), session->_destinationSocket.getPort()); } -static gnutls_certificate_credentials_t* x509ClientCredentials() { +gnutls_certificate_credentials_t* x509CACredentials() { static gnutls_certificate_credentials_t x509Credentials; static bool credentialsInitialized = false; @@ -45,23 +45,9 @@ static gnutls_certificate_credentials_t* x509ClientCredentials() { return &x509Credentials; } -DTLSSession::DTLSSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) : +DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) : _dtlsSocket(dtlsSocket), _destinationSocket(destinationSocket) { - qDebug() << "Initializing DTLS Session."; - - gnutls_init(&_gnutlsSession, GNUTLS_CLIENT | GNUTLS_DATAGRAM); - gnutls_priority_set_direct(_gnutlsSession, "NORMAL", NULL); - - gnutls_credentials_set(_gnutlsSession, GNUTLS_CRD_CERTIFICATE, x509ClientCredentials()); - - // tell GnuTLS to call us for push or pull - gnutls_transport_set_ptr(_gnutlsSession, this); - gnutls_transport_set_push_function(_gnutlsSession, socketPush); - gnutls_transport_set_pull_function(_gnutlsSession, socketPull); - gnutls_transport_set_pull_timeout_function(_gnutlsSession, socketPullTimeout); - - // start the handshake process with domain-server now - gnutls_handshake(_gnutlsSession); + gnutls_init(&_gnutlsSession, end | GNUTLS_DATAGRAM); } \ No newline at end of file diff --git a/libraries/shared/src/DTLSSession.h b/libraries/shared/src/DTLSSession.h index c0077a38b4..ce453c6d22 100644 --- a/libraries/shared/src/DTLSSession.h +++ b/libraries/shared/src/DTLSSession.h @@ -15,13 +15,16 @@ #include "HifiSockAddr.h" -class DTLSSession { +class DTLSSession : public QObject { + Q_OBJECT public: - DTLSSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket); -private: + DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket); + +protected: 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 ssize_t socketPush(gnutls_transport_ptr_t ptr, const void* buffer, size_t size); + static gnutls_certificate_credentials_t* x509CACredentials(); QUdpSocket& _dtlsSocket; gnutls_session_t _gnutlsSession; diff --git a/libraries/shared/src/DomainHandler.cpp b/libraries/shared/src/DomainHandler.cpp index 2881da64c5..e6403dcbc1 100644 --- a/libraries/shared/src/DomainHandler.cpp +++ b/libraries/shared/src/DomainHandler.cpp @@ -42,7 +42,7 @@ void DomainHandler::reset() { void DomainHandler::initializeDTLSSession() { if (!_dtlsSession) { - _dtlsSession = new DTLSSession(NodeList::getInstance()->getDTLSSocket(), _sockAddr); + _dtlsSession = new DTLSClientSession(NodeList::getInstance()->getDTLSSocket(), _sockAddr); } } diff --git a/libraries/shared/src/DomainHandler.h b/libraries/shared/src/DomainHandler.h index 4a9f166963..5032138858 100644 --- a/libraries/shared/src/DomainHandler.h +++ b/libraries/shared/src/DomainHandler.h @@ -14,7 +14,7 @@ #include #include -#include "DTLSSession.h" +#include "DTLSClientSession.h" #include "HifiSockAddr.h" const QString DEFAULT_DOMAIN_HOSTNAME = "alpha.highfidelity.io"; @@ -67,7 +67,7 @@ private: QUuid _assignmentUUID; bool _isConnected; bool _requiresDTLS; - DTLSSession* _dtlsSession; + DTLSClientSession* _dtlsSession; }; #endif /* defined(__hifi__DomainHandler__) */ diff --git a/libraries/shared/src/HifiSockAddr.cpp b/libraries/shared/src/HifiSockAddr.cpp index cc031525d8..8010202424 100644 --- a/libraries/shared/src/HifiSockAddr.cpp +++ b/libraries/shared/src/HifiSockAddr.cpp @@ -6,12 +6,14 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include "HifiSockAddr.h" +#include #include #include #include +#include "HifiSockAddr.h" + static int hifiSockAddrMetaTypeId = qMetaTypeId(); HifiSockAddr::HifiSockAddr() : @@ -44,6 +46,16 @@ HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort) { } } +HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) { + _address = QHostAddress(sockaddr); + + if (sockaddr->sa_family == AF_INET) { + _port = reinterpret_cast(sockaddr)->sin_port; + } else { + _port = reinterpret_cast(sockaddr)->sin6_port; + } +} + HifiSockAddr& HifiSockAddr::operator=(const HifiSockAddr& rhsSockAddr) { _address = rhsSockAddr._address; _port = rhsSockAddr._port; @@ -109,3 +121,8 @@ quint32 getHostOrderLocalAddress() { // return the looked up local address return localAddress; } + +uint qHash(const HifiSockAddr& key, uint seed) { + // use the existing QHostAddress and quint16 hash functions to get our hash + return qHash(key.getAddress(), seed) + qHash(key.getPort(), seed); +} diff --git a/libraries/shared/src/HifiSockAddr.h b/libraries/shared/src/HifiSockAddr.h index e8f928c36d..365067080b 100644 --- a/libraries/shared/src/HifiSockAddr.h +++ b/libraries/shared/src/HifiSockAddr.h @@ -17,6 +17,7 @@ public: HifiSockAddr(const QHostAddress& address, quint16 port); HifiSockAddr(const HifiSockAddr& otherSockAddr); HifiSockAddr(const QString& hostname, quint16 hostOrderPort); + HifiSockAddr(const sockaddr* sockaddr); bool isNull() const { return _address.isNull() && _port == 0; } @@ -45,6 +46,8 @@ private: quint16 _port; }; +uint qHash(const HifiSockAddr& key, uint seed); + quint32 getHostOrderLocalAddress(); Q_DECLARE_METATYPE(HifiSockAddr)