Adam Ierymenko 9 years ago
parent
commit
5cf410490e
5 changed files with 58 additions and 39 deletions
  1. 3 0
      node/CertificateOfMembership.cpp
  2. 6 6
      node/IncomingPacket.cpp
  3. 5 0
      node/Membership.hpp
  4. 36 33
      node/Network.cpp
  5. 8 0
      node/Topology.hpp

+ 3 - 0
node/CertificateOfMembership.cpp

@@ -155,6 +155,9 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) c
 	unsigned int myidx = 0;
 	unsigned int otheridx = 0;
 
+	if ((_qualifierCount == 0)||(other._qualifierCount == 0))
+		return false;
+
 	while (myidx < _qualifierCount) {
 		// Fail if we're at the end of other, since this means the field is
 		// missing.

+ 6 - 6
node/IncomingPacket.cpp

@@ -446,7 +446,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
 				if ((flags & 0x01) != 0) { // deprecated but still used by older peers
 					CertificateOfMembership com;
 					offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS);
-					LockingPtr<Membership> m = peer->membership(com.networkId(),true);
+					LockingPtr<Membership> m(peer->membership(com.networkId(),true));
 					if (m) m->addCredential(RR,RR->node->now(),com);
 				}
 
@@ -586,7 +586,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
 				if ((flags & 0x01) != 0) { // deprecated but still used by old peers
 					CertificateOfMembership com;
 					comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
-					LockingPtr<Membership> m = peer->membership(com.networkId(),true);
+					LockingPtr<Membership> m(peer->membership(com.networkId(),true));
 					if (m) m->addCredential(RR,RR->node->now(),com);
 				}
 
@@ -707,7 +707,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
 		unsigned int p = ZT_PACKET_IDX_PAYLOAD;
 		while ((p < size())&&((*this)[p])) {
 			p += com.deserialize(*this,p);
-			LockingPtr<Membership> m = peer->membership(com.networkId(),true);
+			LockingPtr<Membership> m(peer->membership(com.networkId(),true));
 			if (!m) return true; // sanity check
 			if (m->addCredential(RR,now,com) == 1) return false; // wait for WHOIS
 		}
@@ -717,7 +717,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
 			const unsigned int numCapabilities = at<uint16_t>(p); p += 2;
 			for(unsigned int i=0;i<numCapabilities;++i) {
 				p += cap.deserialize(*this,p);
-				LockingPtr<Membership> m = peer->membership(cap.networkId(),true);
+				LockingPtr<Membership> m(peer->membership(cap.networkId(),true));
 				if (!m) return true; // sanity check
 				if (m->addCredential(RR,now,cap) == 1) return false; // wait for WHOIS
 			}
@@ -725,7 +725,7 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const S
 			const unsigned int numTags = at<uint16_t>(p); p += 2;
 			for(unsigned int i=0;i<numTags;++i) {
 				p += tag.deserialize(*this,p);
-				LockingPtr<Membership> m = peer->membership(tag.networkId(),true);
+				LockingPtr<Membership> m(peer->membership(tag.networkId(),true));
 				if (!m) return true; // sanity check
 				if (m->addCredential(RR,now,tag) == 1) return false; // wait for WHOIS
 			}
@@ -868,7 +868,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
 			if ((flags & 0x01) != 0) { // deprecated but still used by older peers
 				CertificateOfMembership com;
 				offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
-				LockingPtr<Membership> m = peer->membership(com.networkId(),true);
+				LockingPtr<Membership> m(peer->membership(com.networkId(),true));
 				if (m) m->addCredential(RR,RR->node->now(),com);
 			}
 

+ 5 - 0
node/Membership.hpp

@@ -114,6 +114,11 @@ public:
 		return sendCredentialsIfNeeded(RR,now,peer,nconf,(const uint32_t *)0,0,(const uint32_t *)0,0);
 	}
 
+	/**
+	 * @return This peer's COM if they have sent one
+	 */
+	inline const CertificateOfMembership &com() const { return _com; }
+
 	/**
 	 * @param nconf Network configuration
 	 * @param id Tag ID

+ 36 - 33
node/Network.cpp

@@ -29,6 +29,7 @@
 #include "Buffer.hpp"
 #include "NetworkController.hpp"
 #include "Node.hpp"
+#include "Peer.hpp"
 
 #include "../version.h"
 
@@ -384,17 +385,20 @@ bool Network::_isAllowed(const SharedPtr<Peer> &peer) const
 {
 	// Assumes _lock is locked
 	try {
-		if (!_config)
-			return false;
-		if (_config.isPublic())
-			return true;
-		return ((_config.com)&&(peer->networkMembershipCertificatesAgree(_id,_config.com)));
-	} catch (std::exception &exc) {
-		TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer->address().toString().c_str(),exc.what());
+		if (_config) {
+			if (_config.isPublic()) {
+				return true;
+			} else {
+				LockingPtr<Membership> m(peer->membership(_id,false));
+				if (m) {
+					return _config.com.agreesWith(m->com());
+				}
+			}
+		}
 	} catch ( ... ) {
-		TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer->address().toString().c_str());
+		TRACE("isAllowed() check failed for peer %s: unexpected exception: unexpected exception",peer->address().toString().c_str());
 	}
-	return false; // default position on any failure
+	return false;
 }
 
 class _MulticastAnnounceAll
@@ -405,13 +409,13 @@ public:
 		_controller(nw->controller()),
 		_network(nw),
 		_anchors(nw->config().anchors()),
-		_rootAddresses(renv->topology->rootAddresses())
+		_upstreamAddresses(renv->topology->upstreamAddresses())
 	{}
 	inline void operator()(Topology &t,const SharedPtr<Peer> &p)
 	{
-		if ( (_network->_isAllowed(p)) || // FIXME: this causes multicast LIKEs for public networks to get spammed
+		if ( (_network->_isAllowed(p)) || // FIXME: this causes multicast LIKEs for public networks to get spammed, which isn't terrible but is a bit stupid
 		     (p->address() == _controller) ||
-		     (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) ||
+		     (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),p->address()) != _upstreamAddresses.end()) ||
 				 (std::find(_anchors.begin(),_anchors.end(),p->address()) != _anchors.end()) ) {
 			peers.push_back(p);
 		}
@@ -422,7 +426,7 @@ private:
 	const Address _controller;
 	Network *const _network;
 	const std::vector<Address> _anchors;
-	const std::vector<Address> _rootAddresses;
+	const std::vector<Address> _upstreamAddresses;
 };
 void Network::_announceMulticastGroups()
 {
@@ -438,31 +442,30 @@ void Network::_announceMulticastGroupsTo(const SharedPtr<Peer> &peer,const std::
 {
 	// Assumes _lock is locked
 
-	// We push COMs ahead of MULTICAST_LIKE since they're used for access control -- a COM is a public
-	// credential so "over-sharing" isn't really an issue (and we only do so with roots).
-	if ((_config)&&(_config.com)&&(!_config.isPublic())&&(peer->needsOurNetworkMembershipCertificate(_id,RR->node->now(),true))) {
-		Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
-		_config.com.serialize(outp);
-		RR->sw->send(outp,true,0);
-	}
-
+	// Anyone we announce multicast groups to will need our COM to authenticate GATHER requests.
 	{
-		Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
+		LockingPtr<Membership> m(peer->membership(_id,false));
+		if (m) m->sendCredentialsIfNeeded(RR,RR->node->now(),*peer,_config);
+	}
 
-		for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
-			if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) {
-				RR->sw->send(outp,true,0);
-				outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
-			}
+	Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
 
-			// network ID, MAC, ADI
-			outp.append((uint64_t)_id);
-			mg->mac().appendTo(outp);
-			outp.append((uint32_t)mg->adi());
+	for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
+		if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) {
+			outp.compress();
+			RR->sw->send(outp,true,0);
+			outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
 		}
 
-		if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH)
-			RR->sw->send(outp,true,0);
+		// network ID, MAC, ADI
+		outp.append((uint64_t)_id);
+		mg->mac().appendTo(outp);
+		outp.append((uint32_t)mg->adi());
+	}
+
+	if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) {
+		outp.compress();
+		RR->sw->send(outp,true,0);
 	}
 }
 

+ 8 - 0
node/Topology.hpp

@@ -153,6 +153,14 @@ public:
 		return _rootAddresses;
 	}
 
+	/**
+	 * @return Vector of active upstream addresses (including roots)
+	 */
+	inline std::vector<Address> upstreamAddresses() const
+	{
+		return rootAddresses();
+	}
+
 	/**
 	 * @return Current World (copy)
 	 */