diff options
Diffstat (limited to 'node/Membership.cpp')
-rw-r--r-- | node/Membership.cpp | 164 |
1 files changed, 128 insertions, 36 deletions
diff --git a/node/Membership.cpp b/node/Membership.cpp index 8c6dab64..1eacb93d 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -37,6 +37,7 @@ Membership::Membership() : { for(unsigned int i=0;i<ZT_MAX_NETWORK_TAGS;++i) _remoteTags[i] = &(_tagMem[i]); for(unsigned int i=0;i<ZT_MAX_NETWORK_CAPABILITIES;++i) _remoteCaps[i] = &(_capMem[i]); + for(unsigned int i=0;i<ZT_MAX_CERTIFICATES_OF_OWNERSHIP;++i) _remoteCoos[i] = &(_cooMem[i]); } void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force) @@ -62,8 +63,19 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now } } + const CertificateOfOwnership *sendCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]; + unsigned int sendCooCount = 0; + for(unsigned int c=0;c<nconf.certificateOfOwnershipCount;++c) { + if ( (_localCoos[c].id != nconf.certificatesOfOwnership[c].id()) || ((now - _localCoos[c].lastPushed) >= ZT_CREDENTIAL_PUSH_EVERY) || (force) ) { + _localCoos[c].lastPushed = now; + _localCoos[c].id = nconf.certificatesOfOwnership[c].id(); + sendCoos[sendCooCount++] = &(nconf.certificatesOfOwnership[c]); + } + } + unsigned int tagPtr = 0; - while ((tagPtr < sendTagCount)||(sendCom)||(sendCap)) { + unsigned int cooPtr = 0; + while ((tagPtr < sendTagCount)||(cooPtr < sendCooCount)||(sendCom)||(sendCap)) { Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); if (sendCom) { @@ -82,7 +94,7 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now const unsigned int tagCountAt = outp.size(); outp.addSize(2); unsigned int thisPacketTagCount = 0; - while ((tagPtr < sendTagCount)&&((outp.size() + sizeof(Tag) + 32) < ZT_PROTO_MAX_PACKET_LENGTH)) { + while ((tagPtr < sendTagCount)&&((outp.size() + sizeof(Tag) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) { sendTags[tagPtr++]->serialize(outp); ++thisPacketTagCount; } @@ -91,6 +103,15 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now // No revocations, these propagate differently outp.append((uint16_t)0); + const unsigned int cooCountAt = outp.size(); + outp.addSize(2); + unsigned int thisPacketCooCount = 0; + while ((cooPtr < sendCooCount)&&((outp.size() + sizeof(CertificateOfOwnership) + 16) < ZT_PROTO_MAX_PACKET_LENGTH)) { + sendCoos[cooPtr++]->serialize(outp); + ++thisPacketCooCount; + } + outp.setAt(cooCountAt,(uint16_t)thisPacketCooCount); + outp.compress(); RR->sw->send(outp,true); } @@ -98,14 +119,14 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,const uint64_t now const Capability *Membership::getCapability(const NetworkConfig &nconf,const uint32_t id) const { - const _RemoteCapability *const *c = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)id,_RemoteCredentialSorter<_RemoteCapability>()); - return ( ((c != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*c)->id == (uint64_t)id)) ? ((((*c)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*c)->cap,**c))) ? &((*c)->cap) : (const Capability *)0) : (const Capability *)0); + const _RemoteCredential<Capability> *const *c = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)id,_RemoteCredentialComp<Capability>()); + return ( ((c != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*c)->id == (uint64_t)id)) ? ((((*c)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*c)->credential,**c))) ? &((*c)->credential) : (const Capability *)0) : (const Capability *)0); } const Tag *Membership::getTag(const NetworkConfig &nconf,const uint32_t id) const { - const _RemoteTag *const *t = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)id,_RemoteCredentialSorter<_RemoteTag>()); - return ( ((t != &(_remoteTags[ZT_MAX_NETWORK_CAPABILITIES]))&&((*t)->id == (uint64_t)id)) ? ((((*t)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*t)->tag,**t))) ? &((*t)->tag) : (const Tag *)0) : (const Tag *)0); + const _RemoteCredential<Tag> *const *t = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)id,_RemoteCredentialComp<Tag>()); + return ( ((t != &(_remoteTags[ZT_MAX_NETWORK_CAPABILITIES]))&&((*t)->id == (uint64_t)id)) ? ((((*t)->lastReceived)&&(_isCredentialTimestampValid(nconf,(*t)->credential,**t))) ? &((*t)->credential) : (const Tag *)0) : (const Tag *)0); } Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfMembership &com) @@ -141,14 +162,14 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Tag &tag) { - _RemoteTag *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)tag.id(),_RemoteCredentialSorter<_RemoteTag>()); - _RemoteTag *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)tag.id())) ? *htmp : (_RemoteTag *)0; + _RemoteCredential<Tag> *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)tag.id(),_RemoteCredentialComp<Tag>()); + _RemoteCredential<Tag> *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)tag.id())) ? *htmp : (_RemoteCredential<Tag> *)0; if (have) { - if ( (!_isCredentialTimestampValid(nconf,tag,*have)) || (have->tag.timestamp() > tag.timestamp()) ) { + if ( (!_isCredentialTimestampValid(nconf,tag,*have)) || (have->credential.timestamp() > tag.timestamp()) ) { TRACE("addCredential(Tag) for %s on %.16llx REJECTED (revoked or too old)",tag.issuedTo().toString().c_str(),tag.networkId()); return ADD_REJECTED; } - if (have->tag == tag) { + if (have->credential == tag) { TRACE("addCredential(Tag) for %s on %.16llx ACCEPTED (redundant)",tag.issuedTo().toString().c_str(),tag.networkId()); return ADD_ACCEPTED_REDUNDANT; } @@ -162,7 +183,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme TRACE("addCredential(Tag) for %s on %.16llx ACCEPTED (new)",tag.issuedTo().toString().c_str(),tag.networkId()); if (!have) have = _newTag(tag.id()); have->lastReceived = RR->node->now(); - have->tag = tag; + have->credential = tag; return ADD_ACCEPTED_NEW; case 1: return ADD_DEFERRED_FOR_WHOIS; @@ -171,14 +192,14 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const Capability &cap) { - _RemoteCapability *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)cap.id(),_RemoteCredentialSorter<_RemoteCapability>()); - _RemoteCapability *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)cap.id())) ? *htmp : (_RemoteCapability *)0; + _RemoteCredential<Capability> *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)cap.id(),_RemoteCredentialComp<Capability>()); + _RemoteCredential<Capability> *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)cap.id())) ? *htmp : (_RemoteCredential<Capability> *)0; if (have) { - if ( (!_isCredentialTimestampValid(nconf,cap,*have)) || (have->cap.timestamp() > cap.timestamp()) ) { + if ( (!_isCredentialTimestampValid(nconf,cap,*have)) || (have->credential.timestamp() > cap.timestamp()) ) { TRACE("addCredential(Capability) for %s on %.16llx REJECTED (revoked or too old)",cap.issuedTo().toString().c_str(),cap.networkId()); return ADD_REJECTED; } - if (have->cap == cap) { + if (have->credential == cap) { TRACE("addCredential(Capability) for %s on %.16llx ACCEPTED (redundant)",cap.issuedTo().toString().c_str(),cap.networkId()); return ADD_ACCEPTED_REDUNDANT; } @@ -192,7 +213,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme TRACE("addCredential(Capability) for %s on %.16llx ACCEPTED (new)",cap.issuedTo().toString().c_str(),cap.networkId()); if (!have) have = _newCapability(cap.id()); have->lastReceived = RR->node->now(); - have->cap = cap; + have->credential = cap; return ADD_ACCEPTED_NEW; case 1: return ADD_DEFERRED_FOR_WHOIS; @@ -209,13 +230,15 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme switch(rev.type()) { default: //case Revocation::CREDENTIAL_TYPE_ALL: - return ( (_revokeCom(rev)||_revokeCap(rev,now)||_revokeTag(rev,now)) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT ); + return ( (_revokeCom(rev)||_revokeCap(rev,now)||_revokeTag(rev,now)||_revokeCoo(rev,now)) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT ); case Revocation::CREDENTIAL_TYPE_COM: return (_revokeCom(rev) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT); case Revocation::CREDENTIAL_TYPE_CAPABILITY: return (_revokeCap(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT); case Revocation::CREDENTIAL_TYPE_TAG: return (_revokeTag(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT); + case Revocation::CREDENTIAL_TYPE_COO: + return (_revokeCoo(rev,now) ? ADD_ACCEPTED_NEW : ADD_ACCEPTED_REDUNDANT); } } case 1: @@ -223,9 +246,40 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme } } -Membership::_RemoteTag *Membership::_newTag(const uint64_t id) + +Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,const NetworkConfig &nconf,const CertificateOfOwnership &coo) +{ + _RemoteCredential<CertificateOfOwnership> *const *htmp = std::lower_bound(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]),(uint64_t)coo.id(),_RemoteCredentialComp<CertificateOfOwnership>()); + _RemoteCredential<CertificateOfOwnership> *have = ((htmp != &(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]))&&((*htmp)->id == (uint64_t)coo.id())) ? *htmp : (_RemoteCredential<CertificateOfOwnership> *)0; + if (have) { + if ( (!_isCredentialTimestampValid(nconf,coo,*have)) || (have->credential.timestamp() > coo.timestamp()) ) { + TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (revoked or too old)",cap.issuedTo().toString().c_str(),cap.networkId()); + return ADD_REJECTED; + } + if (have->credential == coo) { + TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx ACCEPTED (redundant)",cap.issuedTo().toString().c_str(),cap.networkId()); + return ADD_ACCEPTED_REDUNDANT; + } + } + + switch(coo.verify(RR)) { + default: + TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx REJECTED (invalid)",cap.issuedTo().toString().c_str(),cap.networkId()); + return ADD_REJECTED; + case 0: + TRACE("addCredential(CertificateOfOwnership) for %s on %.16llx ACCEPTED (new)",cap.issuedTo().toString().c_str(),cap.networkId()); + if (!have) have = _newCoo(coo.id()); + have->lastReceived = RR->node->now(); + have->credential = coo; + return ADD_ACCEPTED_NEW; + case 1: + return ADD_DEFERRED_FOR_WHOIS; + } +} + +Membership::_RemoteCredential<Tag> *Membership::_newTag(const uint64_t id) { - _RemoteTag *t = NULL; + _RemoteCredential<Tag> *t = NULL; uint64_t minlr = 0xffffffffffffffffULL; for(unsigned int i=0;i<ZT_MAX_NETWORK_TAGS;++i) { if (_remoteTags[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) { @@ -236,21 +290,21 @@ Membership::_RemoteTag *Membership::_newTag(const uint64_t id) minlr = _remoteTags[i]->lastReceived; } } - - if (t) { - t->id = id; - t->lastReceived = 0; - t->revocationThreshold = 0; - t->tag = Tag(); - } - - std::sort(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),_RemoteCredentialSorter<_RemoteTag>()); + + if (t) { + t->id = id; + t->lastReceived = 0; + t->revocationThreshold = 0; + t->credential = Tag(); + } + + std::sort(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS])); return t; } -Membership::_RemoteCapability *Membership::_newCapability(const uint64_t id) +Membership::_RemoteCredential<Capability> *Membership::_newCapability(const uint64_t id) { - _RemoteCapability *c = NULL; + _RemoteCredential<Capability> *c = NULL; uint64_t minlr = 0xffffffffffffffffULL; for(unsigned int i=0;i<ZT_MAX_NETWORK_CAPABILITIES;++i) { if (_remoteCaps[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) { @@ -266,10 +320,35 @@ Membership::_RemoteCapability *Membership::_newCapability(const uint64_t id) c->id = id; c->lastReceived = 0; c->revocationThreshold = 0; - c->cap = Capability(); + c->credential = Capability(); + } + + std::sort(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES])); + return c; +} + +Membership::_RemoteCredential<CertificateOfOwnership> *Membership::_newCoo(const uint64_t id) +{ + _RemoteCredential<CertificateOfOwnership> *c = NULL; + uint64_t minlr = 0xffffffffffffffffULL; + for(unsigned int i=0;i<ZT_MAX_CERTIFICATES_OF_OWNERSHIP;++i) { + if (_remoteCoos[i]->id == ZT_MEMBERSHIP_CRED_ID_UNUSED) { + c = _remoteCoos[i]; + break; + } else if (_remoteCoos[i]->lastReceived <= minlr) { + c = _remoteCoos[i]; + minlr = _remoteCoos[i]->lastReceived; + } + } + + if (c) { + c->id = id; + c->lastReceived = 0; + c->revocationThreshold = 0; + c->credential = CertificateOfOwnership(); } - std::sort(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),_RemoteCredentialSorter<_RemoteCapability>()); + std::sort(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP])); return c; } @@ -284,8 +363,8 @@ bool Membership::_revokeCom(const Revocation &rev) bool Membership::_revokeCap(const Revocation &rev,const uint64_t now) { - _RemoteCapability *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)rev.credentialId(),_RemoteCredentialSorter<_RemoteCapability>()); - _RemoteCapability *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCapability *)0; + _RemoteCredential<Capability> *const *htmp = std::lower_bound(&(_remoteCaps[0]),&(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]),(uint64_t)rev.credentialId(),_RemoteCredentialComp<Capability>()); + _RemoteCredential<Capability> *have = ((htmp != &(_remoteCaps[ZT_MAX_NETWORK_CAPABILITIES]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCredential<Capability> *)0; if (!have) have = _newCapability(rev.credentialId()); if (rev.threshold() > have->revocationThreshold) { have->lastReceived = now; @@ -297,8 +376,8 @@ bool Membership::_revokeCap(const Revocation &rev,const uint64_t now) bool Membership::_revokeTag(const Revocation &rev,const uint64_t now) { - _RemoteTag *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)rev.credentialId(),_RemoteCredentialSorter<_RemoteTag>()); - _RemoteTag *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteTag *)0; + _RemoteCredential<Tag> *const *htmp = std::lower_bound(&(_remoteTags[0]),&(_remoteTags[ZT_MAX_NETWORK_TAGS]),(uint64_t)rev.credentialId(),_RemoteCredentialComp<Tag>()); + _RemoteCredential<Tag> *have = ((htmp != &(_remoteTags[ZT_MAX_NETWORK_TAGS]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCredential<Tag> *)0; if (!have) have = _newTag(rev.credentialId()); if (rev.threshold() > have->revocationThreshold) { have->lastReceived = now; @@ -308,4 +387,17 @@ bool Membership::_revokeTag(const Revocation &rev,const uint64_t now) return false; } +bool Membership::_revokeCoo(const Revocation &rev,const uint64_t now) +{ + _RemoteCredential<CertificateOfOwnership> *const *htmp = std::lower_bound(&(_remoteCoos[0]),&(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]),(uint64_t)rev.credentialId(),_RemoteCredentialComp<CertificateOfOwnership>()); + _RemoteCredential<CertificateOfOwnership> *have = ((htmp != &(_remoteCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]))&&((*htmp)->id == (uint64_t)rev.credentialId())) ? *htmp : (_RemoteCredential<CertificateOfOwnership> *)0; + if (!have) have = _newCoo(rev.credentialId()); + if (rev.threshold() > have->revocationThreshold) { + have->lastReceived = now; + have->revocationThreshold = rev.threshold(); + return true; + } + return false; +} + } // namespace ZeroTier |