summaryrefslogtreecommitdiff
path: root/controller
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-08-23 13:02:59 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-08-23 13:02:59 -0700
commit32fa0617004e80c99b341eb1b4753705b515b53a (patch)
tree55840f1e0d524cbea83cae6fd8945ed142267f3b /controller
parent70368312039f37d08ba687b07a5caad1c57cd8de (diff)
downloadinfinitytier-32fa0617004e80c99b341eb1b4753705b515b53a.tar.gz
infinitytier-32fa0617004e80c99b341eb1b4753705b515b53a.zip
Compute credential TTL et al.
Diffstat (limited to 'controller')
-rw-r--r--controller/EmbeddedNetworkController.cpp44
-rw-r--r--controller/EmbeddedNetworkController.hpp8
-rw-r--r--controller/README.md3
3 files changed, 49 insertions, 6 deletions
diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp
index 738fea9a..4db219c9 100644
--- a/controller/EmbeddedNetworkController.cpp
+++ b/controller/EmbeddedNetworkController.cpp
@@ -413,7 +413,7 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(
lrt = now;
}
- json network(_readJson(_networkJP(nwid,false)));
+ const json network(_readJson(_networkJP(nwid,false)));
if (!network.size())
return NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND;
@@ -458,7 +458,11 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(
// If member already has an authorized field, leave it alone. That way its state is
// preserved if the user toggles the network back to private. Otherwise set it to
// true by default for new members of public nets.
- if (!member.count("authorized")) member["authorized"] = true;
+ if (!member.count("authorized")) {
+ member["authorized"] = true;
+ member["lastAuthorizedTime"] = now;
+ member["lastAuthorizedBy"] = authorizedBy;
+ }
} else if (_jB(member["authorized"],false)) {
authorizedBy = "memberIsAuthorized";
} else {
@@ -476,6 +480,8 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(
if ( ((expires == 0ULL)||(expires > now)) && (tok.length() > 0) && (tok == atok) ) {
authorizedBy = "token";
member["authorized"] = true; // tokens actually change member authorization state
+ member["lastAuthorizedTime"] = now;
+ member["lastAuthorizedBy"] = authorizedBy;
break;
}
}
@@ -517,14 +523,28 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(
return NetworkController::NETCONF_QUERY_ACCESS_DENIED;
}
+ // -------------------------------------------------------------------------
// If we made it this far, they are authorized.
+ // -------------------------------------------------------------------------
_NetworkMemberInfo nmi;
_getNetworkMemberInfo(now,nwid,nmi);
+ // Compute credential TTL. This is the "moving window" for COM agreement and
+ // the global TTL for Capability and Tag objects. (The same value is used
+ // for both.) This is computed by reference to the last time we deauthorized
+ // a member, since within the time period since this event any temporal
+ // differences are not particularly relevant.
+ uint64_t credentialTtl = ZT_NETWORKCONFIG_DEFAULT_MIN_CREDENTIAL_TTL;
+ if (now > nmi.mostRecentDeauthTime)
+ credentialTtl += (now - nmi.mostRecentDeauthTime);
+ if (credentialTtl > ZT_NETWORKCONFIG_DEFAULT_MAX_CREDENTIAL_TTL)
+ credentialTtl = ZT_NETWORKCONFIG_DEFAULT_MAX_CREDENTIAL_TTL;
+
nc.networkId = nwid;
nc.type = _jB(network["private"],true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC;
nc.timestamp = now;
+ nc.credentialTimeToLive = credentialTtl;
nc.revision = _jI(network["revision"],0ULL);
nc.issuedTo = identity.address();
if (_jB(network["enableBroadcast"],true)) nc.flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST;
@@ -777,7 +797,7 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(
}
if (_jB(network["private"],true)) {
- CertificateOfMembership com(now,ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA,nwid,identity.address());
+ CertificateOfMembership com(now,credentialTtl,nwid,identity.address());
if (com.sign(signingId)) {
nc.com = com;
} else {
@@ -976,10 +996,24 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
_initMember(member);
try {
- if (b.count("authorized")) member["authorized"] = _jB(b["authorized"],false);
if (b.count("activeBridge")) member["activeBridge"] = _jB(b["activeBridge"],false);
if ((b.count("identity"))&&(!member.count("identity"))) member["identity"] = _jS(b["identity"],""); // allow identity to be populated only if not already known
+ if (b.count("authorized")) {
+ const bool newAuth = _jB(b["authorized"],false);
+ const bool oldAuth = _jB(member["authorized"],false);
+ if (newAuth != oldAuth) {
+ if (newAuth) {
+ member["authorized"] = true;
+ member["lastAuthorizedTime"] = now;
+ member["lastAuthorizedBy"] = "user";
+ } else {
+ member["authorized"] = false;
+ member["lastDeauthorizedTime"] = now;
+ }
+ }
+ }
+
if (b.count("ipAssignments")) {
auto ipa = b["ipAssignments"];
if (ipa.is_array()) {
@@ -1476,6 +1510,8 @@ void EmbeddedNetworkController::_getNetworkMemberInfo(uint64_t now,uint64_t nwid
nmi.allocatedIps.insert(mip);
}
}
+ } else {
+ nmi.mostRecentDeauthTime = std::max(nmi.mostRecentDeauthTime,_jI(nm->second["lastDeauthorizedTime"],0ULL));
}
}
}
diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp
index e6b4bb59..3613e0ef 100644
--- a/controller/EmbeddedNetworkController.hpp
+++ b/controller/EmbeddedNetworkController.hpp
@@ -141,12 +141,13 @@ private:
// This does lock _networkMemberCache_m
struct _NetworkMemberInfo
{
- _NetworkMemberInfo() : authorizedMemberCount(0),activeMemberCount(0),totalMemberCount(0) {}
+ _NetworkMemberInfo() : authorizedMemberCount(0),activeMemberCount(0),totalMemberCount(0),mostRecentDeauthTime(0) {}
std::set<Address> activeBridges;
std::set<InetAddress> allocatedIps;
unsigned long authorizedMemberCount;
unsigned long activeMemberCount;
unsigned long totalMemberCount;
+ uint64_t mostRecentDeauthTime;
};
void _getNetworkMemberInfo(uint64_t now,uint64_t nwid,_NetworkMemberInfo &nmi);
@@ -154,7 +155,10 @@ private:
inline void _initMember(nlohmann::json &member)
{
if (!member.count("authorized")) member["authorized"] = false;
- if (!member.count("ipAssignments")) member["ipAssignments"] = nlohmann::json::array();
+ if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
+ if (!member.count("lastAuthorizedBy")) member["lastAuthorizedBy"] = "";
+ if (!member.count("lastDeauthorizedTime")) member["lastDeauthorizedTime"] = 0ULL;
+ if (!member.count("ipAssignments")) member["ipAssignments"] = nlohmann::json::array();
if (!member.count("recentLog")) member["recentLog"] = nlohmann::json::array();
if (!member.count("activeBridge")) member["activeBridge"] = false;
if (!member.count("tags")) member["tags"] = nlohmann::json::array();
diff --git a/controller/README.md b/controller/README.md
index 339adb31..189fcdbd 100644
--- a/controller/README.md
+++ b/controller/README.md
@@ -208,6 +208,9 @@ This returns an object containing all currently online members and the most rece
| nwid | string | 16-digit network ID | no |
| clock | integer | Current clock, ms since epoch | no |
| authorized | boolean | Is member authorized? (for private networks) | YES |
+| lastAuthorizedTime | integer | Time 'authorized' was last set to 'true' | no |
+| lastAuthorizedBy | string | What last set 'authorized' to 'true'? | no |
+| lastDeauthorizedTime | integer | Time 'authorized' was last set to 'false' | no |
| activeBridge | boolean | Member is able to bridge to other Ethernet nets | YES |
| identity | string | Member's public ZeroTier identity (if known) | no |
| ipAssignments | array[string] | Managed IP address assignments | YES |