diff --git a/node/Capability.cpp b/node/Capability.cpp index 07eb41a97..ee798a6cc 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -21,19 +21,29 @@ #include "Identity.hpp" #include "Topology.hpp" #include "Switch.hpp" +#include "Network.hpp" namespace ZeroTier { int Capability::verify(const RuntimeEnvironment *RR) const { try { + if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) + return -1; + Buffer<(sizeof(Capability) * 2)> tmp; this->serialize(tmp,true); - for(unsigned int c=0;ctopology->getIdentity(_custody[c].from)); if (id) { if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature)) @@ -44,9 +54,8 @@ int Capability::verify(const RuntimeEnvironment *RR) const } } return 0; - } catch ( ... ) { - return -1; - } + } catch ( ... ) {} + return -1; } } // namespace ZeroTier diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 0c36aa459..43efcd202 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -20,6 +20,7 @@ #include "RuntimeEnvironment.hpp" #include "Topology.hpp" #include "Switch.hpp" +#include "Network.hpp" namespace ZeroTier { @@ -208,7 +209,7 @@ bool CertificateOfMembership::sign(const Identity &with) int CertificateOfMembership::verify(const RuntimeEnvironment *RR) const { - if ((!_signedBy)||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) + if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) return -1; const Identity id(RR->topology->getIdentity(_signedBy)); diff --git a/node/Membership.cpp b/node/Membership.cpp index 91cf693a5..a1a8eb8a1 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -80,8 +80,8 @@ bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint } } catch ( ... ) { TRACE("unable to send credentials due to unexpected exception"); - return false; } + return false; } int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const CertificateOfMembership &com) diff --git a/node/Peer.cpp b/node/Peer.cpp index cc5810043..a994c4b24 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -371,80 +371,6 @@ void Peer::getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) } } -bool Peer::networkMembershipCertificatesAgree(uint64_t nwid,const CertificateOfMembership &com) const -{ - Mutex::Lock _l(_networkComs_m); - const _NetworkCom *ourCom = _networkComs.get(nwid); - if (ourCom) - return ourCom->com.agreesWith(com); - return false; -} - -bool Peer::validateAndSetNetworkMembershipCertificate(uint64_t nwid,const CertificateOfMembership &com) -{ - // Sanity checks - if ((!com)||(com.issuedTo() != _id.address())) - return false; - - // Return true if we already have this *exact* COM - { - Mutex::Lock _l(_networkComs_m); - _NetworkCom *ourCom = _networkComs.get(nwid); - if ((ourCom)&&(ourCom->com == com)) - return true; - } - - // Check signature, log and return if cert is invalid - if (com.signedBy() != Network::controllerFor(nwid)) { - TRACE("rejected network membership certificate for %.16llx signed by %s: signer not a controller of this network",(unsigned long long)nwid,com.signedBy().toString().c_str()); - return false; // invalid signer - } - - if (com.signedBy() == RR->identity.address()) { - - // We are the controller: RR->identity.address() == controller() == cert.signedBy() - // So, verify that we signed th cert ourself - if (!com.verify(RR->identity)) { - TRACE("rejected network membership certificate for %.16llx self signed by %s: signature check failed",(unsigned long long)nwid,com.signedBy().toString().c_str()); - return false; // invalid signature - } - - } else { - - SharedPtr signer(RR->topology->getPeer(com.signedBy())); - - if (!signer) { - // This would be rather odd, since this is our controller... could happen - // if we get packets before we've gotten config. - RR->sw->requestWhois(com.signedBy()); - return false; // signer unknown - } - - if (!com.verify(signer->identity())) { - TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)nwid,com.signedBy().toString().c_str()); - return false; // invalid signature - } - } - - // If we made it past all those checks, add or update cert in our cert info store - { - Mutex::Lock _l(_networkComs_m); - _networkComs.set(nwid,_NetworkCom(RR->node->now(),com)); - } - - return true; -} - -bool Peer::needsOurNetworkMembershipCertificate(uint64_t nwid,uint64_t now,bool updateLastPushedTime) -{ - Mutex::Lock _l(_networkComs_m); - uint64_t &lastPushed = _lastPushedComs[nwid]; - const uint64_t tmp = lastPushed; - if (updateLastPushedTime) - lastPushed = now; - return ((now - tmp) >= (ZT_NETWORK_AUTOCONF_DELAY / 3)); -} - void Peer::clean(uint64_t now) { { @@ -460,24 +386,13 @@ void Peer::clean(uint64_t now) } { - Mutex::Lock _l(_networkComs_m); - { - uint64_t *k = (uint64_t *)0; - _NetworkCom *v = (_NetworkCom *)0; - Hashtable< uint64_t,_NetworkCom >::Iterator i(_networkComs); - while (i.next(k,v)) { - if ( (!RR->node->belongsToNetwork(*k)) && ((now - v->ts) >= ZT_PEER_NETWORK_COM_EXPIRATION) ) - _networkComs.erase(*k); - } - } - { - uint64_t *k = (uint64_t *)0; - uint64_t *v = (uint64_t *)0; - Hashtable< uint64_t,uint64_t >::Iterator i(_lastPushedComs); - while (i.next(k,v)) { - if ((now - *v) > (ZT_NETWORK_AUTOCONF_DELAY * 2)) - _lastPushedComs.erase(*k); - } + Mutex::Lock _l(_memberships_m); + uint64_t *nwid = (uint64_t *)0; + Membership *m = (Membership *)0; + Hashtable::Iterator i(_memberships); + while (i.next(nwid,m)) { + if ((now - m->clean(now)) > ZT_MEMBERSHIP_EXPIRATION_TIME) + _memberships.erase(*nwid); } } } diff --git a/node/Tag.cpp b/node/Tag.cpp index 1ad17251c..352ecde8e 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -21,12 +21,13 @@ #include "Identity.hpp" #include "Topology.hpp" #include "Switch.hpp" +#include "Network.hpp" namespace ZeroTier { int Tag::verify(const RuntimeEnvironment *RR) const { - if (!_signedBy) + if ((!_signedBy)||(_signedBy != Network::controllerFor(_nwid))) return -1; const Identity id(RR->topology->getIdentity(_signedBy)); if (!id) {