Browse Source

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

Adam Ierymenko 12 years ago
parent
commit
e4c5ad9f43
6 changed files with 95 additions and 18 deletions
  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) :
 	throw(std::runtime_error) :
 	_r(renv),
 	_r(renv),
 	_tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this),
 	_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)
 void Network::setConfiguration(const Network::Config &conf)
 {
 {
+	Mutex::Lock _l(_lock);
+	_configuration = conf;
+	_myCertificate = conf.certificateOfMembership();
 }
 }
 
 
 void Network::requestConfiguration()
 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)
 void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)
 {
 {
 	const RuntimeEnvironment *_r = ((Network *)arg)->_r;
 	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
 		 * @return Certificate of membership for this network, or empty cert if none
 		 */
 		 */
@@ -221,7 +245,7 @@ public:
 		 */
 		 */
 		inline bool isOpen() const
 		inline bool isOpen() const
 		{
 		{
-			return (get("isOpen","0") == "1");
+			return (get("isOpen") == "1");
 		}
 		}
 
 
 		/**
 		/**
@@ -304,8 +328,12 @@ public:
 	inline bool isOpen() const
 	inline bool isOpen() const
 		throw()
 		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();
 	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:
 private:
 	static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
 	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;
 	EthernetTap _tap;
 	std::set<MulticastGroup> _multicastGroups;
 	std::set<MulticastGroup> _multicastGroups;
-
+	std::map<Address,Certificate> _membershipCertificates;
+	Config _configuration;
+	Certificate _myCertificate;
+	uint64_t _lastCertificateUpdate;
 	uint64_t _id;
 	uint64_t _id;
-	bool _isOpen;
-
 	Mutex _lock;
 	Mutex _lock;
 
 
 	AtomicCounter __refCount;
 	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_COLLISION: return "IDENTITY_COLLISION";
 		case ERROR_IDENTITY_INVALID: return "IDENTITY_INVALID";
 		case ERROR_IDENTITY_INVALID: return "IDENTITY_INVALID";
 		case ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION";
 		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)";
 	return "(unknown)";
 }
 }

+ 1 - 4
node/Packet.hpp

@@ -537,10 +537,7 @@ public:
 		ERROR_UNSUPPORTED_OPERATION = 6,
 		ERROR_UNSUPPORTED_OPERATION = 6,
 
 
 		/* Message to private network rejected -- no unexpired certificate on file */
 		/* 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);
 		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) {
 		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) {
 				for(std::set<MulticastGroup>::iterator mg(nwmgs->second.begin());mg!=nwmgs->second.end();++mg) {
 					if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
 					if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
 						send(outp,true);
 						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];
 	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);
 	Buffer<ZT_KISSDB_VALUE_SIZE> b(ZT_KISSDB_VALUE_SIZE);
 	_dbm_m.lock();
 	_dbm_m.lock();
@@ -309,7 +309,7 @@ void Topology::main()
 						if (p->second->getAndResetDirty()) {
 						if (p->second->getAndResetDirty()) {
 							try {
 							try {
 								uint64_t atmp[ZT_ADDRESS_LENGTH];
 								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;
 								Buffer<ZT_PEER_MAX_SERIALIZED_LENGTH> b;
 								p->second->serialize(b);
 								p->second->serialize(b);
 								b.zeroUnused();
 								b.zeroUnused();
@@ -340,7 +340,7 @@ void Topology::_reallyAddPeer(const SharedPtr<Peer> &p)
 	}
 	}
 	try {
 	try {
 		uint64_t atmp[ZT_ADDRESS_LENGTH];
 		uint64_t atmp[ZT_ADDRESS_LENGTH];
-		p->address().copyTo(atmp);
+		p->address().copyTo(atmp,ZT_ADDRESS_LENGTH);
 		Buffer<ZT_PEER_MAX_SERIALIZED_LENGTH> b;
 		Buffer<ZT_PEER_MAX_SERIALIZED_LENGTH> b;
 		p->serialize(b);
 		p->serialize(b);
 		b.zeroUnused();
 		b.zeroUnused();