From 27c779666b954dc96b91112e2ae23aefd6136e90 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Feb 2014 13:29:32 -0800 Subject: [PATCH] add auth to assignment-client, fix refresh of static assignments --- assignment-client/src/AssignmentClient.cpp | 31 ++++++++++ assignment-client/src/AssignmentClient.h | 1 + domain-server/src/DomainServer.cpp | 68 ++++++++++++---------- domain-server/src/DomainServerNodeData.cpp | 16 +++++ domain-server/src/DomainServerNodeData.h | 7 ++- libraries/shared/src/AccountManager.h | 1 + libraries/shared/src/DomainInfo.cpp | 2 +- libraries/shared/src/DomainInfo.h | 4 +- 8 files changed, 96 insertions(+), 34 deletions(-) create mode 100644 domain-server/src/DomainServerNodeData.cpp diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 73d3d2c90d..4671989ade 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -6,9 +6,11 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // +#include #include #include +#include #include #include #include @@ -91,6 +93,10 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // connect our readPendingDatagrams method to the readyRead() signal of the socket connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); + + // connections to AccountManager for authentication + connect(&AccountManager::getInstance(), &AccountManager::authRequired, + this, &AssignmentClient::handleAuthenticationRequest); } void AssignmentClient::sendAssignmentRequest() { @@ -158,6 +164,30 @@ void AssignmentClient::readPendingDatagrams() { } } +void AssignmentClient::handleAuthenticationRequest() { + const QString DATA_SERVER_USERNAME_ENV = "HIFI_AC_USERNAME"; + const QString DATA_SERVER_PASSWORD_ENV = "HIFI_AC_PASSWORD"; + + // this node will be using an authentication server, let's make sure we have a username/password + QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment(); + + QString username = sysEnvironment.value(DATA_SERVER_USERNAME_ENV); + QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV); + + AccountManager& accountManager = AccountManager::getInstance(); + + if (!username.isEmpty() && !password.isEmpty()) { + // ask the account manager to log us in from the env variables + accountManager.requestAccessToken(username, password); + } else { + qDebug() << "Authentication was requested against" << qPrintable(accountManager.getRootURL().toString()) + << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) + << "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate."; + + return; + } +} + void AssignmentClient::assignmentCompleted() { // reset the logging target to the the CHILD_TARGET_NAME Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); @@ -175,5 +205,6 @@ void AssignmentClient::assignmentCompleted() { // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NodeType::Unassigned); nodeList->reset(); + nodeList->getDomainInfo().reset(); nodeList->resetNodeInterestSet(); } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index f19c8015b3..29187fa3d6 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,6 +21,7 @@ private slots: void sendAssignmentRequest(); void readPendingDatagrams(); void assignmentCompleted(); + void handleAuthenticationRequest(); private: Assignment _requestAssignment; ThreadedAssignment* _currentAssignment; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9276c6cd1f..f4b920fad1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -55,23 +55,24 @@ DomainServer::DomainServer(int argc, char* argv[]) : } if (!_nodeAuthenticationURL.isEmpty()) { - // this domain-server will be using an authentication server, let's make sure we have a username/password - QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment(); - const QString DATA_SERVER_USERNAME_ENV = "HIFI_DS_USERNAME"; const QString DATA_SERVER_PASSWORD_ENV = "HIFI_DS_PASSWORD"; + + // this node will be using an authentication server, let's make sure we have a username/password + QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment(); + QString username = sysEnvironment.value(DATA_SERVER_USERNAME_ENV); QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV); + AccountManager& accountManager = AccountManager::getInstance(); + accountManager.setRootURL(_nodeAuthenticationURL); + if (!username.isEmpty() && !password.isEmpty()) { - AccountManager& accountManager = AccountManager::getInstance(); - accountManager.setRootURL(_nodeAuthenticationURL); - - // TODO: failure case for not receiving a token - accountManager.requestAccessToken(username, password); connect(&accountManager, &AccountManager::loginComplete, this, &DomainServer::requestCreationFromDataServer); + // ask the account manager to log us in from the env variables + accountManager.requestAccessToken(username, password); } else { qDebug() << "Authentication was requested against" << qPrintable(_nodeAuthenticationURL.toString()) << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) @@ -82,6 +83,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : return; } + } else { // auth is not requested for domain-server, setup NodeList and assignments now setupNodeListAndAssignments(); @@ -326,27 +328,28 @@ void DomainServer::addNodeToNodeListAndConfirmConnection(const QByteArray& packe int numPreInterestBytes = parseNodeDataFromByteArray(nodeType, publicSockAddr, localSockAddr, packet, senderSockAddr); - QUuid nodeUUID = uuidFromPacketHeader(packet); + QUuid assignmentUUID = uuidFromPacketHeader(packet); SharedAssignmentPointer matchingAssignment; - if (!nodeUUID.isNull() && (matchingAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType))) { + if (!assignmentUUID.isNull() && (matchingAssignment = matchingStaticAssignmentForCheckIn(assignmentUUID, nodeType)) + && matchingAssignment) { // this is an assigned node, make sure the UUID sent is for an assignment we're actually trying to give out - nodeUUID = uuidFromPacketHeader(packet); - if (matchingAssignment) { - // this was a newly added node with a matching assignment - - // remove the matching assignment from the assignment queue so we don't take the next check in - // (if it exists) - removeMatchingAssignmentFromQueue(matchingAssignment); - } + // remove the matching assignment from the assignment queue so we don't take the next check in + // (if it exists) + removeMatchingAssignmentFromQueue(matchingAssignment); + } else { + assignmentUUID = QUuid(); } // create a new session UUID for this node - nodeUUID = QUuid::createUuid(); + QUuid nodeUUID = QUuid::createUuid(); SharedNodePointer newNode = NodeList::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); + if (!authJsonObject.isEmpty()) { // pull the connection secret from the authJsonObject and set it as the connection secret for this node QUuid connectionSecret(authJsonObject["data"].toObject()["connection_secret"].toString()); @@ -779,19 +782,24 @@ void DomainServer::nodeAdded(SharedNodePointer node) { } void DomainServer::nodeKilled(SharedNodePointer node) { - // if this node's UUID matches a static assignment we need to throw it back in the assignment queue - SharedAssignmentPointer matchedAssignment = _staticAssignmentHash.value(node->getUUID()); - if (matchedAssignment) { - refreshStaticAssignmentAndAddToQueue(matchedAssignment); - } - - // cleanup the connection secrets that we set up for this node (on the other nodes) DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); - foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) { - SharedNodePointer otherNode = NodeList::getInstance()->nodeWithUUID(otherNodeSessionUUID); - if (otherNode) { - reinterpret_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); + if (nodeData) { + // if this node's UUID matches a static assignment we need to throw it back in the assignment queue + if (!nodeData->getStaticAssignmentUUID().isNull()) { + SharedAssignmentPointer matchedAssignment = _staticAssignmentHash.value(nodeData->getStaticAssignmentUUID()); + + if (matchedAssignment) { + refreshStaticAssignmentAndAddToQueue(matchedAssignment); + } + } + + // cleanup the connection secrets that we set up for this node (on the other nodes) + foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) { + SharedNodePointer otherNode = NodeList::getInstance()->nodeWithUUID(otherNodeSessionUUID); + if (otherNode) { + reinterpret_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); + } } } } diff --git a/domain-server/src/DomainServerNodeData.cpp b/domain-server/src/DomainServerNodeData.cpp new file mode 100644 index 0000000000..2e32903712 --- /dev/null +++ b/domain-server/src/DomainServerNodeData.cpp @@ -0,0 +1,16 @@ +// +// DomainServerNodeData.cpp +// hifi +// +// Created by Stephen Birarda on 2/6/2014. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#include "DomainServerNodeData.h" + +DomainServerNodeData::DomainServerNodeData() : + _sessionSecretHash(), + _staticAssignmentUUID() +{ + +} \ No newline at end of file diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h index ea56e31f1c..6686b9120f 100644 --- a/domain-server/src/DomainServerNodeData.h +++ b/domain-server/src/DomainServerNodeData.h @@ -10,17 +10,22 @@ #define __hifi__DomainServerNodeData__ #include +#include #include class DomainServerNodeData : public NodeData { public: - DomainServerNodeData() : _sessionSecretHash() {}; + DomainServerNodeData(); int parseData(const QByteArray& packet) { return 0; } + void setStaticAssignmentUUID(const QUuid& staticAssignmentUUID) { _staticAssignmentUUID = staticAssignmentUUID; } + const QUuid& getStaticAssignmentUUID() const { return _staticAssignmentUUID; } + QHash& getSessionSecretHash() { return _sessionSecretHash; } private: QHash _sessionSecretHash; + QUuid _staticAssignmentUUID; }; #endif /* defined(__hifi__DomainServerNodeData__) */ diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index 6bdb4f92e2..0018a6bba0 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -41,6 +41,7 @@ public: const JSONCallbackParameters& callbackParams = JSONCallbackParameters(), const QByteArray& dataByteArray = QByteArray()); + const QUrl& getRootURL() const { return _rootURL; } void setRootURL(const QUrl& rootURL); bool hasAuthEndpoint() { return !_rootURL.isEmpty(); } diff --git a/libraries/shared/src/DomainInfo.cpp b/libraries/shared/src/DomainInfo.cpp index 258254be94..fff3cc1ed6 100644 --- a/libraries/shared/src/DomainInfo.cpp +++ b/libraries/shared/src/DomainInfo.cpp @@ -31,7 +31,7 @@ void DomainInfo::reset() { _hostname = QString(); _sockAddr.setAddress(QHostAddress::Null); _assignmentUUID = QUuid(); - _connectionSecret = QString(); + _connectionSecret = QUuid(); _registrationToken = QByteArray(); _rootAuthenticationURL = QUrl(); _publicKey = QString(); diff --git a/libraries/shared/src/DomainInfo.h b/libraries/shared/src/DomainInfo.h index 0c5344a0c5..5dc04d58c7 100644 --- a/libraries/shared/src/DomainInfo.h +++ b/libraries/shared/src/DomainInfo.h @@ -24,6 +24,8 @@ class DomainInfo : public QObject { public: DomainInfo(); + void reset(); + void parseAuthInformationFromJsonObject(const QJsonObject& jsonObject); const QUuid& getUUID() const { return _uuid; } @@ -62,8 +64,6 @@ signals: void hostnameChanged(const QString& hostname); void connectedToDomain(const QString& hostname); private: - void reset(); - QUuid _uuid; QString _hostname; HifiSockAddr _sockAddr;