summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Capability.hpp12
-rw-r--r--node/CertificateOfMembership.hpp49
-rw-r--r--node/Membership.cpp2
-rw-r--r--node/Membership.hpp10
-rw-r--r--node/Network.cpp14
-rw-r--r--node/NetworkConfig.cpp2
-rw-r--r--node/NetworkConfig.hpp20
-rw-r--r--node/Tag.hpp8
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;