فهرست منبع

More work on network membership certs, and it builds now. Still in heavy development.

Adam Ierymenko 12 سال پیش
والد
کامیت
e4c5ad9f43
6فایلهای تغییر یافته به همراه95 افزوده شده و 18 حذف شده
  1. 33 2
      node/Network.cpp
  2. 56 6
      node/Network.hpp
  3. 1 2
      node/Packet.cpp
  4. 1 4
      node/Packet.hpp
  5. 1 1
      node/Switch.cpp
  6. 3 3
      node/Topology.cpp

+ 33 - 2
node/Network.cpp

@@ -103,8 +103,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
 	throw(std::runtime_error) :
 	_r(renv),
 	_tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this),
-	_id(id),
-	_isOpen(false)
+	_id(id)
 {
 }
 
@@ -114,12 +113,44 @@ Network::~Network()
 
 void Network::setConfiguration(const Network::Config &conf)
 {
+	Mutex::Lock _l(_lock);
+	_configuration = conf;
+	_myCertificate = conf.certificateOfMembership();
 }
 
 void Network::requestConfiguration()
 {
 }
 
+bool Network::isAllowed(const Address &peer) const
+{
+	try {
+		Mutex::Lock _l(_lock);
+		if (_configuration.isOpen())
+			return true;
+		std::map<Address,Certificate>::const_iterator pc(_membershipCertificates.find(peer));
+		if (pc == _membershipCertificates.end())
+			return false;
+		return _myCertificate.qualifyMembership(pc->second);
+	} catch (std::exception &exc) {
+		TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer.toString().c_str(),exc.what());
+		return false;
+	} catch ( ... ) {
+		TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer.toString().c_str());
+		return false;
+	}
+}
+
+void Network::clean()
+{
+	Mutex::Lock _l(_lock);
+	for(std::map<Address,Certificate>::iterator i=(_membershipCertificates.begin());i!=_membershipCertificates.end();) {
+		if (_myCertificate.qualifyMembership(i->second))
+			++i;
+		else _membershipCertificates.erase(i++);
+	}
+}
+
 void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)
 {
 	const RuntimeEnvironment *_r = ((Network *)arg)->_r;

+ 56 - 6
node/Network.hpp

@@ -208,6 +208,30 @@ public:
 		{
 		}
 
+		inline void setNetworkId(uint64_t id)
+		{
+			char buf[32];
+			sprintf(buf,"%llu",id);
+			(*this)["nwid"] = buf;
+		}
+
+		inline uint64_t networkId() const
+			throw(std::invalid_argument)
+		{
+			return strtoull(get("nwid").c_str(),(char **)0,10);
+		}
+
+		inline void setPeerAddress(Address &a)
+		{
+			(*this)["peer"] = a.toString();
+		}
+
+		inline Address peerAddress() const
+			throw(std::invalid_argument)
+		{
+			return Address(get("peer"));
+		}
+
 		/**
 		 * @return Certificate of membership for this network, or empty cert if none
 		 */
@@ -221,7 +245,7 @@ public:
 		 */
 		inline bool isOpen() const
 		{
-			return (get("isOpen","0") == "1");
+			return (get("isOpen") == "1");
 		}
 
 		/**
@@ -304,8 +328,12 @@ public:
 	inline bool isOpen() const
 		throw()
 	{
-		Mutex::Lock _l(_lock);
-		return _isOpen;
+		try {
+			Mutex::Lock _l(_lock);
+			return _configuration.isOpen();
+		} catch ( ... ) {
+			return false;
+		}
 	}
 
 	/**
@@ -343,6 +371,27 @@ public:
 	 */
 	void requestConfiguration();
 
+	/**
+	 * Add or update a peer's membership certificate
+	 *
+	 * The certificate must already have been validated via signature checking.
+	 *
+	 * @param peer Peer that owns certificate
+	 * @param cert Certificate itself
+	 */
+	inline void addMembershipCertificate(const Address &peer,const Certificate &cert)
+	{
+		Mutex::Lock _l(_lock);
+		_membershipCertificates[peer] = cert;
+	}
+
+	bool isAllowed(const Address &peer) const;
+
+	/**
+	 * Perform periodic database cleaning such as removing expired membership certificates
+	 */
+	void clean();
+
 private:
 	static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
 
@@ -350,10 +399,11 @@ private:
 
 	EthernetTap _tap;
 	std::set<MulticastGroup> _multicastGroups;
-
+	std::map<Address,Certificate> _membershipCertificates;
+	Config _configuration;
+	Certificate _myCertificate;
+	uint64_t _lastCertificateUpdate;
 	uint64_t _id;
-	bool _isOpen;
-
 	Mutex _lock;
 
 	AtomicCounter __refCount;

+ 1 - 2
node/Packet.cpp

@@ -60,8 +60,7 @@ const char *Packet::errorString(ErrorCode e)
 		case ERROR_IDENTITY_COLLISION: return "IDENTITY_COLLISION";
 		case ERROR_IDENTITY_INVALID: return "IDENTITY_INVALID";
 		case ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION";
-		case ERROR_NO_MEMBER_CERTIFICATE_ON_FILE: return "NO_MEMBER_CERTIFICATE_ON_FILE";
-		case ERROR_MEMBER_CERTIFICATE_UNQUALIFIED: return "MEMBER_CERTIFICATE_UNQUALIFIED";
+		case ERROR_NO_MEMBER_CERTIFICATE: return "NO_MEMBER_CERTIFICATE";
 	}
 	return "(unknown)";
 }

+ 1 - 4
node/Packet.hpp

@@ -537,10 +537,7 @@ public:
 		ERROR_UNSUPPORTED_OPERATION = 6,
 
 		/* Message to private network rejected -- no unexpired certificate on file */
-		ERROR_NO_MEMBER_CERTIFICATE_ON_FILE = 7,
-
-		/* Membership certificate no longer qualified for membership in network */
-		ERROR_MEMBER_CERTIFICATE_UNQUALIFIED = 8
+		ERROR_NO_MEMBER_CERTIFICATE = 7
 	};
 
 	/**

+ 1 - 1
node/Switch.cpp

@@ -386,7 +386,7 @@ void Switch::announceMulticastGroups(const std::map< SharedPtr<Network>,std::set
 		Packet outp((*p)->address(),_r->identity.address(),Packet::VERB_MULTICAST_LIKE);
 
 		for(std::map< SharedPtr<Network>,std::set<MulticastGroup> >::const_iterator nwmgs(allMemberships.begin());nwmgs!=allMemberships.end();++nwmgs) {
-			if ((nwmgs->first->open())||(_r->topology->isSupernode((*p)->address()))||(nwmgs->first->isMember((*p)->address()))) {
+			if ((_r->topology->isSupernode((*p)->address()))||(nwmgs->first->isAllowed((*p)->address()))) {
 				for(std::set<MulticastGroup>::iterator mg(nwmgs->second.begin());mg!=nwmgs->second.end();++mg) {
 					if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
 						send(outp,true);

+ 3 - 3
node/Topology.cpp

@@ -133,7 +133,7 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta)
 	}
 
 	unsigned char ztatmp[ZT_ADDRESS_LENGTH];
-	zta.copyTo(ztatmp);
+	zta.copyTo(ztatmp,ZT_ADDRESS_LENGTH);
 
 	Buffer<ZT_KISSDB_VALUE_SIZE> b(ZT_KISSDB_VALUE_SIZE);
 	_dbm_m.lock();
@@ -309,7 +309,7 @@ void Topology::main()
 						if (p->second->getAndResetDirty()) {
 							try {
 								uint64_t atmp[ZT_ADDRESS_LENGTH];
-								p->second->identity().address().copyTo(atmp);
+								p->second->identity().address().copyTo(atmp,ZT_ADDRESS_LENGTH);
 								Buffer<ZT_PEER_MAX_SERIALIZED_LENGTH> b;
 								p->second->serialize(b);
 								b.zeroUnused();
@@ -340,7 +340,7 @@ void Topology::_reallyAddPeer(const SharedPtr<Peer> &p)
 	}
 	try {
 		uint64_t atmp[ZT_ADDRESS_LENGTH];
-		p->address().copyTo(atmp);
+		p->address().copyTo(atmp,ZT_ADDRESS_LENGTH);
 		Buffer<ZT_PEER_MAX_SERIALIZED_LENGTH> b;
 		p->serialize(b);
 		b.zeroUnused();