浏览代码

Clean out some unnecessarily pedantic auth stuff in favor of a simpler way of gating multicast gathers.

Adam Ierymenko 6 年之前
父节点
当前提交
e03102dbcb
共有 8 个文件被更改,包括 51 次插入121 次删除
  1. 17 52
      node/IncomingPacket.cpp
  2. 1 21
      node/Multicaster.cpp
  3. 0 39
      node/Multicaster.hpp
  4. 0 1
      node/Network.cpp
  5. 5 7
      node/Network.hpp
  6. 4 0
      node/Node.cpp
  7. 23 0
      node/Node.hpp
  8. 1 1
      node/Switch.cpp

+ 17 - 52
node/IncomingPacket.cpp

@@ -645,8 +645,6 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const Shar
 			_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
 			_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
 			RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_FRAME,true);
 			RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_FRAME,true);
 		}
 		}
-	} else {
-		_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
 	}
 	}
 
 
 	peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished,nwid);
 	peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_FRAME,0,Packet::VERB_NOP,trustEstablished,nwid);
@@ -757,45 +755,10 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share
 bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
 bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
 {
 {
 	const int64_t now = RR->node->now();
 	const int64_t now = RR->node->now();
-
-	uint64_t authOnNetwork[256]; // cache for approved network IDs
-	unsigned int authOnNetworkCount = 0;
-	SharedPtr<Network> network;
-	bool trustEstablished = false;
-
-	// Iterate through 18-byte network,MAC,ADI tuples
-	for(unsigned int ptr=ZT_PACKET_IDX_PAYLOAD;ptr<size();ptr+=18) {
-		const uint64_t nwid = at<uint64_t>(ptr);
-
-		bool auth = false;
-		for(unsigned int i=0;i<authOnNetworkCount;++i) {
-			if (nwid == authOnNetwork[i]) {
-				auth = true;
-				break;
-			}
-		}
-		if (!auth) {
-			if ((!network)||(network->id() != nwid))
-				network = RR->node->network(nwid);
-			const bool authOnNet = ((network)&&(network->gate(tPtr,peer)));
-			if (!authOnNet)
-				_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
-			trustEstablished |= authOnNet;
-			if (authOnNet||RR->mc->cacheAuthorized(peer->address(),nwid,now)) {
-				auth = true;
-				if (authOnNetworkCount < 256) // sanity check, packets can't really be this big
-					authOnNetwork[authOnNetworkCount++] = nwid;
-			}
-		}
-
-		if (auth) {
-			const MulticastGroup group(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14));
-			RR->mc->add(tPtr,now,nwid,group,peer->address());
-		}
-	}
-
-	peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,trustEstablished,(network) ? network->id() : 0);
-
+	// Packet contains a series of 18-byte network,MAC,ADI tuples
+	for(unsigned int ptr=ZT_PACKET_IDX_PAYLOAD;ptr<size();ptr+=18)
+		RR->mc->add(tPtr,now,at<uint64_t>(ptr),MulticastGroup(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14)),peer->address());
+	peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,false,0);
 	return true;
 	return true;
 }
 }
 
 
@@ -828,7 +791,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t
 					case Membership::ADD_DEFERRED_FOR_WHOIS:
 					case Membership::ADD_DEFERRED_FOR_WHOIS:
 						return false;
 						return false;
 				}
 				}
-			} else RR->mc->addCredential(tPtr,com,false);
+			}
 		}
 		}
 	}
 	}
 	++p; // skip trailing 0 after COMs if present
 	++p; // skip trailing 0 after COMs if present
@@ -982,18 +945,20 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
 		try {
 		try {
 			CertificateOfMembership com;
 			CertificateOfMembership com;
 			com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM);
 			com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM);
-			if (com) {
-				if (network)
-					network->addCredential(tPtr,com);
-				else RR->mc->addCredential(tPtr,com,false);
-			}
+			if ((com)&&(network))
+				network->addCredential(tPtr,com);
 		} catch ( ... ) {} // discard invalid COMs
 		} catch ( ... ) {} // discard invalid COMs
 	}
 	}
 
 
-	const bool trustEstablished = ((network)&&(network->gate(tPtr,peer)));
-	if (!trustEstablished)
-		_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
-	if ( ( trustEstablished || RR->mc->cacheAuthorized(peer->address(),nwid,RR->node->now()) ) && (gatherLimit > 0) ) {
+	bool trustEstablished = false;
+	if (network) {
+		if (network->gate(tPtr,peer))
+			trustEstablished = true;
+		else _sendErrorNeedCredentials(RR,tPtr,peer,nwid);
+	}
+
+	const int64_t now = RR->node->now();
+	if ((gatherLimit > 0)&&((trustEstablished)||(RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())))) {
 		Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
 		Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
 		outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER);
 		outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER);
 		outp.append(packetId());
 		outp.append(packetId());
@@ -1003,7 +968,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
 		const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit);
 		const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit);
 		if (gatheredLocally > 0) {
 		if (gatheredLocally > 0) {
 			outp.armor(peer->key(),true);
 			outp.armor(peer->key(),true);
-			_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
+			_path->send(RR,tPtr,outp.data(),outp.size(),now);
 		}
 		}
 	}
 	}
 
 

+ 1 - 21
node/Multicaster.cpp

@@ -42,8 +42,7 @@ namespace ZeroTier {
 
 
 Multicaster::Multicaster(const RuntimeEnvironment *renv) :
 Multicaster::Multicaster(const RuntimeEnvironment *renv) :
 	RR(renv),
 	RR(renv),
-	_groups(256),
-	_gatherAuth(256)
+	_groups(32)
 {
 {
 }
 }
 
 
@@ -415,25 +414,6 @@ void Multicaster::clean(int64_t now)
 			}
 			}
 		}
 		}
 	}
 	}
-
-	{
-		Mutex::Lock _l(_gatherAuth_m);
-		_GatherAuthKey *k = (_GatherAuthKey *)0;
-		uint64_t *ts = NULL;
-		Hashtable<_GatherAuthKey,uint64_t>::Iterator i(_gatherAuth);
-		while (i.next(k,ts)) {
-			if ((now - *ts) >= ZT_MULTICAST_CREDENTIAL_EXPIRATON)
-				_gatherAuth.erase(*k);
-		}
-	}
-}
-
-void Multicaster::addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated)
-{
-	if ((alreadyValidated)||(com.verify(RR,tPtr) == 0)) {
-		Mutex::Lock _l(_gatherAuth_m);
-		_gatherAuth[_GatherAuthKey(com.networkId(),com.issuedTo())] = RR->node->now();
-	}
 }
 }
 
 
 void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member)
 void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member)

+ 0 - 39
node/Multicaster.hpp

@@ -158,33 +158,6 @@ public:
 	 */
 	 */
 	void clean(int64_t now);
 	void clean(int64_t now);
 
 
-	/**
-	 * Add an authorization credential
-	 *
-	 * The Multicaster keeps its own track of when valid credentials of network
-	 * membership are presented. This allows it to control MULTICAST_LIKE
-	 * GATHER authorization for networks this node does not belong to.
-	 *
-	 * @param com Certificate of membership
-	 * @param alreadyValidated If true, COM has already been checked and found to be valid and signed
-	 */
-	void addCredential(void *tPtr,const CertificateOfMembership &com,bool alreadyValidated);
-
-	/**
-	 * Check authorization for GATHER and LIKE for non-network-members
-	 *
-	 * @param a Address of peer
-	 * @param nwid Network ID
-	 * @param now Current time
-	 * @return True if GATHER and LIKE should be allowed
-	 */
-	bool cacheAuthorized(const Address &a,const uint64_t nwid,const int64_t now) const
-	{
-		Mutex::Lock _l(_gatherAuth_m);
-		const uint64_t *p = _gatherAuth.get(_GatherAuthKey(nwid,a));
-		return ((p)&&((now - *p) < ZT_MULTICAST_CREDENTIAL_EXPIRATON));
-	}
-
 private:
 private:
 	struct Key
 	struct Key
 	{
 	{
@@ -226,18 +199,6 @@ private:
 
 
 	Hashtable<Multicaster::Key,MulticastGroupStatus> _groups;
 	Hashtable<Multicaster::Key,MulticastGroupStatus> _groups;
 	Mutex _groups_m;
 	Mutex _groups_m;
-
-	struct _GatherAuthKey
-	{
-		_GatherAuthKey() : member(0),networkId(0) {}
-		_GatherAuthKey(const uint64_t nwid,const Address &a) : member(a.toInt()),networkId(nwid) {}
-		inline unsigned long hashCode() const { return (unsigned long)(member ^ networkId); }
-		inline bool operator==(const _GatherAuthKey &k) const { return ((member == k.member)&&(networkId == k.networkId)); }
-		uint64_t member;
-		uint64_t networkId;
-	};
-	Hashtable< _GatherAuthKey,uint64_t > _gatherAuth;
-	Mutex _gatherAuth_m;
 };
 };
 
 
 } // namespace ZeroTier
 } // namespace ZeroTier

+ 0 - 1
node/Network.cpp

@@ -1370,7 +1370,6 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Certific
 	const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,com);
 	const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,com);
 	if ((result == Membership::ADD_ACCEPTED_NEW)||(result == Membership::ADD_ACCEPTED_REDUNDANT)) {
 	if ((result == Membership::ADD_ACCEPTED_NEW)||(result == Membership::ADD_ACCEPTED_REDUNDANT)) {
 		m.pushCredentials(RR,tPtr,RR->node->now(),a,_config,-1,false);
 		m.pushCredentials(RR,tPtr,RR->node->now(),a,_config,-1,false);
-		RR->mc->addCredential(tPtr,com,true);
 	}
 	}
 	return result;
 	return result;
 }
 }

+ 5 - 7
node/Network.hpp

@@ -290,6 +290,11 @@ public:
 		return ((br) ? *br : Address());
 		return ((br) ? *br : Address());
 	}
 	}
 
 
+	/**
+	 * @return True if QoS is in effect for this network
+	 */
+	inline bool qosEnabled() { return false; }
+
 	/**
 	/**
 	 * Set a bridge route
 	 * Set a bridge route
 	 *
 	 *
@@ -298,13 +303,6 @@ public:
 	 */
 	 */
 	void learnBridgeRoute(const MAC &mac,const Address &addr);
 	void learnBridgeRoute(const MAC &mac,const Address &addr);
 
 
-	/**
-	 * Whether QoS is in effect for this network
-	 */
-	bool QoSEnabled() {
-		return false;
-	}
-
 	/**
 	/**
 	 * Learn a multicast group that is bridged to our tap device
 	 * Learn a multicast group that is bridged to our tap device
 	 *
 	 *

+ 4 - 0
node/Node.cpp

@@ -633,6 +633,10 @@ std::vector<World> Node::moons() const
 
 
 void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
 void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
 {
 {
+	_localControllerAuthorizations_m.lock();
+	_localControllerAuthorizations[_LocalControllerAuth(nwid,destination)] = now();
+	_localControllerAuthorizations_m.unlock();
+
 	if (destination == RR->identity.address()) {
 	if (destination == RR->identity.address()) {
 		SharedPtr<Network> n(network(nwid));
 		SharedPtr<Network> n(network(nwid));
 		if (!n) return;
 		if (!n) return;

+ 23 - 0
node/Node.hpp

@@ -263,6 +263,16 @@ public:
 	inline void setMultipathMode(uint8_t mode) { _multipathMode = mode; }
 	inline void setMultipathMode(uint8_t mode) { _multipathMode = mode; }
 	inline uint8_t getMultipathMode() { return _multipathMode; }
 	inline uint8_t getMultipathMode() { return _multipathMode; }
 
 
+	inline bool localControllerHasAuthorized(const int64_t now,const uint64_t nwid,const Address &addr) const
+	{
+		_localControllerAuthorizations_m.lock();
+		const int64_t *const at = _localControllerAuthorizations.get(_LocalControllerAuth(nwid,addr));
+		_localControllerAuthorizations_m.unlock();
+		if (at)
+			return ((now - *at) < (ZT_NETWORK_AUTOCONF_DELAY * 3));
+		return false;
+	}
+
 private:
 private:
 	RuntimeEnvironment _RR;
 	RuntimeEnvironment _RR;
 	RuntimeEnvironment *RR;
 	RuntimeEnvironment *RR;
@@ -276,6 +286,19 @@ private:
 	// Time of last identity verification indexed by InetAddress.rateGateHash() -- used in IncomingPacket::_doHELLO() via rateGateIdentityVerification()
 	// Time of last identity verification indexed by InetAddress.rateGateHash() -- used in IncomingPacket::_doHELLO() via rateGateIdentityVerification()
 	int64_t _lastIdentityVerification[16384];
 	int64_t _lastIdentityVerification[16384];
 
 
+	// Map that remembers if we have recently sent a network config to someone
+	// querying us as a controller.
+	struct _LocalControllerAuth
+	{
+		uint64_t nwid,address;
+		_LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {}
+		inline unsigned long hashCode() const { return (unsigned long)(nwid ^ address); }
+		inline bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); }
+		inline bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); }
+	};
+	Hashtable< _LocalControllerAuth,int64_t > _localControllerAuthorizations;
+	Mutex _localControllerAuthorizations_m;
+
 	Hashtable< uint64_t,SharedPtr<Network> > _networks;
 	Hashtable< uint64_t,SharedPtr<Network> > _networks;
 	Mutex _networks_m;
 	Mutex _networks_m;
 
 

+ 1 - 1
node/Switch.cpp

@@ -502,7 +502,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
 
 
 void Switch::aqm_enqueue(void *tPtr, const SharedPtr<Network> &network, Packet &packet,bool encrypt,int qosBucket)
 void Switch::aqm_enqueue(void *tPtr, const SharedPtr<Network> &network, Packet &packet,bool encrypt,int qosBucket)
 {
 {
-	if(!network->QoSEnabled()) {
+	if(!network->qosEnabled()) {
 		send(tPtr, packet, encrypt);
 		send(tPtr, packet, encrypt);
 		return;
 		return;
 	}
 	}