Overte C++ Documentation
DomainGatekeeper.h
1 //
2 // DomainGatekeeper.h
3 // domain-server/src
4 //
5 // Created by Stephen Birarda on 2015-08-24.
6 // Copyright 2015 High Fidelity, Inc.
7 // Copyright 2020 Vircadia contributors.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 //
12 
13 #pragma once
14 
15 #ifndef hifi_DomainGatekeeper_h
16 #define hifi_DomainGatekeeper_h
17 
18 #include <unordered_map>
19 #include <unordered_set>
20 
21 #include <QtCore/QObject>
22 #include <QtNetwork/QNetworkReply>
23 #include <QtCore/QSharedPointer>
24 
25 #include <DomainHandler.h>
26 
27 #include <NLPacket.h>
28 #include <Node.h>
29 #include <UUIDHasher.h>
30 
31 #include "NodeConnectionData.h"
32 #include "PendingAssignedNodeData.h"
33 
34 const QString DOMAIN_GROUP_CHAR = "@";
35 
36 class DomainServer;
37 
38 class DomainGatekeeper : public QObject {
39  Q_OBJECT
40 public:
41  DomainGatekeeper(DomainServer* server);
42 
43  void addPendingAssignedNode(const QUuid& nodeUUID, const QUuid& assignmentUUID, const QString& nodeVersion);
44  QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID);
45 
46  void cleanupICEPeerForNode(const QUuid& nodeID);
47 
48  Node::LocalID findOrCreateLocalID(const QUuid& uuid);
49 
50  static void sendProtocolMismatchConnectionDenial(const SockAddr& senderSockAddr);
51 public slots:
52  void processConnectRequestPacket(QSharedPointer<ReceivedMessage> message);
53  void processICEPingPacket(QSharedPointer<ReceivedMessage> message);
54  void processICEPingReplyPacket(QSharedPointer<ReceivedMessage> message);
55  void processICEPeerInformationPacket(QSharedPointer<ReceivedMessage> message);
56 
57  void publicKeyJSONCallback(QNetworkReply* requestReply);
58  void publicKeyJSONErrorCallback(QNetworkReply* requestReply);
59 
60  void getIsGroupMemberJSONCallback(QNetworkReply* requestReply);
61  void getIsGroupMemberErrorCallback(QNetworkReply* requestReply);
62 
63  void getDomainOwnerFriendsListJSONCallback(QNetworkReply* requestReply);
64  void getDomainOwnerFriendsListErrorCallback(QNetworkReply* requestReply);
65 
66  void refreshGroupsCache();
67 
68 signals:
69  void killNode(SharedNodePointer node);
70  void connectedNode(SharedNodePointer node, quint64 requestReceiveTime);
71 
72 public slots:
73  void updateNodePermissions();
74 
75 private slots:
76  void handlePeerPingTimeout();
77 
78  // Login and groups for domain, separate from directory services.
79  void requestDomainUserFinished();
80 
81 private:
82  SharedNodePointer processAssignmentConnectRequest(const NodeConnectionData& nodeConnection,
83  const PendingAssignedNodeData& pendingAssignment);
84  SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection,
85  const QString& username,
86  const QByteArray& usernameSignature,
87  const QString& domainUsername,
88  const QString& domainAccessToken,
89  const QString& domainRefreshToken);
90  SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection);
91 
92  bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature,
93  const SockAddr& senderSockAddr);
94 
95  bool needToVerifyDomainUserIdentity(const QString& username, const QString& accessToken, const QString& refreshToken);
96  bool verifyDomainUserIdentity(const QString& username, const QString& accessToken, const QString& refreshToken,
97  const SockAddr& senderSockAddr);
98 
99  bool isWithinMaxCapacity();
100 
101  bool shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature,
102  const SockAddr& senderSockAddr);
103 
104  void sendConnectionTokenPacket(const QString& username, const SockAddr& senderSockAddr);
105  static void sendConnectionDeniedPacket(const QString& reason, const SockAddr& senderSockAddr,
106  DomainHandler::ConnectionRefusedReason reasonCode = DomainHandler::ConnectionRefusedReason::Unknown,
107  QString extraInfo = QString());
108 
109  void pingPunchForConnectingPeer(const SharedNetworkPeer& peer);
110 
111  void requestUserPublicKey(const QString& username, bool isOptimistic = false);
112 
113  DomainServer* _server;
114 
115  std::unordered_map<QUuid, PendingAssignedNodeData> _pendingAssignedNodes;
116 
117  QHash<QUuid, SharedNetworkPeer> _icePeers;
118 
119  using ConnectingNodeID = QUuid;
120  using ICEPeerID = QUuid;
121  QHash<ConnectingNodeID, ICEPeerID> _nodeToICEPeerIDs;
122 
123  QHash<QString, QUuid> _connectionTokenHash;
124 
125  // the word "optimistic" below is used for keys that we request during user connection before the user has
126  // had a chance to upload a new public key
127 
128  // we don't send back user signature decryption errors for those keys so that there isn't a thrasing of key re-generation
129  // and connection refusal
130 
131  using KeyFlagPair = QPair<QByteArray, bool>;
132 
133  QHash<QString, KeyFlagPair> _userPublicKeys; // keep track of keys and flag them as optimistic or not
134  QHash<QString, bool> _inFlightPublicKeyRequests; // keep track of keys we've asked for (and if it was optimistic)
135  QSet<QString> _domainOwnerFriends; // keep track of friends of the domain owner
136  QSet<QString> _inFlightGroupMembershipsRequests; // keep track of which we've already asked for
137 
138  NodePermissions setPermissionsForUser(bool isLocalUser, QString verifiedUsername, QString verifiedDomainUsername,
139  const QHostAddress& senderAddress, const QString& hardwareAddress,
140  const QUuid& machineFingerprint);
141 
142  void getGroupMemberships(const QString& username);
143  // void getIsGroupMember(const QString& username, const QUuid groupID);
144  void getDomainOwnerFriendsList();
145 
146  // Local ID management.
147  void initLocalIDManagement();
148  using UUIDToLocalID = std::unordered_map<QUuid, Node::LocalID> ;
149  using LocalIDs = std::unordered_set<Node::LocalID>;
150  LocalIDs _localIDs;
151  UUIDToLocalID _uuidToLocalID;
152  Node::LocalID _currentLocalID;
153  Node::LocalID _idIncrement;
154 
155  // Login and groups for domain, separate from directory services.
156  bool domainHasLogin();
157  void requestDomainUser(const QString& username, const QString& accessToken, const QString& refreshToken);
158 
159  typedef QHash<QString, QPair<QString, QString>> DomainUserIdentities; // <domainUserName, <access_token, refresh_token>>
160  DomainUserIdentities _inFlightDomainUserIdentityRequests; // Domain user identity requests currently in progress.
161  DomainUserIdentities _verifiedDomainUserIdentities; // Verified domain users.
162 
163  QHash<QString, QStringList> _domainGroupMemberships; // <domainUserName, [domainGroupName]>
164 };
165 
166 
167 #endif // hifi_DomainGatekeeper_h