diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/Capability.hpp | 12 | ||||
-rw-r--r-- | node/CertificateOfMembership.hpp | 49 | ||||
-rw-r--r-- | node/Membership.cpp | 2 | ||||
-rw-r--r-- | node/Membership.hpp | 10 | ||||
-rw-r--r-- | node/Network.cpp | 14 | ||||
-rw-r--r-- | node/NetworkConfig.cpp | 2 | ||||
-rw-r--r-- | node/NetworkConfig.hpp | 20 | ||||
-rw-r--r-- | node/Tag.hpp | 8 |
8 files changed, 49 insertions, 68 deletions
diff --git a/node/Capability.hpp b/node/Capability.hpp index 689a2c6a..b0620891 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -72,17 +72,15 @@ public: * @param id Capability ID * @param nwid Network ID * @param ts Timestamp (at controller) - * @param expiration Expiration relative to network config timestamp * @param mccl Maximum custody chain length (1 to create non-transferrable capability) * @param rules Network flow rules for this capability * @param ruleCount Number of flow rules */ - Capability(uint32_t id,uint64_t nwid,uint64_t ts,uint64_t expiration,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) + Capability(uint32_t id,uint64_t nwid,uint64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) { memset(this,0,sizeof(Capability)); _nwid = nwid; _ts = ts; - _expiration = expiration; _id = id; _maxCustodyChainLength = (mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1; _ruleCount = (ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES; @@ -111,11 +109,6 @@ public: inline uint64_t networkId() const { return _nwid; } /** - * @return Expiration time relative to network config timestamp - */ - inline uint64_t expiration() const { return _expiration; } - - /** * @return Timestamp */ inline uint64_t timestamp() const { return _ts; } @@ -343,7 +336,6 @@ public: // These are the same between Tag and Capability b.append(_nwid); b.append(_ts); - b.append(_expiration); b.append(_id); b.append((uint16_t)_ruleCount); @@ -381,7 +373,6 @@ public: // These are the same between Tag and Capability _nwid = b.template at<uint64_t>(p); p += 8; _ts = b.template at<uint64_t>(p); p += 8; - _expiration = b.template at<uint64_t>(p); p += 8; _id = b.template at<uint32_t>(p); p += 4; const unsigned int rc = b.template at<uint16_t>(p); p += 2; @@ -420,7 +411,6 @@ public: private: uint64_t _nwid; uint64_t _ts; - uint64_t _expiration; uint32_t _id; unsigned int _maxCustodyChainLength; diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index a04f8255..304111d6 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -35,11 +35,6 @@ /** * Default window of time for certificate agreement - * - * Right now we use time for 'revision' so this is the maximum time divergence - * between two certs for them to agree. It comes out to five minutes, which - * gives a lot of margin for error if the controller hiccups or its clock - * drifts but causes de-authorized peers to fall off fast enough. */ #define ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA (ZT_NETWORK_AUTOCONF_DELAY * 5) @@ -93,25 +88,17 @@ public: enum ReservedId { /** - * Revision number of certificate - * - * Certificates may differ in revision number by a designated max - * delta. Differences wider than this cause certificates not to agree. + * Timestamp of certificate */ - COM_RESERVED_ID_REVISION = 0, + COM_RESERVED_ID_TIMESTAMP = 0, /** * Network ID for which certificate was issued - * - * maxDelta here is zero, since this must match. */ COM_RESERVED_ID_NETWORK_ID = 1, /** * ZeroTier address to whom certificate was issued - * - * maxDelta will be 0xffffffffffffffff here since it's permitted to differ - * from peers obviously. */ COM_RESERVED_ID_ISSUED_TO = 2 }; @@ -132,16 +119,16 @@ public: /** * Create from required fields common to all networks * - * @param revision Revision number of certificate + * @param timestamp Timestamp of certificate * @param timestampMaxDelta Maximum variation between timestamps on this net * @param nwid Network ID * @param issuedTo Certificate recipient */ - CertificateOfMembership(uint64_t revision,uint64_t revisionMaxDelta,uint64_t nwid,const Address &issuedTo) + CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo) { - _qualifiers[0].id = COM_RESERVED_ID_REVISION; - _qualifiers[0].value = revision; - _qualifiers[0].maxDelta = revisionMaxDelta; + _qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP; + _qualifiers[0].value = timestamp; + _qualifiers[0].maxDelta = timestampMaxDelta; _qualifiers[1].id = COM_RESERVED_ID_NETWORK_ID; _qualifiers[1].value = nwid; _qualifiers[1].maxDelta = 0; @@ -176,27 +163,15 @@ public: inline operator bool() const throw() { return (_qualifierCount != 0); } /** - * @return Maximum delta for mandatory revision field or 0 if field missing + * @return Timestamp for this cert and maximum delta for timestamp */ - inline uint64_t revisionMaxDelta() const + inline std::pair<uint64_t,uint64_t> timestamp() const { for(unsigned int i=0;i<_qualifierCount;++i) { - if (_qualifiers[i].id == COM_RESERVED_ID_REVISION) - return _qualifiers[i].maxDelta; + if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP) + return std::pair<uint64_t,uint64_t>(_qualifiers[i].value,_qualifiers[i].maxDelta); } - return 0ULL; - } - - /** - * @return Revision number for this cert - */ - inline uint64_t revision() const - { - for(unsigned int i=0;i<_qualifierCount;++i) { - if (_qualifiers[i].id == COM_RESERVED_ID_REVISION) - return _qualifiers[i].value; - } - return 0ULL; + return std::pair<uint64_t,uint64_t>(0ULL,0ULL); } /** diff --git a/node/Membership.cpp b/node/Membership.cpp index dbba7f0d..969032ff 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -86,7 +86,7 @@ int Membership::addCredential(const RuntimeEnvironment *RR,const CertificateOfMe if (_com == com) return 0; const int vr = com.verify(RR); - if ((vr == 0)&&(com.revision() > _com.revision())) + if ((vr == 0)&&(com.timestamp().first > _com.timestamp().first)) _com = com; return vr; } diff --git a/node/Membership.hpp b/node/Membership.hpp index e9f9d488..92bd7ebf 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -84,10 +84,10 @@ public: { } - inline const Capability *next() + inline const Capability *next(const NetworkConfig &nconf) { while (_i != _e) { - if (_i->second.lastReceived) + if ((_i->second.lastReceived)&&(nconf.isCredentialTimestampValid(_i->second.cap))) return &((_i++)->second.cap); else ++_i; } @@ -137,7 +137,7 @@ public: inline const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const { const TState *t = _tags.get(id); - return ((t) ? (((t->lastReceived != 0)&&(t->tag.expiration() < nconf.timestamp)) ? &(t->tag) : (const Tag *)0) : (const Tag *)0); + return ((t) ? (((t->lastReceived != 0)&&(nconf.isCredentialTimestampValid(t->tag))) ? &(t->tag) : (const Tag *)0) : (const Tag *)0); } /** @@ -154,7 +154,7 @@ public: TState *ts = (TState *)0; Hashtable<uint32_t,TState>::Iterator i(const_cast<Membership *>(this)->_tags); while (i.next(id,ts)) { - if ((ts->lastReceived)&&(ts->tag.expiration() < nconf.timestamp)) { + if ((ts->lastReceived)&&(nconf.isCredentialTimestampValid(ts->tag))) { if (n >= maxTags) return n; ids[n] = *id; @@ -172,7 +172,7 @@ public: inline const Capability *getCapability(const NetworkConfig &nconf,const uint32_t id) const { std::map<uint32_t,CState>::const_iterator c(_caps.find(id)); - return ((c != _caps.end()) ? (((c->second.lastReceived != 0)&&(c->second.cap.expiration() < nconf.timestamp)) ? &(c->second.cap) : (const Capability *)0) : (const Capability *)0); + return ((c != _caps.end()) ? (((c->second.lastReceived != 0)&&(nconf.isCredentialTimestampValid(c->second.cap))) ? &(c->second.cap) : (const Capability *)0) : (const Capability *)0); } /** diff --git a/node/Network.cpp b/node/Network.cpp index 0bd4ea55..7adb6aeb 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -102,7 +102,7 @@ static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsig // 0 == no match, -1 == match/drop, 1 == match/accept static int _doZtFilter( const RuntimeEnvironment *RR, - const uint64_t nwid, + const NetworkConfig &nconf, const bool inbound, const Address &ztSource, const Address &ztDest, @@ -155,7 +155,7 @@ static int _doZtFilter( case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_REDIRECT: { Packet outp(Address(rules[rn].v.zt),RR->identity.address(),Packet::VERB_EXT_FRAME); - outp.append(nwid); + outp.append(nconf.networkId); outp.append((uint8_t)((rt == ZT_NETWORK_RULE_ACTION_REDIRECT) ? 0x04 : 0x02)); macDest.appendTo(outp); macSource.appendTo(outp); @@ -481,7 +481,7 @@ bool Network::filterOutgoingPacket( Membership &m = _memberships[ztDest]; const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS); - switch(_doZtFilter(RR,_id,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { + switch(_doZtFilter(RR,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { case -1: return false; case 1: @@ -491,7 +491,7 @@ bool Network::filterOutgoingPacket( for(unsigned int c=0;c<_config.capabilityCount;++c) { relevantLocalTagCount = 0; - switch (_doZtFilter(RR,_id,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { + switch (_doZtFilter(RR,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { case -1: return false; case 1: @@ -523,7 +523,7 @@ bool Network::filterIncomingPacket( Membership &m = _memberships[ztDest]; const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS); - switch (_doZtFilter(RR,_id,true,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { + switch (_doZtFilter(RR,_config,true,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { case -1: return false; case 1: @@ -532,9 +532,9 @@ bool Network::filterIncomingPacket( Membership::CapabilityIterator mci(m); const Capability *c; - while ((c = mci.next())) { + while ((c = mci.next(_config))) { relevantLocalTagCount = 0; - switch(_doZtFilter(RR,_id,false,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { + switch(_doZtFilter(RR,_config,false,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) { case -1: return false; case 1: diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index a4fddf40..14ebb209 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -37,6 +37,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,this->networkId)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp)) return false; + if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TTL,this->credentialTimeToLive)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) return false; @@ -202,6 +203,7 @@ bool NetworkConfig::fromDictionary(const Identity &controllerId,Dictionary<ZT_NE return false; } this->timestamp = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,0); + this->credentialTimeToLive = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TTL,0); this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION,0); this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0); if (!this->issuedTo) { diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 25e0ccaf..97e9287a 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -125,6 +125,8 @@ namespace ZeroTier { #define ZT_NETWORKCONFIG_DICT_KEY_TYPE "t" // text #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" +// credential time to live in ms +#define ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TTL "cttl" // binary serialized certificate of membership #define ZT_NETWORKCONFIG_DICT_KEY_COM "C" // specialists (binary array of uint64_t) @@ -367,11 +369,24 @@ public: return (Tag *)0; } + /** + * Check whether a capability or tag is expired + * + * @param cred Credential to check -- must have timestamp() accessor method + * @return True if credential is NOT expired + */ + template<typename C> + inline bool isCredentialTimestampValid(const C &cred) const + { + return ( (cred.timestamp() >= timestamp) || ((timestamp - cred.timestamp()) <= credentialTimeToLive) ); + } + /* inline void dump() const { printf("networkId==%.16llx\n",networkId); printf("timestamp==%llu\n",timestamp); + printf("credentialTimeToLive==%llu\n",credentialTimeToLive); printf("revision==%llu\n",revision); printf("issuedTo==%.10llx\n",issuedTo.toInt()); printf("multicastLimit==%u\n",multicastLimit); @@ -406,6 +421,11 @@ public: uint64_t timestamp; /** + * TTL for capabilities and tags + */ + uint64_t credentialTimeToLive; + + /** * Controller-side revision counter for this configuration */ uint64_t revision; diff --git a/node/Tag.hpp b/node/Tag.hpp index bb019474..14cc3a5d 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -62,15 +62,13 @@ public: /** * @param nwid Network ID * @param ts Timestamp - * @param expiration Tag expiration relative to network config timestamp * @param issuedTo Address to which this tag was issued * @param id Tag ID * @param value Tag value */ - Tag(const uint64_t nwid,const uint64_t ts,const uint64_t expiration,const Address &issuedTo,const uint32_t id,const uint32_t value) : + Tag(const uint64_t nwid,const uint64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) : _nwid(nwid), _ts(ts), - _expiration(expiration), _id(id), _value(value), _issuedTo(issuedTo), @@ -79,7 +77,6 @@ public: } inline uint64_t networkId() const { return _nwid; } - inline uint64_t expiration() const { return _expiration; } inline uint64_t timestamp() const { return _ts; } inline uint32_t id() const { return _id; } inline const uint32_t &value() const { return _value; } @@ -120,7 +117,6 @@ public: // These are the same between Tag and Capability b.append(_nwid); b.append(_ts); - b.append(_expiration); b.append(_id); b.append(_value); @@ -146,7 +142,6 @@ public: // These are the same between Tag and Capability _nwid = b.template at<uint64_t>(p); p += 8; _ts = b.template at<uint64_t>(p); p += 8; - _expiration = b.template at<uint64_t>(p); p += 8; _id = b.template at<uint32_t>(p); p += 4; _value = b.template at<uint32_t>(p); p += 4; @@ -176,7 +171,6 @@ public: private: uint64_t _nwid; uint64_t _ts; - uint64_t _expiration; uint32_t _id; uint32_t _value; Address _issuedTo; |