mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
.
This commit is contained in:
parent
5cf410490e
commit
56febbf2ba
5 changed files with 29 additions and 103 deletions
|
@ -21,19 +21,29 @@
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
|
#include "Network.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
int Capability::verify(const RuntimeEnvironment *RR) const
|
int Capability::verify(const RuntimeEnvironment *RR) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH))
|
||||||
|
return -1;
|
||||||
|
|
||||||
Buffer<(sizeof(Capability) * 2)> tmp;
|
Buffer<(sizeof(Capability) * 2)> tmp;
|
||||||
this->serialize(tmp,true);
|
this->serialize(tmp,true);
|
||||||
for(unsigned int c=0;c<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++c) {
|
for(unsigned int c=0;c<_maxCustodyChainLength;++c) {
|
||||||
if (!_custody[c].to)
|
if (c == 0) {
|
||||||
return ((c == 0) ? -1 : 0);
|
if ((!_custody[c].to)||(!_custody[c].from)||(_custody[c].from != Network::controllerFor(_nwid)))
|
||||||
if (!_custody[c].from)
|
return -1; // the first entry must be present and from the network's controller
|
||||||
return -1;
|
} else {
|
||||||
|
if (!_custody[c].to)
|
||||||
|
return 0; // all previous entries were valid, so we are valid
|
||||||
|
else if ((!_custody[c].from)||(_custody[c].from != _custody[c-1].to))
|
||||||
|
return -1; // otherwise if we have another entry it must be from the previous holder in the chain
|
||||||
|
}
|
||||||
|
|
||||||
const Identity id(RR->topology->getIdentity(_custody[c].from));
|
const Identity id(RR->topology->getIdentity(_custody[c].from));
|
||||||
if (id) {
|
if (id) {
|
||||||
if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature))
|
if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature))
|
||||||
|
@ -44,9 +54,8 @@ int Capability::verify(const RuntimeEnvironment *RR) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "RuntimeEnvironment.hpp"
|
#include "RuntimeEnvironment.hpp"
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
|
#include "Network.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
@ -208,7 +209,7 @@ bool CertificateOfMembership::sign(const Identity &with)
|
||||||
|
|
||||||
int CertificateOfMembership::verify(const RuntimeEnvironment *RR) const
|
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;
|
return -1;
|
||||||
|
|
||||||
const Identity id(RR->topology->getIdentity(_signedBy));
|
const Identity id(RR->topology->getIdentity(_signedBy));
|
||||||
|
|
|
@ -80,8 +80,8 @@ bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("unable to send credentials due to unexpected exception");
|
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)
|
int Membership::addCredential(const RuntimeEnvironment *RR,const uint64_t now,const CertificateOfMembership &com)
|
||||||
|
|
|
@ -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<Peer> 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)
|
void Peer::clean(uint64_t now)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -460,24 +386,13 @@ void Peer::clean(uint64_t now)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_networkComs_m);
|
Mutex::Lock _l(_memberships_m);
|
||||||
{
|
uint64_t *nwid = (uint64_t *)0;
|
||||||
uint64_t *k = (uint64_t *)0;
|
Membership *m = (Membership *)0;
|
||||||
_NetworkCom *v = (_NetworkCom *)0;
|
Hashtable<uint64_t,Membership>::Iterator i(_memberships);
|
||||||
Hashtable< uint64_t,_NetworkCom >::Iterator i(_networkComs);
|
while (i.next(nwid,m)) {
|
||||||
while (i.next(k,v)) {
|
if ((now - m->clean(now)) > ZT_MEMBERSHIP_EXPIRATION_TIME)
|
||||||
if ( (!RR->node->belongsToNetwork(*k)) && ((now - v->ts) >= ZT_PEER_NETWORK_COM_EXPIRATION) )
|
_memberships.erase(*nwid);
|
||||||
_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,13 @@
|
||||||
#include "Identity.hpp"
|
#include "Identity.hpp"
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
|
#include "Network.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
int Tag::verify(const RuntimeEnvironment *RR) const
|
int Tag::verify(const RuntimeEnvironment *RR) const
|
||||||
{
|
{
|
||||||
if (!_signedBy)
|
if ((!_signedBy)||(_signedBy != Network::controllerFor(_nwid)))
|
||||||
return -1;
|
return -1;
|
||||||
const Identity id(RR->topology->getIdentity(_signedBy));
|
const Identity id(RR->topology->getIdentity(_signedBy));
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue