Переглянути джерело

This may improve controller behavior with SSO and mixed SSO, needs testing!

Adam Ierymenko 3 роки тому
батько
коміт
42a2afaef9

+ 4 - 0
controller/DBMirrorSet.cpp

@@ -248,6 +248,7 @@ void DBMirrorSet::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,u
 	_listener->onNetworkMemberDeauthorize(this,networkId,memberId);
 }
 
+/*
 void DBMirrorSet::membersExpiring(std::set< std::pair<uint64_t, uint64_t> > &soon, std::set< std::pair<uint64_t, uint64_t> > &expired)
 {
 	std::unique_lock<std::mutex> l(_membersExpiringSoon_l);
@@ -284,11 +285,14 @@ void DBMirrorSet::membersExpiring(std::set< std::pair<uint64_t, uint64_t> > &soo
 		_membersExpiringSoon.erase(next++);
 	}
 }
+*/
 
+/*
 void DBMirrorSet::memberWillExpire(int64_t expTime, uint64_t nwid, uint64_t memberId)
 {
 	std::unique_lock<std::mutex> l(_membersExpiringSoon_l);
 	_membersExpiringSoon.insert(std::pair< int64_t, std::pair< uint64_t, uint64_t > >(expTime, std::pair< uint64_t, uint64_t >(nwid, memberId)));
 }
+*/
 
 } // namespace ZeroTier

+ 4 - 4
controller/DBMirrorSet.hpp

@@ -61,8 +61,8 @@ public:
 		_dbs.push_back(db);
 	}
 
-	void membersExpiring(std::set< std::pair<uint64_t, uint64_t> > &soon, std::set< std::pair<uint64_t, uint64_t> > &expired);
-	void memberWillExpire(int64_t expTime, uint64_t nwid, uint64_t memberId);
+	//void membersExpiring(std::set< std::pair<uint64_t, uint64_t> > &soon, std::set< std::pair<uint64_t, uint64_t> > &expired);
+	//void memberWillExpire(int64_t expTime, uint64_t nwid, uint64_t memberId);
 
 private:
 	DB::ChangeListener *const _listener;
@@ -70,8 +70,8 @@ private:
 	std::thread _syncCheckerThread;
 	std::vector< std::shared_ptr< DB > > _dbs;
 	mutable std::mutex _dbs_l;
-	std::set< std::pair< int64_t, std::pair<uint64_t, uint64_t> > > _membersExpiringSoon;
-	mutable std::mutex _membersExpiringSoon_l;
+	//std::set< std::pair< int64_t, std::pair<uint64_t, uint64_t> > > _membersExpiringSoon;
+	//mutable std::mutex _membersExpiringSoon_l;
 };
 
 } // namespace ZeroTier

+ 39 - 7
controller/EmbeddedNetworkController.cpp

@@ -1335,9 +1335,10 @@ void EmbeddedNetworkController::_request(
 	// Should we check SSO Stuff?
 	// If network is configured with SSO, and the member is not marked exempt: yes
 	// Otherwise no, we use standard auth logic.
+	AuthInfo info;
+	int64_t authenticationExpiryTime = -1;
 	bool networkSSOEnabled = OSUtils::jsonBool(network["ssoEnabled"], false);
 	bool memberSSOExempt = OSUtils::jsonBool(member["ssoExempt"], false);
-	AuthInfo info;
 	if (networkSSOEnabled && !memberSSOExempt) {
 		// TODO:  Get expiry time if auth is still valid
 
@@ -1347,7 +1348,7 @@ void EmbeddedNetworkController::_request(
 
 		std::string memberId = member["id"];
 		//fprintf(stderr, "ssoEnabled && !ssoExempt %s-%s\n", nwids, memberId.c_str());
-		uint64_t authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0);
+		authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0);
 		fprintf(stderr, "authExpiryTime: %lld\n", authenticationExpiryTime);
 		if (authenticationExpiryTime < now) {
 			fprintf(stderr, "Handling expired member\n");
@@ -1392,7 +1393,7 @@ void EmbeddedNetworkController::_request(
 			}
 		} else if (authorized) {
 			fprintf(stderr, "Setting member will expire to: %lld\n", authenticationExpiryTime);
-			_db.memberWillExpire(authenticationExpiryTime, nwid, identity.address().toInt());
+			//_db.memberWillExpire(authenticationExpiryTime, nwid, identity.address().toInt());
 		}
 	}
 
@@ -1409,10 +1410,12 @@ void EmbeddedNetworkController::_request(
 			member["vRev"] = vRev;
 			member["vProto"] = vProto;
 
+			_MemberStatusKey msk(nwid,identity.address().toInt());
+
 			{
 				std::lock_guard<std::mutex> l(_memberStatus_l);
-				_MemberStatus &ms = _memberStatus[_MemberStatusKey(nwid,identity.address().toInt())];
-
+				_MemberStatus &ms = _memberStatus[msk];
+				ms.authenticationExpiryTime = authenticationExpiryTime;
 				ms.vMajor = (int)vMajor;
 				ms.vMinor = (int)vMinor;
 				ms.vRev = (int)vRev;
@@ -1420,9 +1423,13 @@ void EmbeddedNetworkController::_request(
 				ms.lastRequestMetaData = metaData;
 				ms.identity = identity;
 			}
-		}		
+
+			if (authenticationExpiryTime > 0) {
+				std::lock_guard<std::mutex> l(_expiringSoon_l);
+				_expiringSoon.insert(std::pair<int64_t, _MemberStatusKey>(authenticationExpiryTime, msk));
+			}
+		}
 	} else {
-		
 		// If they are not authorized, STOP!
 		DB::cleanMember(member);
 		_db.save(member,true);
@@ -1876,6 +1883,30 @@ void EmbeddedNetworkController::_startThreads()
 					}
 				}
 
+				std::vector< std::pair<uint64_t, uint64_t> > expired;
+				int64_t now = OSUtils::now();
+				{
+					std::lock_guard<std::mutex> l(_expiringSoon_l);
+					for(auto s=_expiringSoon.begin();s!=_expiringSoon.end();) {
+						int64_t when = s->first;
+						if (when <= now) {
+							// Remove expired entries and if they are still correct as per the network status, deauth them.
+							std::lock_guard<std::mutex> l(_memberStatus_l);
+							_MemberStatus &ms = _memberStatus[s->second];
+							if ((ms.authenticationExpiryTime > 0)&&(ms.authenticationExpiryTime <= now)) {
+								expired.push_back(std::pair<uint64_t, uint64_t>(s->second.networkId, s->second.nodeId));
+							}
+							_expiringSoon.erase(s++);
+						} else if ((when - now) > 1000) {
+							// Don't bother going further into the future than necessary.
+							break;
+						} else {
+							++s;
+						}
+					}
+				}
+
+				/*
 				std::set< std::pair<uint64_t, uint64_t> > soon;
 				std::set< std::pair<uint64_t, uint64_t> > expired;
 				_db.membersExpiring(soon, expired);
@@ -1895,6 +1926,7 @@ void EmbeddedNetworkController::_startThreads()
 						request(s->first,InetAddress(),0,identity,lastMetaData);
 					}
 				}
+				*/
 
 				for(auto e=expired.begin();e!=expired.end();++e) {
 					onNetworkMemberDeauthorize(nullptr, e->first, e->second);

+ 7 - 2
controller/EmbeddedNetworkController.hpp

@@ -109,6 +109,7 @@ private:
 			RQENTRY_TYPE_REQUEST = 0
 		} type;
 	};
+
 	struct _MemberStatusKey
 	{
 		_MemberStatusKey() : networkId(0),nodeId(0) {}
@@ -119,8 +120,9 @@ private:
 	};
 	struct _MemberStatus
 	{
-		_MemberStatus() : lastRequestTime(0),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
-		uint64_t lastRequestTime;
+		_MemberStatus() : lastRequestTime(0),authenticationExpiryTime(-1),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
+		int64_t lastRequestTime;
+		int64_t authenticationExpiryTime;
 		int vMajor,vMinor,vRev,vProto;
 		Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastRequestMetaData;
 		Identity identity;
@@ -152,6 +154,9 @@ private:
 	std::unordered_map< _MemberStatusKey,_MemberStatus,_MemberStatusHash > _memberStatus;
 	std::mutex _memberStatus_l;
 
+	std::multimap< int64_t, _MemberStatusKey > _expiringSoon;
+	std::mutex _expiringSoon_l;
+
 	RedisConfig *_rc;
 	std::string _ssoRedirectURL;
 };