mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-07 20:22:27 +02:00
add signed heartbeat sending to domain-server
This commit is contained in:
parent
d444d5dd18
commit
11a1bc4488
7 changed files with 81 additions and 31 deletions
|
@ -42,7 +42,7 @@
|
|||
|
||||
int const DomainServer::EXIT_CODE_REBOOT = 234923;
|
||||
|
||||
const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io";
|
||||
const QString ICE_SERVER_DEFAULT_HOSTNAME = "localhost";
|
||||
|
||||
DomainServer::DomainServer(int argc, char* argv[]) :
|
||||
QCoreApplication(argc, argv),
|
||||
|
@ -1053,11 +1053,55 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) {
|
|||
domainUpdateJSON.toUtf8());
|
||||
}
|
||||
|
||||
// TODO: have data-web respond with ice-server hostname to use
|
||||
|
||||
void DomainServer::sendHeartbeatToIceServer() {
|
||||
if (!_iceServerSocket.getAddress().isNull()) {
|
||||
DependencyManager::get<LimitedNodeList>()->sendHeartbeatToIceServer(_iceServerSocket);
|
||||
static auto heartbeatPacket = NLPacket::create(PacketType::ICEServerHeartbeat);
|
||||
|
||||
bool shouldRecreatePacket = false;
|
||||
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
if (heartbeatPacket->getPayloadSize() > 0) {
|
||||
// if either of our sockets have changed we need to re-sign the heartbeat
|
||||
// first read the sockets out from the current packet
|
||||
heartbeatPacket->seek(0);
|
||||
QDataStream heartbeatStream(heartbeatPacket.get());
|
||||
|
||||
QUuid senderUUID;
|
||||
HifiSockAddr publicSocket, localSocket;
|
||||
heartbeatStream >> senderUUID >> publicSocket >> localSocket;
|
||||
|
||||
if (publicSocket != limitedNodeList->getPublicSockAddr() || localSocket != limitedNodeList->getLocalSockAddr()) {
|
||||
shouldRecreatePacket = true;
|
||||
}
|
||||
} else {
|
||||
shouldRecreatePacket = true;
|
||||
}
|
||||
|
||||
if (shouldRecreatePacket) {
|
||||
// either we don't have a heartbeat packet yet or sockets have changed and we need to make a new one
|
||||
|
||||
// reset the position in the packet before writing
|
||||
heartbeatPacket->reset();
|
||||
|
||||
// write our plaintext data to the packet
|
||||
QDataStream heartbeatDataStream(heartbeatPacket.get());
|
||||
heartbeatDataStream << limitedNodeList->getSessionUUID()
|
||||
<< limitedNodeList->getPublicSockAddr() << limitedNodeList->getLocalSockAddr();
|
||||
|
||||
// setup a QByteArray that points to the plaintext data
|
||||
auto plaintext = QByteArray::fromRawData(heartbeatPacket->getPayload(), heartbeatPacket->getPayloadSize());
|
||||
|
||||
// generate a signature for the plaintext data in the packet
|
||||
auto& accountManager = AccountManager::getInstance();
|
||||
auto signature = accountManager.getAccountInfo().signPlaintext(plaintext);
|
||||
|
||||
// pack the signature with the data
|
||||
heartbeatDataStream << plaintext;
|
||||
}
|
||||
|
||||
// send the heartbeat packet to the ice server now
|
||||
limitedNodeList->sendUnreliablePacket(*heartbeatPacket, _iceServerSocket);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "AccountManager.h"
|
||||
#include "NetworkLogging.h"
|
||||
|
||||
const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false;
|
||||
const bool VERBOSE_HTTP_REQUEST_DEBUGGING = true;
|
||||
|
||||
AccountManager& AccountManager::getInstance(bool forceReset) {
|
||||
static std::unique_ptr<AccountManager> sharedInstance(new AccountManager());
|
||||
|
|
|
@ -117,41 +117,47 @@ void DataServerAccountInfo::setProfileInfoFromJSON(const QJsonObject& jsonObject
|
|||
}
|
||||
|
||||
QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionToken) {
|
||||
|
||||
QByteArray lowercaseUsername = _username.toLower().toUtf8();
|
||||
QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()),
|
||||
QCryptographicHash::Sha256);
|
||||
|
||||
auto signature = signPlaintext(usernameWithToken);
|
||||
if (!signature.isEmpty()) {
|
||||
qDebug(networking) << "Returning username" << _username
|
||||
<< "signed with connection UUID" << uuidStringWithoutCurlyBraces(connectionToken);
|
||||
} else {
|
||||
qCDebug(networking) << "Error signing username with connection token";
|
||||
qCDebug(networking) << "Will re-attempt on next domain-server check in.";
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
QByteArray DataServerAccountInfo::signPlaintext(const QByteArray& plaintext) {
|
||||
if (!_privateKey.isEmpty()) {
|
||||
const char* privateKeyData = _privateKey.constData();
|
||||
RSA* rsaPrivateKey = d2i_RSAPrivateKey(NULL,
|
||||
reinterpret_cast<const unsigned char**>(&privateKeyData),
|
||||
_privateKey.size());
|
||||
if (rsaPrivateKey) {
|
||||
QByteArray lowercaseUsername = _username.toLower().toUtf8();
|
||||
QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()),
|
||||
QCryptographicHash::Sha256);
|
||||
|
||||
QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0);
|
||||
unsigned int usernameSignatureSize = 0;
|
||||
|
||||
QByteArray signature(RSA_size(rsaPrivateKey), 0);
|
||||
unsigned int signatureBytes = 0;
|
||||
|
||||
int encryptReturn = RSA_sign(NID_sha256,
|
||||
reinterpret_cast<const unsigned char*>(usernameWithToken.constData()),
|
||||
usernameWithToken.size(),
|
||||
reinterpret_cast<unsigned char*>(usernameSignature.data()),
|
||||
&usernameSignatureSize,
|
||||
reinterpret_cast<const unsigned char*>(plaintext.constData()),
|
||||
plaintext.size(),
|
||||
reinterpret_cast<unsigned char*>(signature.data()),
|
||||
&signatureBytes,
|
||||
rsaPrivateKey);
|
||||
|
||||
|
||||
// free the private key RSA struct now that we are done with it
|
||||
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;
|
||||
if (encryptReturn != -1) {
|
||||
return signature;
|
||||
}
|
||||
|
||||
} else {
|
||||
qCDebug(networking) << "Could not create RSA struct from QByteArray private key.";
|
||||
qCDebug(networking) << "Will re-attempt on next domain-server check in.";
|
||||
}
|
||||
}
|
||||
return QByteArray();
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
bool hasPrivateKey() const { return !_privateKey.isEmpty(); }
|
||||
void setPrivateKey(const QByteArray& privateKey) { _privateKey = privateKey; }
|
||||
|
||||
QByteArray signPlaintext(const QByteArray& plaintext);
|
||||
|
||||
void setDomainID(const QUuid& domainID) { _domainID = domainID; }
|
||||
const QUuid& getDomainID() const { return _domainID; }
|
||||
|
||||
|
|
|
@ -902,10 +902,6 @@ void LimitedNodeList::updateLocalSockAddr() {
|
|||
}
|
||||
}
|
||||
|
||||
void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSockAddr) {
|
||||
sendPacketToIceServer(PacketType::ICEServerHeartbeat, iceServerSockAddr, _sessionUUID);
|
||||
}
|
||||
|
||||
void LimitedNodeList::sendPeerQueryToIceServer(const HifiSockAddr& iceServerSockAddr, const QUuid& clientID,
|
||||
const QUuid& peerID) {
|
||||
sendPacketToIceServer(PacketType::ICEServerQuery, iceServerSockAddr, clientID, peerID);
|
||||
|
|
|
@ -143,6 +143,7 @@ public:
|
|||
bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; }
|
||||
|
||||
const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; }
|
||||
const HifiSockAddr& getPublicSockAddr() const { return _publicSockAddr; }
|
||||
const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; }
|
||||
|
||||
void processKillNode(ReceivedMessage& message);
|
||||
|
@ -161,7 +162,6 @@ public:
|
|||
std::unique_ptr<NLPacket> constructICEPingPacket(PingType_t pingType, const QUuid& iceID);
|
||||
std::unique_ptr<NLPacket> constructICEPingReplyPacket(ReceivedMessage& message, const QUuid& iceID);
|
||||
|
||||
void sendHeartbeatToIceServer(const HifiSockAddr& iceServerSockAddr);
|
||||
void sendPeerQueryToIceServer(const HifiSockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID);
|
||||
|
||||
SharedNodePointer findNodeWithAddr(const HifiSockAddr& addr);
|
||||
|
|
|
@ -45,6 +45,8 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SoftAttachmentSupport);
|
||||
case PacketType::ICEServerHeartbeat:
|
||||
return 18; // ICE Server Heartbeat signing
|
||||
default:
|
||||
return 17;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue