Throw a bunch of code at the wall and hope some sticks

This commit is contained in:
Zach Fox 2017-10-04 15:06:55 -07:00
parent f7ea50ef3b
commit b35eaf2cc8
5 changed files with 112 additions and 30 deletions

View file

@ -92,7 +92,9 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer<ReceivedMessage>
// Ask our tree subclass if it can handle the incoming packet...
PacketType packetType = message->getType();
if (_myServer->getOctree()->handlesEditPacketType(packetType)) {
if (packetType == PacketType::ChallengeOwnership) {
_myServer->getOctree()->processChallengeOwnershipPacket(*message, sendingNode);
} else if (_myServer->getOctree()->handlesEditPacketType(packetType)) {
PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE", debugProcessPacket);
_receivedPacketCount++;

View file

@ -656,16 +656,29 @@ bool Wallet::changePassphrase(const QString& newPassphrase) {
void Wallet::handleChallengeOwnershipPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
QString decryptedText;
quint64 encryptedTextSize;
quint64 publicKeySize;
int certIDByteArraySize;
int encryptedTextByteArraySize;
int ownerKeyByteArraySize;
if (verifyOwnerChallenge(packet->read(packet->readPrimitive(&encryptedTextSize)), packet->read(packet->readPrimitive(&publicKeySize)), decryptedText)) {
packet->readPrimitive(&certIDByteArraySize);
packet->readPrimitive(&encryptedTextByteArraySize);
packet->readPrimitive(&ownerKeyByteArraySize);
QByteArray certID = packet->read(certIDByteArraySize);
if (verifyOwnerChallenge(packet->read(encryptedTextByteArraySize), packet->read(ownerKeyByteArraySize), decryptedText)) {
auto nodeList = DependencyManager::get<NodeList>();
// setup the packet
auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, NUM_BYTES_RFC4122_UUID + decryptedText.size(), true);
// write the decrypted text to the packet
decryptedTextPacket->write(decryptedText.toUtf8());
QByteArray decryptedTextByteArray = decryptedText.toUtf8();
int decryptedTextByteArraySize = decryptedTextByteArray.size();
int certIDSize = certID.size();
// setup the packet
auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2*sizeof(int), true);
decryptedTextPacket->writePrimitive(certIDSize);
decryptedTextPacket->writePrimitive(decryptedTextByteArraySize);
decryptedTextPacket->write(certID);
decryptedTextPacket->write(decryptedTextByteArray);
qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text";
@ -677,6 +690,6 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer<ReceivedMessage> pack
bool Wallet::verifyOwnerChallenge(const QByteArray& encryptedText, const QString& publicKey, QString& decryptedText) {
// I have no idea how to do this yet, so here's some dummy code that may not even work.
decryptedText = QString("hello");
decryptedText = QString("fail");
return true;
}

View file

@ -1097,6 +1097,30 @@ bool EntityTree::isScriptInWhitelist(const QString& scriptProperty) {
return false;
}
void EntityTree::processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) {
int certIDByteArraySize;
int decryptedTextByteArraySize;
message.readPrimitive(&certIDByteArraySize);
message.readPrimitive(&decryptedTextByteArraySize);
QString certID(message.read(certIDByteArraySize));
QString decryptedText(message.read(decryptedTextByteArraySize));
emit killChallengeOwnershipTimeoutTimer(certID);
if (decryptedText == "fail") {
QReadLocker certIdMapLocker(&_entityCertificateIDMapLock);
EntityItemID id = _entityCertificateIDMap.value(certID);
qCDebug(entities) << "Ownership challenge failed, deleting entity" << id;
deleteEntity(id, true);
QWriteLocker recentlyDeletedLocker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), id);
} else {
}
}
int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
const SharedNodePointer& senderNode) {
@ -1299,6 +1323,8 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
<< "static certificate verification.";
// Delete the entity we just added if it doesn't pass static certificate verification
deleteEntity(entityItemID, true);
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
} else {
QString certID = properties.getCertificateID();
EntityItemID existingEntityItemID;
@ -1314,6 +1340,8 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
qCDebug(entities) << "Certificate ID" << certID << "already exists on entity with ID"
<< existingEntityItemID << ". Deleting existing entity.";
deleteEntity(existingEntityItemID, true);
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), existingEntityItemID);
}
{
@ -1323,6 +1351,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
}
// Start owner verification.
auto nodeList = DependencyManager::get<NodeList>();
// First, asynchronously hit "proof_of_purchase_status?transaction_type=transfer" endpoint.
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest;
@ -1331,7 +1360,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
requestURL.setPath("/api/v1/commerce/proof_of_purchase_status?transaction_type=transfer");
QJsonObject request;
request["certificate_id"] = certID;
request["domain_id"] = DependencyManager::get<NodeList>()->getDomainHandler().getUUID().toString();
request["domain_id"] = nodeList->getDomainHandler().getUUID().toString();
networkRequest.setUrl(requestURL);
QNetworkReply* networkReply = NULL;
@ -1340,33 +1369,68 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
connect(networkReply, &QNetworkReply::finished, [=]() {
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
QJsonDocument doc(jsonObject);
qCDebug(entities) << "ZRF FIXME" << networkReply->error();
qCDebug(entities) << "ZRF FIXME" << doc.toJson(QJsonDocument::Compact);
if (networkReply->error() == QNetworkReply::NoError) {
//QJsonObject jsonObject = QJsonDocument::fromJson(reply.readAll()).object();
//qCDebug(entities) << "ZRF FIXME" << jsonObject;
//if (!jsonObject["invalid_reason"].toString().isEmpty()) {
// qCDebug(entities) << "invalid_reason not empty, deleting entity" << entityItemID;
// deleteEntity(entityItemID, true);
//} else if (jsonObject["transfer_status"].toString() == "failed") {
// qCDebug(entities) << "'transfer_status' is 'failed', deleting entity" << entityItemID;
// deleteEntity(entityItemID, true);
//} else {
// // Second, challenge ownership of the PoP cert
// // 1. Encrypt a nonce with the owner's public key
// QString ownerKey(jsonObject["owner_public_key"].toString());
// QString encryptedText("");
if (!jsonObject["invalid_reason"].toString().isEmpty()) {
qCDebug(entities) << "invalid_reason not empty, deleting entity" << entityItemID;
deleteEntity(entityItemID, true);
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
} else if (jsonObject["transfer_status"].toString() == "failed") {
qCDebug(entities) << "'transfer_status' is 'failed', deleting entity" << entityItemID;
deleteEntity(entityItemID, true);
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
} else {
// Second, challenge ownership of the PoP cert
// 1. Encrypt a nonce with the owner's public key
QString ownerKey(jsonObject["owner_public_key"].toString());
QString encryptedText("test");
// // 2. Send the encrypted text to the rezzing avatar's node
// auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership, NUM_BYTES_RFC4122_UUID + sizeof(encryptedText));
// challengeOwnershipPacket->write(senderNode->getUUID());
// challengeOwnershipPacket->writePrimitive(encryptedText);
// // 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time
//}
// 2. Send the encrypted text to the rezzing avatar's node
QByteArray certIDByteArray = certID.toUtf8();
int certIDByteArraySize = certIDByteArray.size();
QByteArray encryptedTextByteArray = encryptedText.toUtf8();
int encryptedTextByteArraySize = encryptedTextByteArray.size();
QByteArray ownerKeyByteArray = ownerKey.toUtf8();
int ownerKeyByteArraySize = ownerKeyByteArray.size();
auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership,
certIDByteArraySize + encryptedTextByteArraySize + ownerKeyByteArraySize + 3*sizeof(int),
true);
challengeOwnershipPacket->writePrimitive(certIDByteArraySize);
challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize);
challengeOwnershipPacket->writePrimitive(ownerKeyByteArraySize);
challengeOwnershipPacket->write(certIDByteArray);
challengeOwnershipPacket->write(encryptedTextByteArray);
challengeOwnershipPacket->write(ownerKeyByteArray);
nodeList->sendPacket(std::move(challengeOwnershipPacket), *senderNode);
// 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time
QTimer* challengeOwnershipTimeoutTimer = new QTimer(this);
connect(this, &EntityTree::killChallengeOwnershipTimeoutTimer, this, [&](const QString& certID) {
QReadLocker locker(&_entityCertificateIDMapLock);
EntityItemID id = _entityCertificateIDMap.value(certID);
if (entityItemID == id) {
challengeOwnershipTimeoutTimer->stop();
challengeOwnershipTimeoutTimer->deleteLater();
}
});
connect(challengeOwnershipTimeoutTimer, &QTimer::timeout, this, [=]() {
qCDebug(entities) << "Ownership challenge timed out, deleting entity" << entityItemID;
deleteEntity(entityItemID, true);
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
});
challengeOwnershipTimeoutTimer->setSingleShot(false);
challengeOwnershipTimeoutTimer->setInterval(10000);
challengeOwnershipTimeoutTimer->start();
}
} else {
qCDebug(entities) << "Call to proof_of_purchase_status endpoint failed; deleting entity" << entityItemID;
deleteEntity(entityItemID, true);
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
}
networkReply->deleteLater();

View file

@ -100,6 +100,7 @@ public:
void fixupTerseEditLogging(EntityItemProperties& properties, QList<QString>& changedProperties);
virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
const SharedNodePointer& senderNode) override;
virtual void processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) override;
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
QVector<EntityItemID> entityIdsToInclude, QVector<EntityItemID> entityIdsToDiscard,
@ -281,6 +282,7 @@ signals:
void entityServerScriptChanging(const EntityItemID& entityItemID, const bool reload);
void newCollisionSoundURL(const QUrl& url, const EntityItemID& entityID);
void clearingEntities();
void killChallengeOwnershipTimeoutTimer(const QString& certID);
protected:

View file

@ -214,6 +214,7 @@ public:
virtual bool handlesEditPacketType(PacketType packetType) const { return false; }
virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
const SharedNodePointer& sourceNode) { return 0; }
virtual void processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { return; }
virtual bool recurseChildrenWithData() const { return true; }
virtual bool rootElementHasData() const { return false; }