From 244cc016ab1b7c19ac8b49bdf87cbc9cbc9da634 Mon Sep 17 00:00:00 2001 From: bwent Date: Thu, 30 Jul 2015 15:22:17 -0700 Subject: [PATCH 01/12] Generate session token UUIDs to be signed with username --- domain-server/src/DomainServer.cpp | 50 +++++++++++++++---- domain-server/src/DomainServer.h | 6 ++- .../networking/src/DataServerAccountInfo.cpp | 29 ++++++----- .../networking/src/DataServerAccountInfo.h | 2 +- libraries/networking/src/DomainHandler.cpp | 2 + libraries/networking/src/DomainHandler.h | 6 ++- libraries/networking/src/NodeList.cpp | 37 ++++++++++---- libraries/networking/src/NodeList.h | 2 + .../networking/src/udt/PacketHeaders.cpp | 3 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- 10 files changed, 102 insertions(+), 38 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c13de0449e..d9bd18580c 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -285,6 +285,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { packetReceiver.registerListener(PacketType::DomainConnectRequest, this, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::DomainListRequest, this, "processListRequestPacket"); packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket"); + packetReceiver.registerListener(PacketType::DomainServerConnectionToken, this, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket"); packetReceiver.registerListener(PacketType::ICEPing, this, "processICEPingPacket"); packetReceiver.registerListener(PacketType::ICEPingReply, this, "processICEPingReplyPacket"); @@ -579,7 +580,6 @@ const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer void DomainServer::processConnectRequestPacket(QSharedPointer packet) { NodeType_t nodeType; HifiSockAddr publicSockAddr, localSockAddr; - if (packet->getPayloadSize() == 0) { return; @@ -625,15 +625,35 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) return; } } - } QList nodeInterestList; QString username; QByteArray usernameSignature; - packetStream >> nodeInterestList >> username >> usernameSignature; - + packetStream >> nodeInterestList; + + if (packet->bytesLeftToRead() > 0) { + // try to verify username and usernameSignature + packetStream >> username >> usernameSignature; + } else { + + QUuid& connectionToken = _connectionTokenHash[username]; + + if(connectionToken.isNull()) { + // set up the connection token packet + static auto connectionTokenPacket = NLPacket::create(PacketType::DomainServerConnectionToken, NUM_BYTES_RFC4122_UUID); + connectionToken->write(connectionToken.toRfc4122()); + nodeList->sendUnreliablePacket(connectionTokenPacket, packet->getSenderSockAddr()); + + return; + } else { + // reset existing packet + connectionToken->reset(); + } + + } + auto limitedNodeList = DependencyManager::get(); QString reason; @@ -736,6 +756,7 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) } } + void DomainServer::processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { NodeType_t throwawayNodeType; @@ -754,6 +775,7 @@ void DomainServer::processListRequestPacket(QSharedPointer packet, Sha sendDomainListToNode(sendingNode, packet->getSenderSockAddr(), nodeInterestList.toSet()); } + unsigned int DomainServer::countConnectedUsers() { unsigned int result = 0; auto nodeList = DependencyManager::get(); @@ -766,11 +788,12 @@ unsigned int DomainServer::countConnectedUsers() { } -bool DomainServer::verifyUsersKey(const QString& username, +bool DomainServer::verifyUserSignature(const QString& username, const QByteArray& usernameSignature, QString& reasonReturn) { // it's possible this user can be allowed to connect, but we need to check their username signature - + + QByteArray publicKeyArray = _userPublicKeys.value(username); if (!publicKeyArray.isEmpty()) { // if we do have a public key for the user, check for a signature match @@ -787,13 +810,20 @@ bool DomainServer::verifyUsersKey(const QString& username, reinterpret_cast(usernameSignature.constData()), reinterpret_cast(decryptedArray.data()), rsaPublicKey, RSA_PKCS1_PADDING); - + + QByteArray lowercaseUsername = username.toLower().toUtf8(); + QUuid connectionToken = _connectionTokenHash[username]; + QByteArray usernameWithToken = lowercaseUsername.append(connectionToken); + if (decryptResult != -1) { - if (username.toLower() == decryptedArray) { + if (usernameWithToken == decryptedArray) { qDebug() << "Username signature matches for" << username << "- allowing connection."; // free up the public key before we return RSA_free(rsaPublicKey); + + // remove the username's connection token from the hash + _connectionTokenHash.remove(username); return true; } else { @@ -839,7 +869,7 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); if (allowedUsers.contains(username, Qt::CaseInsensitive)) { - if (!verifyUsersKey(username, usernameSignature, reasonReturn)) { + if (!verifyUserSignature(username, usernameSignature, reasonReturn)) { return false; } } else { @@ -857,7 +887,7 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); if (allowedEditors.contains(username)) { - if (verifyUsersKey(username, usernameSignature, reasonReturn)) { + if (verifyUserSignature(username, usernameSignature, reasonReturn)) { return true; } } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 7786fb34ac..fe79ec4889 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -57,7 +57,7 @@ public slots: void processRequestAssignmentPacket(QSharedPointer packet); void processConnectRequestPacket(QSharedPointer packet); - void processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); + void processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode);; void processNodeJSONStatsPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processPathQueryPacket(QSharedPointer packet); void processICEPingPacket(QSharedPointer packet); @@ -90,7 +90,7 @@ private: void pingPunchForConnectingPeer(const SharedNetworkPeer& peer); 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, const HifiSockAddr& senderSockAddr, QString& reasonReturn); @@ -149,6 +149,8 @@ private: QSet _webAuthenticationStateSet; QHash _cookieSessionHash; + + QHash _connectionTokenHash; QHash _userPublicKeys; diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index a85aa588a8..bdef718ff4 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -128,8 +128,7 @@ void DataServerAccountInfo::setProfileInfoFromJSON(const QJsonObject& jsonObject setWalletID(QUuid(user["wallet_id"].toString())); } -const QByteArray& DataServerAccountInfo::getUsernameSignature() { - if (_usernameSignature.isEmpty()) { +QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionToken) { if (!_privateKey.isEmpty()) { const char* privateKeyData = _privateKey.constData(); RSA* rsaPrivateKey = d2i_RSAPrivateKey(NULL, @@ -137,29 +136,33 @@ const QByteArray& DataServerAccountInfo::getUsernameSignature() { _privateKey.size()); if (rsaPrivateKey) { QByteArray lowercaseUsername = _username.toLower().toUtf8(); - _usernameSignature.resize(RSA_size(rsaPrivateKey)); + QByteArray usernameWithToken = lowercaseUsername.append(connectionToken.toRfc4122()); + + QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); int encryptReturn = RSA_private_encrypt(lowercaseUsername.size(), - reinterpret_cast(lowercaseUsername.constData()), - reinterpret_cast(_usernameSignature.data()), + reinterpret_cast(usernameWithToken.constData()), + reinterpret_cast(usernameSignature.data()), rsaPrivateKey, RSA_PKCS1_PADDING); - if (encryptReturn == -1) { - qCDebug(networking) << "Error encrypting username signature."; - qCDebug(networking) << "Will re-attempt on next domain-server check in."; - _usernameSignature = QByteArray(); - } + // 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 { + return usernameSignature; + } + } else { qCDebug(networking) << "Could not create RSA struct from QByteArray private key."; qCDebug(networking) << "Will re-attempt on next domain-server check in."; } } - } - - return _usernameSignature; + return QByteArray(); } void DataServerAccountInfo::setPrivateKey(const QByteArray& privateKey) { diff --git a/libraries/networking/src/DataServerAccountInfo.h b/libraries/networking/src/DataServerAccountInfo.h index d7f9d5167a..0d8157ccf3 100644 --- a/libraries/networking/src/DataServerAccountInfo.h +++ b/libraries/networking/src/DataServerAccountInfo.h @@ -43,7 +43,7 @@ public: const QUuid& getWalletID() const { return _walletID; } void setWalletID(const QUuid& walletID); - const QByteArray& getUsernameSignature(); + QByteArray getUsernameSignature(const QUuid& connectionToken); bool hasPrivateKey() const { return !_privateKey.isEmpty(); } void setPrivateKey(const QByteArray& privateKey); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index afb362053e..cd53d2608e 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -29,6 +29,7 @@ DomainHandler::DomainHandler(QObject* parent) : _uuid(), _sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), _assignmentUUID(), + _connectionToken(), _iceDomainID(), _iceClientID(), _iceServerSockAddr(), @@ -61,6 +62,7 @@ void DomainHandler::clearSettings() { void DomainHandler::softReset() { qCDebug(networking) << "Resetting current domain connection information."; + _connectionToken = QUuid(); clearConnectionInfo(); clearSettings(); } diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 6079035f8b..7bb0582914 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -50,9 +50,12 @@ public: unsigned short getPort() const { return _sockAddr.getPort(); } 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; } void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } - + const QUuid& getICEDomainID() const { return _iceDomainID; } const QUuid& getICEClientID() const { return _iceClientID; } @@ -114,6 +117,7 @@ private: QString _hostname; HifiSockAddr _sockAddr; QUuid _assignmentUUID; + QUuid _connectionToken; QUuid _iceDomainID; QUuid _iceClientID; HifiSockAddr _iceServerSockAddr; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index dfa3ef86a5..6d62a7bbdc 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -94,7 +94,7 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned packetReceiver.registerListener(PacketType::PingReply, this, "processPingReplyPacket"); packetReceiver.registerListener(PacketType::ICEPing, this, "processICEPingPacket"); packetReceiver.registerListener(PacketType::DomainServerAddedNode, this, "processDomainServerAddedNode"); - + packetReceiver.registerListener(PacketType::DomainServerConnectionToken, this, "processDomainServerConnectionTokenPacket"); packetReceiver.registerListener(PacketType::ICEServerPeerInformation, &_domainHandler, "processICEResponsePacket"); packetReceiver.registerListener(PacketType::DomainServerRequireDTLS, &_domainHandler, "processDTLSRequirementPacket"); packetReceiver.registerListener(PacketType::ICEPingReply, &_domainHandler, "processICEPingReplyPacket"); @@ -274,17 +274,22 @@ void NodeList::sendDomainServerCheckIn() { // pack our data to send to the domain-server packetStream << _ownerType << _publicSockAddr << _localSockAddr << _nodeTypesOfInterest.toList(); - + // 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(); packetStream << accountInfo.getUsername(); - - const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(); - - if (!usernameSignature.isEmpty()) { - qCDebug(networking) << "Including username signature in domain connect request."; - packetStream << usernameSignature; + + // get connection token from the domain-server + const QUuid& connectionToken = _domainHandler.getConnectionToken(); + + if(!connectionToken.isNull()) { + const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); + + if (!usernameSignature.isEmpty()) { + qCDebug(networking) << "Including username signature in domain connect request."; + packetStream << usernameSignature; + } } } @@ -361,6 +366,7 @@ void NodeList::sendDSPathQuery(const QString& newPath) { } } + void NodeList::processDomainServerPathResponse(QSharedPointer packet) { // 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. @@ -450,6 +456,19 @@ void NodeList::pingPunchForDomainServer() { } } + +void NodeList::processDomainServerConnectionToken(QSharedPointer 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 packet) { if (_domainHandler.getSockAddr().isNull()) { // refuse to process this packet if we aren't currently connected to the DS diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index e3f8feeeda..b05e19d349 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -76,6 +76,8 @@ public slots: void processDomainServerAddedNode(QSharedPointer packet); void processDomainServerPathResponse(QSharedPointer packet); + void processDomainServerConnectionToken(QSharedPointer packet); + void processPingPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processPingReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 0591ac30fe..90b4d57e05 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -27,7 +27,7 @@ const QSet SEQUENCE_NUMBERED_PACKETS = QSet NON_SOURCED_PACKETS = QSet() << StunResponse << CreateAssignment << RequestAssignment << DomainServerRequireDTLS << DomainConnectRequest - << DomainList << DomainConnectionDenied + << DomainList << DomainConnectionDenied << DomainServerConnectionToken << DomainServerPathQuery << DomainServerPathResponse << DomainServerAddedNode << ICEServerPeerInformation << ICEServerQuery << ICEServerHeartbeat @@ -119,6 +119,7 @@ QString nameForPacketType(PacketType::Value packetType) { PACKET_TYPE_NAME_LOOKUP(ICEPingReply); PACKET_TYPE_NAME_LOOKUP(EntityAdd); PACKET_TYPE_NAME_LOOKUP(EntityEdit); + PACKET_TYPE_NAME_LOOKUP(DomainServerConnectionToken); default: return QString("Type: ") + QString::number((int)packetType); } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 3f3f165e87..46f834db74 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -73,7 +73,8 @@ namespace PacketType { EntityQuery, EntityAdd, EntityErase, - EntityEdit + EntityEdit, + DomainServerConnectionToken }; }; From af293ec6ddced85a1fa378092fd76f441c55fa22 Mon Sep 17 00:00:00 2001 From: bwent Date: Fri, 31 Jul 2015 09:33:46 -0700 Subject: [PATCH 02/12] Fix DomainServerConnectionTOken packet writing/resetting --- domain-server/src/DomainServer.cpp | 19 ++++++++++--------- libraries/networking/src/NodeList.cpp | 2 +- libraries/networking/src/NodeList.h | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index d9bd18580c..b9f7a293b3 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -630,7 +630,9 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) QList nodeInterestList; QString username; QByteArray usernameSignature; - + + auto limitedNodeList = DependencyManager::get(); + packetStream >> nodeInterestList; if (packet->bytesLeftToRead() > 0) { @@ -638,24 +640,23 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) packetStream >> username >> usernameSignature; } else { - QUuid& connectionToken = _connectionTokenHash[username]; + QUuid connectionToken = _connectionTokenHash[username]; if(connectionToken.isNull()) { // set up the connection token packet static auto connectionTokenPacket = NLPacket::create(PacketType::DomainServerConnectionToken, NUM_BYTES_RFC4122_UUID); - connectionToken->write(connectionToken.toRfc4122()); - nodeList->sendUnreliablePacket(connectionTokenPacket, packet->getSenderSockAddr()); - + connectionTokenPacket.reset(); + connectionTokenPacket->write(connectionToken.toRfc4122()); + nodeList->sendUnreliablePacket(connectionToken, packet->getSenderSockAddr()); return; } else { // reset existing packet - connectionToken->reset(); + + //connectionTokenPacket.reset(); } } - auto limitedNodeList = DependencyManager::get(); - QString 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 @@ -813,7 +814,7 @@ bool DomainServer::verifyUserSignature(const QString& username, QByteArray lowercaseUsername = username.toLower().toUtf8(); QUuid connectionToken = _connectionTokenHash[username]; - QByteArray usernameWithToken = lowercaseUsername.append(connectionToken); + QByteArray usernameWithToken = lowercaseUsername.append(connectionToken.toRfc4122()); if (decryptResult != -1) { if (usernameWithToken == decryptedArray) { diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 6d62a7bbdc..1739285cba 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -457,7 +457,7 @@ void NodeList::pingPunchForDomainServer() { } -void NodeList::processDomainServerConnectionToken(QSharedPointer packet) { +void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer packet) { if (_domainHandler.getSockAddr().isNull()) { // refuse to process this packet if we aren't currently connected to the DS return; diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index b05e19d349..3aae3e3dfc 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -76,7 +76,7 @@ public slots: void processDomainServerAddedNode(QSharedPointer packet); void processDomainServerPathResponse(QSharedPointer packet); - void processDomainServerConnectionToken(QSharedPointer packet); + void processDomainServerConnectionTokenPacket(QSharedPointer packet); void processPingPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processPingReplyPacket(QSharedPointer packet, SharedNodePointer sendingNode); From 54dd5da64cf0e43095873821ef7c44164e01aaec Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 3 Aug 2015 14:02:57 -0700 Subject: [PATCH 03/12] To debug RSA padding error --- domain-server/src/DomainServer.cpp | 47 ++++++++++--------- .../networking/src/DataServerAccountInfo.cpp | 8 ++-- libraries/networking/src/NodeList.cpp | 8 ++-- .../networking/src/udt/PacketHeaders.cpp | 4 +- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index b9f7a293b3..324096c997 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -285,7 +285,6 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { packetReceiver.registerListener(PacketType::DomainConnectRequest, this, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::DomainListRequest, this, "processListRequestPacket"); packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket"); - packetReceiver.registerListener(PacketType::DomainServerConnectionToken, this, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket"); packetReceiver.registerListener(PacketType::ICEPing, this, "processICEPingPacket"); packetReceiver.registerListener(PacketType::ICEPingReply, this, "processICEPingReplyPacket"); @@ -578,6 +577,7 @@ const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer; void DomainServer::processConnectRequestPacket(QSharedPointer packet) { + NodeType_t nodeType; HifiSockAddr publicSockAddr, localSockAddr; @@ -638,23 +638,22 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) if (packet->bytesLeftToRead() > 0) { // try to verify username and usernameSignature packetStream >> username >> usernameSignature; - } else { - QUuid connectionToken = _connectionTokenHash[username]; + } else { + // if user didn't include username and usernameSignature in connect request, send a connectionToken packet + QUuid& connectionToken = _connectionTokenHash[username]; if(connectionToken.isNull()) { // set up the connection token packet - static auto connectionTokenPacket = NLPacket::create(PacketType::DomainServerConnectionToken, NUM_BYTES_RFC4122_UUID); - connectionTokenPacket.reset(); - connectionTokenPacket->write(connectionToken.toRfc4122()); - nodeList->sendUnreliablePacket(connectionToken, packet->getSenderSockAddr()); - return; - } else { - // reset existing packet - - //connectionTokenPacket.reset(); + 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; @@ -793,9 +792,8 @@ bool DomainServer::verifyUserSignature(const QString& username, const QByteArray& usernameSignature, QString& reasonReturn) { // it's possible this user can be allowed to connect, but we need to check their username signature - - QByteArray publicKeyArray = _userPublicKeys.value(username); + QUuid connectionToken = _connectionTokenHash.value(username); if (!publicKeyArray.isEmpty()) { // if we do have a public key for the user, check for a signature match @@ -803,7 +801,8 @@ bool DomainServer::verifyUserSignature(const QString& username, // first load up the public key into an RSA struct RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); - + + if (rsaPublicKey) { QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); int decryptResult = @@ -813,10 +812,13 @@ bool DomainServer::verifyUserSignature(const QString& username, rsaPublicKey, RSA_PKCS1_PADDING); QByteArray lowercaseUsername = username.toLower().toUtf8(); - QUuid connectionToken = _connectionTokenHash[username]; - QByteArray usernameWithToken = lowercaseUsername.append(connectionToken.toRfc4122()); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); + + int err = ERR_get_error(); + qDebug() << "Error: " << err; if (decryptResult != -1) { + if (usernameWithToken == decryptedArray) { qDebug() << "Username signature matches for" << username << "- allowing connection."; @@ -834,10 +836,13 @@ bool DomainServer::verifyUserSignature(const QString& username, } else { qDebug() << "Couldn't decrypt user signature for" << username << "- denying connection."; reasonReturn = "Couldn't decrypt user signature."; + } // free up the public key, we don't need it anymore RSA_free(rsaPublicKey); + _connectionTokenHash.remove(username); + } else { // 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."; @@ -859,10 +864,10 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, _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 - if (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() - || senderSockAddr.getAddress() == QHostAddress::LocalHost) { - return true; - } +// if (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() +// || senderSockAddr.getAddress() == QHostAddress::LocalHost) { +// return true; +// } if (isRestrictingAccess) { diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index bdef718ff4..580a676ece 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -129,6 +129,7 @@ void DataServerAccountInfo::setProfileInfoFromJSON(const QJsonObject& jsonObject } QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionToken) { + if (!_privateKey.isEmpty()) { const char* privateKeyData = _privateKey.constData(); RSA* rsaPrivateKey = d2i_RSAPrivateKey(NULL, @@ -136,16 +137,14 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo _privateKey.size()); if (rsaPrivateKey) { QByteArray lowercaseUsername = _username.toLower().toUtf8(); - QByteArray usernameWithToken = lowercaseUsername.append(connectionToken.toRfc4122()); - + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); - int encryptReturn = RSA_private_encrypt(lowercaseUsername.size(), + int encryptReturn = RSA_private_encrypt(usernameWithToken.size(), reinterpret_cast(usernameWithToken.constData()), reinterpret_cast(usernameSignature.data()), rsaPrivateKey, RSA_PKCS1_PADDING); - // free the private key RSA struct now that we are done with it RSA_free(rsaPrivateKey); @@ -154,6 +153,7 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo qCDebug(networking) << "Error encrypting username signature."; qCDebug(networking) << "Will re-attempt on next domain-server check in."; } else { + qDebug(networking) << "Signing username with connectionUUID"; return usernameSignature; } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 1739285cba..d467fcfa13 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -277,19 +277,20 @@ void NodeList::sendDomainServerCheckIn() { // if this is a connect request, and we can present a username signature, send it along if (!_domainHandler.isConnected() ) { + DataServerAccountInfo& accountInfo = AccountManager::getInstance().getAccountInfo(); - packetStream << accountInfo.getUsername(); // get connection token from the domain-server const QUuid& connectionToken = _domainHandler.getConnectionToken(); if(!connectionToken.isNull()) { + const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); if (!usernameSignature.isEmpty()) { - qCDebug(networking) << "Including username signature in domain connect request."; - packetStream << usernameSignature; + packetStream << accountInfo.getUsername() << usernameSignature; } + } } @@ -462,7 +463,6 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer // 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(); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 90b4d57e05..f3f222f310 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -26,8 +26,8 @@ const QSet SEQUENCE_NUMBERED_PACKETS = QSet NON_SOURCED_PACKETS = QSet() << StunResponse << CreateAssignment << RequestAssignment - << DomainServerRequireDTLS << DomainConnectRequest - << DomainList << DomainConnectionDenied << DomainServerConnectionToken + << DomainServerRequireDTLS << DomainConnectRequest << DomainServerConnectionToken + << DomainList << DomainConnectionDenied << DomainServerPathQuery << DomainServerPathResponse << DomainServerAddedNode << ICEServerPeerInformation << ICEServerQuery << ICEServerHeartbeat From b9364a47a191a724dddf85d25f88e68562249a0a Mon Sep 17 00:00:00 2001 From: bwent Date: Tue, 4 Aug 2015 15:31:26 -0700 Subject: [PATCH 04/12] Debug null QUuid being stored in conenctionTokenHash --- domain-server/src/DomainServer.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 324096c997..5e877527d7 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -641,7 +641,7 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) } else { // if user didn't include username and usernameSignature in connect request, send a connectionToken packet - QUuid& connectionToken = _connectionTokenHash[username]; + QUuid& connectionToken = _connectionTokenHash[username.toLower()]; if(connectionToken.isNull()) { // set up the connection token packet @@ -652,6 +652,9 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) connectionTokenPacket->reset(); connectionTokenPacket->write(connectionToken.toRfc4122()); limitedNodeList->sendUnreliablePacket(*connectionTokenPacket, packet->getSenderSockAddr()); + + qDebug() << "Sending connection token. " << _connectionTokenHash[username.toLower()]; + return; } @@ -664,9 +667,12 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) quint16 payloadSize = utfString.size(); auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied, payloadSize + sizeof(payloadSize)); - connectionDeniedPacket->writePrimitive(payloadSize); - connectionDeniedPacket->write(utfString); + if (payloadSize > 0) { + connectionDeniedPacket->writePrimitive(payloadSize); + connectionDeniedPacket->write(utfString); + } + // tell client it has been refused. limitedNodeList->sendPacket(std::move(connectionDeniedPacket), senderSockAddr); @@ -791,10 +797,14 @@ unsigned int DomainServer::countConnectedUsers() { bool DomainServer::verifyUserSignature(const QString& username, const QByteArray& usernameSignature, QString& reasonReturn) { + // it's possible this user can be allowed to connect, but we need to check their username signature QByteArray publicKeyArray = _userPublicKeys.value(username); - QUuid connectionToken = _connectionTokenHash.value(username); - if (!publicKeyArray.isEmpty()) { + + QUuid connectionToken = _connectionTokenHash.value(username.toLower()); + qDebug() << "Pulling out connection token. " << connectionToken; + + if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) { // if we do have a public key for the user, check for a signature match const unsigned char* publicKeyData = reinterpret_cast(publicKeyArray.constData()); @@ -802,7 +812,6 @@ bool DomainServer::verifyUserSignature(const QString& username, // first load up the public key into an RSA struct RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); - if (rsaPublicKey) { QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); int decryptResult = @@ -841,13 +850,16 @@ bool DomainServer::verifyUserSignature(const QString& username, // free up the public key, we don't need it anymore RSA_free(rsaPublicKey); - _connectionTokenHash.remove(username); } else { + // 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."; 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? From fc385d9bc10474d56e20dfb155ad19700d6e9cae Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 5 Aug 2015 10:29:30 -0700 Subject: [PATCH 05/12] debugging --- domain-server/src/DomainServer.cpp | 93 +++++++++++-------- .../networking/src/DataServerAccountInfo.cpp | 3 +- libraries/networking/src/NodeList.cpp | 4 +- 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 5e877527d7..c164c9bc00 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -636,33 +636,51 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) packetStream >> nodeInterestList; if (packet->bytesLeftToRead() > 0) { - // try to verify username and usernameSignature - packetStream >> username >> usernameSignature; - - } else { - // if user didn't include username and usernameSignature in connect request, send a connectionToken packet - QUuid& connectionToken = _connectionTokenHash[username.toLower()]; - - if(connectionToken.isNull()) { - // set up the connection token packet - 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()); - - qDebug() << "Sending connection token. " << _connectionTokenHash[username.toLower()]; - - return; + // 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()->getLocalSockAddr().getAddress() +// || senderSockAddr.getAddress() == QHostAddress::LocalHost); + + // if username is empty, don't attempt to unpack username signature + if(isRestrictingAccess) { + if (!username.isEmpty()) { + qDebug() << "Reading username signature."; + packetStream >> usernameSignature; + + if(usernameSignature.isEmpty()) { + // if user didn't include username and 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()); + + qDebug() << "Sending connection token. " << _connectionTokenHash[username.toLower()]; + + return; + + } + + } + + } + QString 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 - + QByteArray utfString = reason.toUtf8(); quint16 payloadSize = utfString.size(); @@ -812,6 +830,8 @@ bool DomainServer::verifyUserSignature(const QString& username, // first load up the public key into an RSA struct RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); + qDebug() << "Signature: " << usernameSignature.toHex(); + if (rsaPublicKey) { QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); int decryptResult = @@ -827,7 +847,6 @@ bool DomainServer::verifyUserSignature(const QString& username, qDebug() << "Error: " << err; if (decryptResult != -1) { - if (usernameWithToken == decryptedArray) { qDebug() << "Username signature matches for" << username << "- allowing connection."; @@ -871,38 +890,34 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr, QString& reasonReturn) { - 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 -// if (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() -// || senderSockAddr.getAddress() == QHostAddress::LocalHost) { -// return true; -// } - - if (isRestrictingAccess) { + _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + if(isRestrictingAccess) { QStringList allowedUsers = - _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); - + _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); + if (allowedUsers.contains(username, Qt::CaseInsensitive)) { + if(username.isEmpty()) { + qDebug() << "Connect request denied - no username provided."; + reasonReturn = "No username provided"; + return false; + } if (!verifyUserSignature(username, usernameSignature, reasonReturn)) { return false; } } else { qDebug() << "Connect request denied for user" << username << "not in allowed users list."; reasonReturn = "User not on whitelist."; - + return false; } } - + // 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 const QVariant* allowedEditorsVariant = - valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); + valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); if (allowedEditors.contains(username)) { if (verifyUserSignature(username, usernameSignature, reasonReturn)) { diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index 580a676ece..de647d09c4 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -153,7 +153,8 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo qCDebug(networking) << "Error encrypting username signature."; qCDebug(networking) << "Will re-attempt on next domain-server check in."; } else { - qDebug(networking) << "Signing username with connectionUUID"; + qDebug(networking) << "Signing username with connectionUUID " << connectionToken; + qDebug() << "Signature: " << usernameSignature.toHex(); return usernameSignature; } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index d467fcfa13..9cc4eba83b 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -279,6 +279,7 @@ void NodeList::sendDomainServerCheckIn() { if (!_domainHandler.isConnected() ) { DataServerAccountInfo& accountInfo = AccountManager::getInstance().getAccountInfo(); + packetStream << accountInfo.getUsername(); // get connection token from the domain-server const QUuid& connectionToken = _domainHandler.getConnectionToken(); @@ -287,8 +288,9 @@ void NodeList::sendDomainServerCheckIn() { const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); + if (!usernameSignature.isEmpty()) { - packetStream << accountInfo.getUsername() << usernameSignature; + packetStream << usernameSignature; } } From 60fdc390c56d1980e10f86b9cd9f5a31d5f45fb4 Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 5 Aug 2015 10:42:10 -0700 Subject: [PATCH 06/12] fix username signature not const --- libraries/networking/src/NodeList.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 9cc4eba83b..13224ca5bc 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -282,17 +282,15 @@ void NodeList::sendDomainServerCheckIn() { packetStream << accountInfo.getUsername(); // get connection token from the domain-server - const QUuid& connectionToken = _domainHandler.getConnectionToken(); + QUuid connectionToken = _domainHandler.getConnectionToken(); if(!connectionToken.isNull()) { - const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); - + QByteArray usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); if (!usernameSignature.isEmpty()) { packetStream << usernameSignature; } - } } From 8868148c94a363b736f897485a01b76d4a01aab8 Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 5 Aug 2015 14:07:25 -0700 Subject: [PATCH 07/12] Parital fix for padding error using RSA_sign and RSA_verify --- domain-server/src/DomainServer.cpp | 52 +++++++------------ .../networking/src/DataServerAccountInfo.cpp | 19 ++----- .../networking/src/DataServerAccountInfo.h | 2 +- libraries/networking/src/NodeList.cpp | 2 + 4 files changed, 28 insertions(+), 47 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c164c9bc00..706307dd70 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -651,14 +651,14 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) // if username is empty, don't attempt to unpack username signature if(isRestrictingAccess) { if (!username.isEmpty()) { - qDebug() << "Reading username signature."; + packetStream >> usernameSignature; if(usernameSignature.isEmpty()) { // if user didn't include username and usernameSignature in connect request, send a connectionToken packet QUuid& connectionToken = _connectionTokenHash[username.toLower()]; - if(connectionToken.isNull()) { + if (connectionToken.isNull()) { connectionToken = QUuid::createUuid(); } @@ -667,14 +667,12 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) connectionTokenPacket->write(connectionToken.toRfc4122()); limitedNodeList->sendUnreliablePacket(*connectionTokenPacket, packet->getSenderSockAddr()); - qDebug() << "Sending connection token. " << _connectionTokenHash[username.toLower()]; + qDebug() << "Sending connectionToken packet with connectionUUID " << _connectionTokenHash[username.toLower()]; return; } - } - } QString reason; @@ -820,7 +818,6 @@ bool DomainServer::verifyUserSignature(const QString& username, QByteArray publicKeyArray = _userPublicKeys.value(username); QUuid connectionToken = _connectionTokenHash.value(username.toLower()); - qDebug() << "Pulling out connection token. " << connectionToken; if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) { // if we do have a public key for the user, check for a signature match @@ -830,46 +827,37 @@ bool DomainServer::verifyUserSignature(const QString& username, // first load up the public key into an RSA struct RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); - qDebug() << "Signature: " << usernameSignature.toHex(); + //qDebug() << "Verifying signature: " << usernameSignature.toHex(); + + QByteArray lowercaseUsername = username.toLower().toUtf8(); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); if (rsaPublicKey) { QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); int decryptResult = - RSA_public_decrypt(usernameSignature.size(), - reinterpret_cast(usernameSignature.constData()), - reinterpret_cast(decryptedArray.data()), - rsaPublicKey, RSA_PKCS1_PADDING); + RSA_verify(NID_sha256, reinterpret_cast(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast(usernameSignature.constData()), usernameSignature.size(), rsaPublicKey); - QByteArray lowercaseUsername = username.toLower().toUtf8(); - QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); int err = ERR_get_error(); - qDebug() << "Error: " << err; + qDebug() << "Decrypt result: " << decryptResult << " Error: " << err; - if (decryptResult != -1) { - if (usernameWithToken == decryptedArray) { - qDebug() << "Username signature matches for" << username << "- allowing connection."; + if (decryptResult == 1) { + qDebug() << "Username signature matches for" << username << "- allowing connection."; - // free up the public key before we return - RSA_free(rsaPublicKey); + // free up the public key before we return + RSA_free(rsaPublicKey); - // remove the username's connection token from the hash - _connectionTokenHash.remove(username); + // remove the username's connection token from the hash + _connectionTokenHash.remove(username); - return true; - } else { - qDebug() << "Username signature did not match for" << username << "- denying connection."; - reasonReturn = "Username signature did not match."; - } + return true; } else { - qDebug() << "Couldn't decrypt user signature for" << username << "- denying connection."; - reasonReturn = "Couldn't decrypt user signature."; - + qDebug() << "Error decrypting username signature for " << username << "- denying connection."; + 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 { // we can't let this user in since we couldn't convert their public key to an RSA key we could use diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index de647d09c4..0d38de7cf0 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -30,8 +31,7 @@ DataServerAccountInfo::DataServerAccountInfo() : _walletID(), _balance(0), _hasBalance(false), - _privateKey(), - _usernameSignature() + _privateKey() { } @@ -73,9 +73,6 @@ void DataServerAccountInfo::setAccessTokenFromJSON(const QJsonObject& jsonObject void DataServerAccountInfo::setUsername(const QString& username) { if (_username != username) { _username = username; - - // clear our username signature so it has to be re-created - _usernameSignature = QByteArray(); qCDebug(networking) << "Username changed to" << username; } @@ -138,13 +135,10 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo if (rsaPrivateKey) { QByteArray lowercaseUsername = _username.toLower().toUtf8(); QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); - QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); - - int encryptReturn = RSA_private_encrypt(usernameWithToken.size(), - reinterpret_cast(usernameWithToken.constData()), - reinterpret_cast(usernameSignature.data()), - rsaPrivateKey, RSA_PKCS1_PADDING); + QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); + unsigned int usernameSignatureSize = 0; + int encryptReturn = RSA_sign(NID_sha256, reinterpret_cast(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast(usernameSignature.data()), &usernameSignatureSize, rsaPrivateKey); // free the private key RSA struct now that we are done with it RSA_free(rsaPrivateKey); @@ -154,7 +148,6 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo qCDebug(networking) << "Will re-attempt on next domain-server check in."; } else { qDebug(networking) << "Signing username with connectionUUID " << connectionToken; - qDebug() << "Signature: " << usernameSignature.toHex(); return usernameSignature; } @@ -169,8 +162,6 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo void DataServerAccountInfo::setPrivateKey(const QByteArray& privateKey) { _privateKey = privateKey; - // clear our username signature so it has to be re-created - _usernameSignature = QByteArray(); } QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) { diff --git a/libraries/networking/src/DataServerAccountInfo.h b/libraries/networking/src/DataServerAccountInfo.h index 0d8157ccf3..9b80de5422 100644 --- a/libraries/networking/src/DataServerAccountInfo.h +++ b/libraries/networking/src/DataServerAccountInfo.h @@ -73,7 +73,7 @@ private: qint64 _balance; bool _hasBalance; QByteArray _privateKey; - QByteArray _usernameSignature; + }; #endif // hifi_DataServerAccountInfo_h diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 13224ca5bc..e8c92e37e3 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -289,6 +289,7 @@ void NodeList::sendDomainServerCheckIn() { QByteArray usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); if (!usernameSignature.isEmpty()) { + qDebug() << "Sending signature to packet stream " << usernameSignature.toHex(); packetStream << usernameSignature; } } @@ -463,6 +464,7 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer // refuse to process this packet if we aren't currently connected to the DS return; } + qDebug() << "Setting connection token and sending domain server checkin"; // read in the connection token from the packet, then send domain-server checkin _domainHandler.setConnectionToken(QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID))); sendDomainServerCheckIn(); From ab2b54a6b252aa768367d0b2b6cd203a1739533b Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 5 Aug 2015 15:33:59 -0700 Subject: [PATCH 08/12] Add connection token to sign with username when connecting to domain-server --- domain-server/src/DomainServer.cpp | 25 ++++++------------- .../networking/src/DataServerAccountInfo.cpp | 5 ++-- libraries/networking/src/DomainHandler.cpp | 4 +-- libraries/networking/src/NodeList.cpp | 4 +-- 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 706307dd70..09c5e31f06 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -644,18 +644,16 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) 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()->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 + bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); - // if username is empty, don't attempt to unpack username signature - if(isRestrictingAccess) { + if (isRestrictingAccess) { if (!username.isEmpty()) { - + // if there's a username, try to unpack username signature packetStream >> usernameSignature; - if(usernameSignature.isEmpty()) { - // if user didn't include username and usernameSignature in connect request, send a connectionToken packet + if (usernameSignature.isEmpty()) { + // if user didn't include usernameSignature in connect request, send a connectionToken packet QUuid& connectionToken = _connectionTokenHash[username.toLower()]; if (connectionToken.isNull()) { @@ -666,11 +664,7 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) connectionTokenPacket->reset(); connectionTokenPacket->write(connectionToken.toRfc4122()); limitedNodeList->sendUnreliablePacket(*connectionTokenPacket, packet->getSenderSockAddr()); - - qDebug() << "Sending connectionToken packet with connectionUUID " << _connectionTokenHash[username.toLower()]; - return; - } } } @@ -827,8 +821,6 @@ bool DomainServer::verifyUserSignature(const QString& username, // first load up the public key into an RSA struct RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); - //qDebug() << "Verifying signature: " << usernameSignature.toHex(); - QByteArray lowercaseUsername = username.toLower().toUtf8(); QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); @@ -837,17 +829,14 @@ bool DomainServer::verifyUserSignature(const QString& username, int decryptResult = RSA_verify(NID_sha256, reinterpret_cast(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast(usernameSignature.constData()), usernameSignature.size(), rsaPublicKey); - int err = ERR_get_error(); qDebug() << "Decrypt result: " << decryptResult << " Error: " << err; if (decryptResult == 1) { qDebug() << "Username signature matches for" << username << "- allowing connection."; - // free up the public key before we return + // free up the public key and remove connection token before we return RSA_free(rsaPublicKey); - - // remove the username's connection token from the hash _connectionTokenHash.remove(username); return true; diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index 0d38de7cf0..9824c1a811 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -135,7 +135,8 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo if (rsaPrivateKey) { QByteArray lowercaseUsername = _username.toLower().toUtf8(); QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); - QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); + + QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); unsigned int usernameSignatureSize = 0; int encryptReturn = RSA_sign(NID_sha256, reinterpret_cast(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast(usernameSignature.data()), &usernameSignatureSize, rsaPrivateKey); @@ -147,7 +148,7 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo qCDebug(networking) << "Error encrypting username signature."; qCDebug(networking) << "Will re-attempt on next domain-server check in."; } else { - qDebug(networking) << "Signing username with connectionUUID " << connectionToken; + qDebug(networking) << "Signing username with connectionUUID."; return usernameSignature; } diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index cd53d2608e..8f4b9cc61f 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -44,7 +44,8 @@ DomainHandler::DomainHandler(QObject* parent) : void DomainHandler::clearConnectionInfo() { _uuid = QUuid(); - + _connectionToken = QUuid(); + _icePeer.reset(); if (requiresICE()) { @@ -62,7 +63,6 @@ void DomainHandler::clearSettings() { void DomainHandler::softReset() { qCDebug(networking) << "Resetting current domain connection information."; - _connectionToken = QUuid(); clearConnectionInfo(); clearSettings(); } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e8c92e37e3..a1c99e9747 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -284,12 +284,11 @@ void NodeList::sendDomainServerCheckIn() { // get connection token from the domain-server QUuid connectionToken = _domainHandler.getConnectionToken(); - if(!connectionToken.isNull()) { + if (!connectionToken.isNull()) { QByteArray usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); if (!usernameSignature.isEmpty()) { - qDebug() << "Sending signature to packet stream " << usernameSignature.toHex(); packetStream << usernameSignature; } } @@ -464,7 +463,6 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer // refuse to process this packet if we aren't currently connected to the DS return; } - qDebug() << "Setting connection token and sending domain server checkin"; // read in the connection token from the packet, then send domain-server checkin _domainHandler.setConnectionToken(QUuid::fromRfc4122(packet->read(NUM_BYTES_RFC4122_UUID))); sendDomainServerCheckIn(); From 45e3eafce3df68cbaa17f05656cc429ae76122c9 Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 5 Aug 2015 16:00:25 -0700 Subject: [PATCH 09/12] Remove ERR_get_error call --- domain-server/src/DomainServer.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 09c5e31f06..293332dc83 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -829,9 +829,6 @@ bool DomainServer::verifyUserSignature(const QString& username, int decryptResult = RSA_verify(NID_sha256, reinterpret_cast(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast(usernameSignature.constData()), usernameSignature.size(), rsaPublicKey); - int err = ERR_get_error(); - qDebug() << "Decrypt result: " << decryptResult << " Error: " << err; - if (decryptResult == 1) { qDebug() << "Username signature matches for" << username << "- allowing connection."; @@ -840,6 +837,7 @@ bool DomainServer::verifyUserSignature(const QString& username, _connectionTokenHash.remove(username); return true; + } else { qDebug() << "Error decrypting username signature for " << username << "- denying connection."; reasonReturn = "Error decrypting username signature."; From a8f9f9d7469ee4e186809de0b3a19867ea42a12f Mon Sep 17 00:00:00 2001 From: bwent Date: Wed, 5 Aug 2015 17:43:03 -0700 Subject: [PATCH 10/12] clean-up formatting --- domain-server/src/DomainServer.cpp | 32 ++++++++----------- domain-server/src/DomainServer.h | 2 +- .../networking/src/DataServerAccountInfo.cpp | 13 ++++++-- libraries/networking/src/NodeList.cpp | 3 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 293332dc83..751e884480 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -577,7 +577,6 @@ const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer; void DomainServer::processConnectRequestPacket(QSharedPointer packet) { - NodeType_t nodeType; HifiSockAddr publicSockAddr, localSockAddr; @@ -638,16 +637,15 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) if (packet->bytesLeftToRead() > 0) { // try to verify username packetStream >> username; - } bool isRestrictingAccess = - _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + _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()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); + bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); - if (isRestrictingAccess) { + if (isRestrictingAccess && !isLocalUser) { if (!username.isEmpty()) { // if there's a username, try to unpack username signature packetStream >> usernameSignature; @@ -672,7 +670,6 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) QString 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 - QByteArray utfString = reason.toUtf8(); quint16 payloadSize = utfString.size(); @@ -680,12 +677,9 @@ void DomainServer::processConnectRequestPacket(QSharedPointer packet) if (payloadSize > 0) { connectionDeniedPacket->writePrimitive(payloadSize); connectionDeniedPacket->write(utfString); - } - // tell client it has been refused. limitedNodeList->sendPacket(std::move(connectionDeniedPacket), senderSockAddr); - return; } @@ -791,7 +785,6 @@ void DomainServer::processListRequestPacket(QSharedPointer packet, Sha sendDomainListToNode(sendingNode, packet->getSenderSockAddr(), nodeInterestList.toSet()); } - unsigned int DomainServer::countConnectedUsers() { unsigned int result = 0; auto nodeList = DependencyManager::get(); @@ -805,13 +798,13 @@ unsigned int DomainServer::countConnectedUsers() { bool DomainServer::verifyUserSignature(const QString& username, - const QByteArray& usernameSignature, - QString& reasonReturn) { + const QByteArray& usernameSignature, + QString& reasonReturn) { // it's possible this user can be allowed to connect, but we need to check their username signature QByteArray publicKeyArray = _userPublicKeys.value(username); - QUuid connectionToken = _connectionTokenHash.value(username.toLower()); + 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 @@ -822,7 +815,8 @@ bool DomainServer::verifyUserSignature(const QString& username, RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); QByteArray lowercaseUsername = username.toLower().toUtf8(); - QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), + QCryptographicHash::Sha256); if (rsaPublicKey) { QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); @@ -866,14 +860,14 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, const HifiSockAddr& senderSockAddr, QString& reasonReturn) { bool isRestrictingAccess = - _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); - if(isRestrictingAccess) { + if (isRestrictingAccess) { QStringList allowedUsers = - _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); + _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); if (allowedUsers.contains(username, Qt::CaseInsensitive)) { - if(username.isEmpty()) { + if (username.isEmpty()) { qDebug() << "Connect request denied - no username provided."; reasonReturn = "No username provided"; return false; @@ -892,7 +886,7 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, // 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 const QVariant* allowedEditorsVariant = - valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); + valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); if (allowedEditors.contains(username)) { if (verifyUserSignature(username, usernameSignature, reasonReturn)) { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index fe79ec4889..7495e080de 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -57,7 +57,7 @@ public slots: void processRequestAssignmentPacket(QSharedPointer packet); void processConnectRequestPacket(QSharedPointer packet); - void processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode);; + void processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processNodeJSONStatsPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processPathQueryPacket(QSharedPointer packet); void processICEPingPacket(QSharedPointer packet); diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index 9824c1a811..0628e21574 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -16,6 +16,7 @@ #include #include +#include "UUID.h" #include "NetworkLogging.h" #include "DataServerAccountInfo.h" @@ -134,12 +135,18 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo _privateKey.size()); if (rsaPrivateKey) { QByteArray lowercaseUsername = _username.toLower().toUtf8(); - QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), + QCryptographicHash::Sha256); QByteArray usernameSignature(RSA_size(rsaPrivateKey), 0); unsigned int usernameSignatureSize = 0; - int encryptReturn = RSA_sign(NID_sha256, reinterpret_cast(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast(usernameSignature.data()), &usernameSignatureSize, rsaPrivateKey); + int encryptReturn = RSA_sign(NID_sha256, + reinterpret_cast(usernameWithToken.constData()), + usernameWithToken.size(), + reinterpret_cast(usernameSignature.data()), + &usernameSignatureSize, + rsaPrivateKey); // free the private key RSA struct now that we are done with it RSA_free(rsaPrivateKey); @@ -148,7 +155,7 @@ QByteArray DataServerAccountInfo::getUsernameSignature(const QUuid& connectionTo qCDebug(networking) << "Error encrypting username signature."; qCDebug(networking) << "Will re-attempt on next domain-server check in."; } else { - qDebug(networking) << "Signing username with connectionUUID."; + qDebug(networking) << "Returning username" << _username << "signed with connection UUID" << uuidStringWithoutCurlyBraces(connectionToken); return usernameSignature; } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index a1c99e9747..f2fb8522b0 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -286,7 +286,7 @@ void NodeList::sendDomainServerCheckIn() { if (!connectionToken.isNull()) { - QByteArray usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); + const QByteArray& usernameSignature = AccountManager::getInstance().getAccountInfo().getUsernameSignature(connectionToken); if (!usernameSignature.isEmpty()) { packetStream << usernameSignature; @@ -466,7 +466,6 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer // 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 packet) { From 73ea95864060a198c562201b7c4c473bf3df8047 Mon Sep 17 00:00:00 2001 From: bwent Date: Thu, 6 Aug 2015 09:01:25 -0700 Subject: [PATCH 11/12] add check if user is local user --- domain-server/src/DomainServer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 751e884480..da5d18dfca 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -859,10 +859,13 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr, QString& reasonReturn) { + + //TODO: improve flow so these bools aren't declared twice bool isRestrictingAccess = _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); - if (isRestrictingAccess) { + if (isRestrictingAccess && !isLocalUser) { QStringList allowedUsers = _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); From ffccc9ca9653e302ba8e4a5666750515e519389a Mon Sep 17 00:00:00 2001 From: bwent Date: Thu, 6 Aug 2015 10:11:22 -0700 Subject: [PATCH 12/12] clean up formatting, make connectionUUID const in NodeList --- domain-server/src/DomainServer.cpp | 8 ++++++-- libraries/networking/src/NodeList.cpp | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index da5d18dfca..4e5b563fc6 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -820,8 +820,12 @@ bool DomainServer::verifyUserSignature(const QString& username, if (rsaPublicKey) { QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); - int decryptResult = - RSA_verify(NID_sha256, reinterpret_cast(usernameWithToken.constData()), usernameWithToken.size(), reinterpret_cast(usernameSignature.constData()), usernameSignature.size(), rsaPublicKey); + int decryptResult = RSA_verify(NID_sha256, + reinterpret_cast(usernameWithToken.constData()), + usernameWithToken.size(), + reinterpret_cast(usernameSignature.constData()), + usernameSignature.size(), + rsaPublicKey); if (decryptResult == 1) { qDebug() << "Username signature matches for" << username << "- allowing connection."; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index f2fb8522b0..44b9c0b829 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -282,7 +282,7 @@ void NodeList::sendDomainServerCheckIn() { packetStream << accountInfo.getUsername(); // get connection token from the domain-server - QUuid connectionToken = _domainHandler.getConnectionToken(); + const QUuid& connectionToken = _domainHandler.getConnectionToken(); if (!connectionToken.isNull()) {