Merge pull request #5513 from bwent/domain-server-authentication

Add connection token UUId to sign with username when connecting to domain-server
This commit is contained in:
Stephen Birarda 2015-08-07 10:05:00 -07:00
commit eec382ade8
10 changed files with 162 additions and 90 deletions

View file

@ -579,7 +579,6 @@ const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer
void DomainServer::processConnectRequestPacket(QSharedPointer<NLPacket> packet) { void DomainServer::processConnectRequestPacket(QSharedPointer<NLPacket> packet) {
NodeType_t nodeType; NodeType_t nodeType;
HifiSockAddr publicSockAddr, localSockAddr; HifiSockAddr publicSockAddr, localSockAddr;
if (packet->getPayloadSize() == 0) { if (packet->getPayloadSize() == 0) {
return; return;
@ -625,31 +624,62 @@ void DomainServer::processConnectRequestPacket(QSharedPointer<NLPacket> packet)
return; return;
} }
} }
} }
QList<NodeType_t> nodeInterestList; QList<NodeType_t> nodeInterestList;
QString username; QString username;
QByteArray usernameSignature; QByteArray usernameSignature;
packetStream >> nodeInterestList >> username >> usernameSignature;
auto limitedNodeList = DependencyManager::get<LimitedNodeList>(); auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
packetStream >> nodeInterestList;
if (packet->bytesLeftToRead() > 0) {
// try to verify username
packetStream >> username;
}
bool isRestrictingAccess =
_settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool();
// we always let in a user who is sending a packet from our local socket or from the localhost address
bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get<LimitedNodeList>()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost);
if (isRestrictingAccess && !isLocalUser) {
if (!username.isEmpty()) {
// if there's a username, try to unpack username signature
packetStream >> usernameSignature;
if (usernameSignature.isEmpty()) {
// if user didn't include usernameSignature in connect request, send a connectionToken packet
QUuid& connectionToken = _connectionTokenHash[username.toLower()];
if (connectionToken.isNull()) {
connectionToken = QUuid::createUuid();
}
static auto connectionTokenPacket = NLPacket::create(PacketType::DomainServerConnectionToken, NUM_BYTES_RFC4122_UUID);
connectionTokenPacket->reset();
connectionTokenPacket->write(connectionToken.toRfc4122());
limitedNodeList->sendUnreliablePacket(*connectionTokenPacket, packet->getSenderSockAddr());
return;
}
}
}
QString reason; QString reason;
if (!isAssignment && !shouldAllowConnectionFromNode(username, usernameSignature, senderSockAddr, reason)) { if (!isAssignment && !shouldAllowConnectionFromNode(username, usernameSignature, senderSockAddr, reason)) {
// this is an agent and we've decided we won't let them connect - send them a packet to deny connection // this is an agent and we've decided we won't let them connect - send them a packet to deny connection
QByteArray utfString = reason.toUtf8(); QByteArray utfString = reason.toUtf8();
quint16 payloadSize = utfString.size(); quint16 payloadSize = utfString.size();
auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied, payloadSize + sizeof(payloadSize)); auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied, payloadSize + sizeof(payloadSize));
connectionDeniedPacket->writePrimitive(payloadSize); if (payloadSize > 0) {
connectionDeniedPacket->write(utfString); connectionDeniedPacket->writePrimitive(payloadSize);
connectionDeniedPacket->write(utfString);
}
// tell client it has been refused. // tell client it has been refused.
limitedNodeList->sendPacket(std::move(connectionDeniedPacket), senderSockAddr); limitedNodeList->sendPacket(std::move(connectionDeniedPacket), senderSockAddr);
return; return;
} }
@ -736,6 +766,7 @@ void DomainServer::processConnectRequestPacket(QSharedPointer<NLPacket> packet)
} }
} }
void DomainServer::processListRequestPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) { void DomainServer::processListRequestPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
NodeType_t throwawayNodeType; NodeType_t throwawayNodeType;
@ -766,52 +797,61 @@ unsigned int DomainServer::countConnectedUsers() {
} }
bool DomainServer::verifyUsersKey(const QString& username, bool DomainServer::verifyUserSignature(const QString& username,
const QByteArray& usernameSignature, const QByteArray& usernameSignature,
QString& reasonReturn) { QString& reasonReturn) {
// it's possible this user can be allowed to connect, but we need to check their username signature // it's possible this user can be allowed to connect, but we need to check their username signature
QByteArray publicKeyArray = _userPublicKeys.value(username); QByteArray publicKeyArray = _userPublicKeys.value(username);
if (!publicKeyArray.isEmpty()) {
const QUuid& connectionToken = _connectionTokenHash.value(username.toLower());
if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) {
// if we do have a public key for the user, check for a signature match // if we do have a public key for the user, check for a signature match
const unsigned char* publicKeyData = reinterpret_cast<const unsigned char*>(publicKeyArray.constData()); const unsigned char* publicKeyData = reinterpret_cast<const unsigned char*>(publicKeyArray.constData());
// first load up the public key into an RSA struct // first load up the public key into an RSA struct
RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size());
QByteArray lowercaseUsername = username.toLower().toUtf8();
QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()),
QCryptographicHash::Sha256);
if (rsaPublicKey) { if (rsaPublicKey) {
QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); QByteArray decryptedArray(RSA_size(rsaPublicKey), 0);
int decryptResult = int decryptResult = RSA_verify(NID_sha256,
RSA_public_decrypt(usernameSignature.size(), reinterpret_cast<const unsigned char*>(usernameWithToken.constData()),
reinterpret_cast<const unsigned char*>(usernameSignature.constData()), usernameWithToken.size(),
reinterpret_cast<unsigned char*>(decryptedArray.data()), reinterpret_cast<const unsigned char*>(usernameSignature.constData()),
rsaPublicKey, RSA_PKCS1_PADDING); usernameSignature.size(),
rsaPublicKey);
if (decryptResult == 1) {
qDebug() << "Username signature matches for" << username << "- allowing connection.";
if (decryptResult != -1) { // free up the public key and remove connection token before we return
if (username.toLower() == decryptedArray) { RSA_free(rsaPublicKey);
qDebug() << "Username signature matches for" << username << "- allowing connection."; _connectionTokenHash.remove(username);
// free up the public key before we return return true;
RSA_free(rsaPublicKey);
return true;
} else {
qDebug() << "Username signature did not match for" << username << "- denying connection.";
reasonReturn = "Username signature did not match.";
}
} else { } else {
qDebug() << "Couldn't decrypt user signature for" << username << "- denying connection."; qDebug() << "Error decrypting username signature for " << username << "- denying connection.";
reasonReturn = "Couldn't decrypt user signature."; reasonReturn = "Error decrypting username signature.";
// free up the public key, we don't need it anymore
RSA_free(rsaPublicKey);
} }
// free up the public key, we don't need it anymore
RSA_free(rsaPublicKey);
} else { } else {
// we can't let this user in since we couldn't convert their public key to an RSA key we could use // we can't let this user in since we couldn't convert their public key to an RSA key we could use
qDebug() << "Couldn't convert data to RSA key for" << username << "- denying connection."; qDebug() << "Couldn't convert data to RSA key for" << username << "- denying connection.";
reasonReturn = "Couldn't convert data to RSA key."; reasonReturn = "Couldn't convert data to RSA key.";
} }
} else {
qDebug() << "Insufficient data to decrypt username signature - denying connection.";
reasonReturn = "Insufficient data";
} }
requestUserPublicKey(username); // no joy. maybe next time? requestUserPublicKey(username); // no joy. maybe next time?
@ -823,41 +863,40 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username,
const QByteArray& usernameSignature, const QByteArray& usernameSignature,
const HifiSockAddr& senderSockAddr, const HifiSockAddr& senderSockAddr,
QString& reasonReturn) { QString& reasonReturn) {
//TODO: improve flow so these bools aren't declared twice
bool isRestrictingAccess = bool isRestrictingAccess =
_settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool();
bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get<LimitedNodeList>()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost);
// we always let in a user who is sending a packet from our local socket or from the localhost address if (isRestrictingAccess && !isLocalUser) {
if (senderSockAddr.getAddress() == DependencyManager::get<LimitedNodeList>()->getLocalSockAddr().getAddress()
|| senderSockAddr.getAddress() == QHostAddress::LocalHost) {
return true;
}
if (isRestrictingAccess) {
QStringList allowedUsers = QStringList allowedUsers =
_settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList();
if (allowedUsers.contains(username, Qt::CaseInsensitive)) { if (allowedUsers.contains(username, Qt::CaseInsensitive)) {
if (!verifyUsersKey(username, usernameSignature, reasonReturn)) { if (username.isEmpty()) {
qDebug() << "Connect request denied - no username provided.";
reasonReturn = "No username provided";
return false;
}
if (!verifyUserSignature(username, usernameSignature, reasonReturn)) {
return false; return false;
} }
} else { } else {
qDebug() << "Connect request denied for user" << username << "not in allowed users list."; qDebug() << "Connect request denied for user" << username << "not in allowed users list.";
reasonReturn = "User not on whitelist."; reasonReturn = "User not on whitelist.";
return false; return false;
} }
} }
// either we aren't restricting users, or this user is in the allowed list // either we aren't restricting users, or this user is in the allowed list
// if this user is in the editors list, exempt them from the max-capacity check // if this user is in the editors list, exempt them from the max-capacity check
const QVariant* allowedEditorsVariant = const QVariant* allowedEditorsVariant =
valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH);
QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList();
if (allowedEditors.contains(username)) { if (allowedEditors.contains(username)) {
if (verifyUsersKey(username, usernameSignature, reasonReturn)) { if (verifyUserSignature(username, usernameSignature, reasonReturn)) {
return true; return true;
} }
} }

View file

@ -90,7 +90,7 @@ private:
void pingPunchForConnectingPeer(const SharedNetworkPeer& peer); void pingPunchForConnectingPeer(const SharedNetworkPeer& peer);
unsigned int countConnectedUsers(); unsigned int countConnectedUsers();
bool verifyUsersKey (const QString& username, const QByteArray& usernameSignature, QString& reasonReturn); bool verifyUserSignature (const QString& username, const QByteArray& usernameSignature, QString& reasonReturn);
bool shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, bool shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature,
const HifiSockAddr& senderSockAddr, QString& reasonReturn); const HifiSockAddr& senderSockAddr, QString& reasonReturn);
@ -149,6 +149,8 @@ private:
QSet<QUuid> _webAuthenticationStateSet; QSet<QUuid> _webAuthenticationStateSet;
QHash<QUuid, DomainServerWebSessionData> _cookieSessionHash; QHash<QUuid, DomainServerWebSessionData> _cookieSessionHash;
QHash<QString, QUuid> _connectionTokenHash;
QHash<QString, QByteArray> _userPublicKeys; QHash<QString, QByteArray> _userPublicKeys;

View file

@ -10,11 +10,13 @@
// //
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/x509.h>
#include <qjsondocument.h> #include <qjsondocument.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QDataStream> #include <QtCore/QDataStream>
#include "UUID.h"
#include "NetworkLogging.h" #include "NetworkLogging.h"
#include "DataServerAccountInfo.h" #include "DataServerAccountInfo.h"
@ -30,8 +32,7 @@ DataServerAccountInfo::DataServerAccountInfo() :
_walletID(), _walletID(),
_balance(0), _balance(0),
_hasBalance(false), _hasBalance(false),
_privateKey(), _privateKey()
_usernameSignature()
{ {
} }
@ -73,9 +74,6 @@ void DataServerAccountInfo::setAccessTokenFromJSON(const QJsonObject& jsonObject
void DataServerAccountInfo::setUsername(const QString& username) { void DataServerAccountInfo::setUsername(const QString& username) {
if (_username != username) { if (_username != username) {
_username = username; _username = username;
// clear our username signature so it has to be re-created
_usernameSignature = QByteArray();
qCDebug(networking) << "Username changed to" << username; qCDebug(networking) << "Username changed to" << username;
} }
@ -128,8 +126,8 @@ void DataServerAccountInfo::setProfileInfoFromJSON(const QJsonObject& jsonObject
setWalletID(QUuid(user["wallet_id"].toString())); setWalletID(QUuid(user["wallet_id"].toString()));
} }
const QByteArray& DataServerAccountInfo::getUsernameSignature() { QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionToken) {
if (_usernameSignature.isEmpty()) {
if (!_privateKey.isEmpty()) { if (!_privateKey.isEmpty()) {
const char* privateKeyData = _privateKey.constData(); const char* privateKeyData = _privateKey.constData();
RSA* rsaPrivateKey = d2i_RSAPrivateKey(NULL, RSA* rsaPrivateKey = d2i_RSAPrivateKey(NULL,
@ -137,36 +135,41 @@ const QByteArray& DataServerAccountInfo::getUsernameSignature() {
_privateKey.size()); _privateKey.size());
if (rsaPrivateKey) { if (rsaPrivateKey) {
QByteArray lowercaseUsername = _username.toLower().toUtf8(); QByteArray lowercaseUsername = _username.toLower().toUtf8();
_usernameSignature.resize(RSA_size(rsaPrivateKey)); QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()),
QCryptographicHash::Sha256);
int encryptReturn = RSA_private_encrypt(lowercaseUsername.size(), QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0);
reinterpret_cast<const unsigned char*>(lowercaseUsername.constData()), unsigned int usernameSignatureSize = 0;
reinterpret_cast<unsigned char*>(_usernameSignature.data()),
rsaPrivateKey, RSA_PKCS1_PADDING);
if (encryptReturn == -1) { int encryptReturn = RSA_sign(NID_sha256,
qCDebug(networking) << "Error encrypting username signature."; reinterpret_cast<const unsigned char*>(usernameWithToken.constData()),
qCDebug(networking) << "Will re-attempt on next domain-server check in."; usernameWithToken.size(),
_usernameSignature = QByteArray(); reinterpret_cast<unsigned char*>(usernameSignature.data()),
} &usernameSignatureSize,
rsaPrivateKey);
// free the private key RSA struct now that we are done with it // free the private key RSA struct now that we are done with it
RSA_free(rsaPrivateKey); RSA_free(rsaPrivateKey);
if (encryptReturn == -1) {
qCDebug(networking) << "Error encrypting username signature.";
qCDebug(networking) << "Will re-attempt on next domain-server check in.";
} else {
qDebug(networking) << "Returning username" << _username << "signed with connection UUID" << uuidStringWithoutCurlyBraces(connectionToken);
return usernameSignature;
}
} else { } else {
qCDebug(networking) << "Could not create RSA struct from QByteArray private key."; qCDebug(networking) << "Could not create RSA struct from QByteArray private key.";
qCDebug(networking) << "Will re-attempt on next domain-server check in."; qCDebug(networking) << "Will re-attempt on next domain-server check in.";
} }
} }
} return QByteArray();
return _usernameSignature;
} }
void DataServerAccountInfo::setPrivateKey(const QByteArray& privateKey) { void DataServerAccountInfo::setPrivateKey(const QByteArray& privateKey) {
_privateKey = privateKey; _privateKey = privateKey;
// clear our username signature so it has to be re-created
_usernameSignature = QByteArray();
} }
QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) { QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) {

View file

@ -43,7 +43,7 @@ public:
const QUuid& getWalletID() const { return _walletID; } const QUuid& getWalletID() const { return _walletID; }
void setWalletID(const QUuid& walletID); void setWalletID(const QUuid& walletID);
const QByteArray& getUsernameSignature(); QByteArray getUsernameSignature(const QUuid& connectionToken);
bool hasPrivateKey() const { return !_privateKey.isEmpty(); } bool hasPrivateKey() const { return !_privateKey.isEmpty(); }
void setPrivateKey(const QByteArray& privateKey); void setPrivateKey(const QByteArray& privateKey);
@ -73,7 +73,7 @@ private:
qint64 _balance; qint64 _balance;
bool _hasBalance; bool _hasBalance;
QByteArray _privateKey; QByteArray _privateKey;
QByteArray _usernameSignature;
}; };
#endif // hifi_DataServerAccountInfo_h #endif // hifi_DataServerAccountInfo_h

View file

@ -29,6 +29,7 @@ DomainHandler::DomainHandler(QObject* parent) :
_uuid(), _uuid(),
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), _sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
_assignmentUUID(), _assignmentUUID(),
_connectionToken(),
_iceDomainID(), _iceDomainID(),
_iceClientID(), _iceClientID(),
_iceServerSockAddr(), _iceServerSockAddr(),
@ -43,7 +44,8 @@ DomainHandler::DomainHandler(QObject* parent) :
void DomainHandler::clearConnectionInfo() { void DomainHandler::clearConnectionInfo() {
_uuid = QUuid(); _uuid = QUuid();
_connectionToken = QUuid();
_icePeer.reset(); _icePeer.reset();
if (requiresICE()) { if (requiresICE()) {

View file

@ -50,9 +50,12 @@ public:
unsigned short getPort() const { return _sockAddr.getPort(); } unsigned short getPort() const { return _sockAddr.getPort(); }
void setPort(quint16 port) { _sockAddr.setPort(port); } void setPort(quint16 port) { _sockAddr.setPort(port); }
const QUuid& getConnectionToken() const { return _connectionToken; }
void setConnectionToken(const QUuid& connectionToken) { _connectionToken = connectionToken; }
const QUuid& getAssignmentUUID() const { return _assignmentUUID; } const QUuid& getAssignmentUUID() const { return _assignmentUUID; }
void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; }
const QUuid& getICEDomainID() const { return _iceDomainID; } const QUuid& getICEDomainID() const { return _iceDomainID; }
const QUuid& getICEClientID() const { return _iceClientID; } const QUuid& getICEClientID() const { return _iceClientID; }
@ -114,6 +117,7 @@ private:
QString _hostname; QString _hostname;
HifiSockAddr _sockAddr; HifiSockAddr _sockAddr;
QUuid _assignmentUUID; QUuid _assignmentUUID;
QUuid _connectionToken;
QUuid _iceDomainID; QUuid _iceDomainID;
QUuid _iceClientID; QUuid _iceClientID;
HifiSockAddr _iceServerSockAddr; HifiSockAddr _iceServerSockAddr;

View file

@ -94,7 +94,7 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
packetReceiver.registerListener(PacketType::PingReply, this, "processPingReplyPacket"); packetReceiver.registerListener(PacketType::PingReply, this, "processPingReplyPacket");
packetReceiver.registerListener(PacketType::ICEPing, this, "processICEPingPacket"); packetReceiver.registerListener(PacketType::ICEPing, this, "processICEPingPacket");
packetReceiver.registerListener(PacketType::DomainServerAddedNode, this, "processDomainServerAddedNode"); packetReceiver.registerListener(PacketType::DomainServerAddedNode, this, "processDomainServerAddedNode");
packetReceiver.registerListener(PacketType::DomainServerConnectionToken, this, "processDomainServerConnectionTokenPacket");
packetReceiver.registerListener(PacketType::ICEServerPeerInformation, &_domainHandler, "processICEResponsePacket"); packetReceiver.registerListener(PacketType::ICEServerPeerInformation, &_domainHandler, "processICEResponsePacket");
packetReceiver.registerListener(PacketType::DomainServerRequireDTLS, &_domainHandler, "processDTLSRequirementPacket"); packetReceiver.registerListener(PacketType::DomainServerRequireDTLS, &_domainHandler, "processDTLSRequirementPacket");
packetReceiver.registerListener(PacketType::ICEPingReply, &_domainHandler, "processICEPingReplyPacket"); packetReceiver.registerListener(PacketType::ICEPingReply, &_domainHandler, "processICEPingReplyPacket");
@ -274,17 +274,23 @@ void NodeList::sendDomainServerCheckIn() {
// pack our data to send to the domain-server // pack our data to send to the domain-server
packetStream << _ownerType << _publicSockAddr << _localSockAddr << _nodeTypesOfInterest.toList(); packetStream << _ownerType << _publicSockAddr << _localSockAddr << _nodeTypesOfInterest.toList();
// if this is a connect request, and we can present a username signature, send it along // if this is a connect request, and we can present a username signature, send it along
if (!_domainHandler.isConnected()) { if (!_domainHandler.isConnected() ) {
DataServerAccountInfo& accountInfo = AccountManager::getInstance().getAccountInfo(); DataServerAccountInfo& accountInfo = AccountManager::getInstance().getAccountInfo();
packetStream << accountInfo.getUsername(); packetStream << accountInfo.getUsername();
const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(); // get connection token from the domain-server
const QUuid& connectionToken = _domainHandler.getConnectionToken();
if (!usernameSignature.isEmpty()) {
qCDebug(networking) << "Including username signature in domain connect request."; if (!connectionToken.isNull()) {
packetStream << usernameSignature;
const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken);
if (!usernameSignature.isEmpty()) {
packetStream << usernameSignature;
}
} }
} }
@ -361,6 +367,7 @@ void NodeList::sendDSPathQuery(const QString& newPath) {
} }
} }
void NodeList::processDomainServerPathResponse(QSharedPointer<NLPacket> packet) { void NodeList::processDomainServerPathResponse(QSharedPointer<NLPacket> packet) {
// This is a response to a path query we theoretically made. // This is a response to a path query we theoretically made.
// In the future we may want to check that this was actually from our DS and for a query we actually made. // In the future we may want to check that this was actually from our DS and for a query we actually made.
@ -450,6 +457,17 @@ void NodeList::pingPunchForDomainServer() {
} }
} }
void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer<NLPacket> packet) {
if (_domainHandler.getSockAddr().isNull()) {
// refuse to process this packet if we aren't currently connected to the DS
return;
}
// read in the connection token from the packet, then send domain-server checkin
_domainHandler.setConnectionToken(QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID)));
sendDomainServerCheckIn();
}
void NodeList::processDomainServerList(QSharedPointer<NLPacket> packet) { void NodeList::processDomainServerList(QSharedPointer<NLPacket> packet) {
if (_domainHandler.getSockAddr().isNull()) { if (_domainHandler.getSockAddr().isNull()) {
// refuse to process this packet if we aren't currently connected to the DS // refuse to process this packet if we aren't currently connected to the DS

View file

@ -76,6 +76,8 @@ public slots:
void processDomainServerAddedNode(QSharedPointer<NLPacket> packet); void processDomainServerAddedNode(QSharedPointer<NLPacket> packet);
void processDomainServerPathResponse(QSharedPointer<NLPacket> packet); void processDomainServerPathResponse(QSharedPointer<NLPacket> packet);
void processDomainServerConnectionTokenPacket(QSharedPointer<NLPacket> packet);
void processPingPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode); void processPingPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
void processPingReplyPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode); void processPingReplyPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);

View file

@ -26,7 +26,7 @@ const QSet<PacketType::Value> SEQUENCE_NUMBERED_PACKETS = QSet<PacketType::Value
const QSet<PacketType::Value> NON_SOURCED_PACKETS = QSet<PacketType::Value>() const QSet<PacketType::Value> NON_SOURCED_PACKETS = QSet<PacketType::Value>()
<< StunResponse << CreateAssignment << RequestAssignment << StunResponse << CreateAssignment << RequestAssignment
<< DomainServerRequireDTLS << DomainConnectRequest << DomainServerRequireDTLS << DomainConnectRequest << DomainServerConnectionToken
<< DomainList << DomainConnectionDenied << DomainList << DomainConnectionDenied
<< DomainServerPathQuery << DomainServerPathResponse << DomainServerPathQuery << DomainServerPathResponse
<< DomainServerAddedNode << DomainServerAddedNode
@ -119,6 +119,7 @@ QString nameForPacketType(PacketType::Value packetType) {
PACKET_TYPE_NAME_LOOKUP(ICEPingReply); PACKET_TYPE_NAME_LOOKUP(ICEPingReply);
PACKET_TYPE_NAME_LOOKUP(EntityAdd); PACKET_TYPE_NAME_LOOKUP(EntityAdd);
PACKET_TYPE_NAME_LOOKUP(EntityEdit); PACKET_TYPE_NAME_LOOKUP(EntityEdit);
PACKET_TYPE_NAME_LOOKUP(DomainServerConnectionToken);
default: default:
return QString("Type: ") + QString::number((int)packetType); return QString("Type: ") + QString::number((int)packetType);
} }

View file

@ -73,7 +73,8 @@ namespace PacketType {
EntityQuery, EntityQuery,
EntityAdd, EntityAdd,
EntityErase, EntityErase,
EntityEdit EntityEdit,
DomainServerConnectionToken
}; };
}; };