mirror of
https://github.com/overte-org/overte.git
synced 2025-08-05 22:40:12 +02:00
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:
commit
eec382ade8
10 changed files with 162 additions and 90 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,8 @@ namespace PacketType {
|
||||||
EntityQuery,
|
EntityQuery,
|
||||||
EntityAdd,
|
EntityAdd,
|
||||||
EntityErase,
|
EntityErase,
|
||||||
EntityEdit
|
EntityEdit,
|
||||||
|
DomainServerConnectionToken
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue