summaryrefslogtreecommitdiff
path: root/controller
diff options
context:
space:
mode:
authorGrant Limberg <glimberg@gmail.com>2016-09-18 18:10:03 -0700
committerGrant Limberg <glimberg@gmail.com>2016-09-18 18:10:03 -0700
commit3366b53247adca547055300a573fd91182e2255c (patch)
tree7fc29673601151750fc6b19a9a06d287e70eaa3b /controller
parent5ed5b22525b9233871e3fca8da2c9d77535afd7b (diff)
parent68e549233ddba17ec686a0462e2630580ee3d2a7 (diff)
downloadinfinitytier-3366b53247adca547055300a573fd91182e2255c.tar.gz
infinitytier-3366b53247adca547055300a573fd91182e2255c.zip
Merge branch 'dev' of http://git.int.zerotier.com/ZeroTier/ZeroTierOne into dev
Diffstat (limited to 'controller')
-rw-r--r--controller/EmbeddedNetworkController.cpp117
-rw-r--r--controller/EmbeddedNetworkController.hpp4
-rw-r--r--controller/README.md4
3 files changed, 72 insertions, 53 deletions
diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp
index cf6bd7c9..53b345b4 100644
--- a/controller/EmbeddedNetworkController.cpp
+++ b/controller/EmbeddedNetworkController.cpp
@@ -566,42 +566,69 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(
// Determine whether and how member is authorized
const char *authorizedBy = (const char *)0;
- if (!_jB(network["private"],true)) {
+ if (_jB(member["authorized"],false)) {
+ authorizedBy = "memberIsAuthorized";
+ } else if (!_jB(network["private"],true)) {
authorizedBy = "networkIsPublic";
- // 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;
- member["lastAuthorizedTime"] = now;
- member["lastAuthorizedBy"] = authorizedBy;
+ json ah;
+ ah["a"] = true;
+ ah["by"] = authorizedBy;
+ ah["ts"] = now;
+ ah["ct"] = json();
+ ah["c"] = json();
+ member["authHistory"].push_back(ah);
member["lastModified"] = now;
- auto revj = member["revision"];
+ json &revj = member["revision"];
member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL);
}
- } else if (_jB(member["authorized"],false)) {
- authorizedBy = "memberIsAuthorized";
} else {
- char atok[256];
- if (metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH_TOKEN,atok,sizeof(atok)) > 0) {
- atok[255] = (char)0; // not necessary but YDIFLO
- if (strlen(atok) > 0) { // extra sanity check since we never want to compare a null token on either side
- auto authTokens = network["authTokens"];
+ char presentedAuth[512];
+ if (metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH,presentedAuth,sizeof(presentedAuth)) > 0) {
+ presentedAuth[511] = (char)0; // sanity check
+
+ // Check for bearer token presented by member
+ if ((strlen(presentedAuth) > 6)&&(!strncmp(presentedAuth,"token:",6))) {
+ const char *const presentedToken = presentedAuth + 6;
+
+ json &authTokens = network["authTokens"];
if (authTokens.is_array()) {
for(unsigned long i=0;i<authTokens.size();++i) {
- auto at = authTokens[i];
- if (at.is_object()) {
- const uint64_t expires = _jI(at["expires"],0ULL);
- std::string tok = _jS(at["token"],"");
- 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;
- member["lastModified"] = now;
- auto revj = member["revision"];
- member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL);
- break;
+ json &token = authTokens[i];
+ if (token.is_object()) {
+ const uint64_t expires = _jI(token["expires"],0ULL);
+ const uint64_t maxUses = _jI(token["maxUsesPerMember"],0ULL);
+ std::string tstr = _jS(token["token"],"");
+
+ if (((expires == 0ULL)||(expires > now))&&(tstr == presentedToken)) {
+ bool usable = (maxUses == 0);
+ if (!usable) {
+ uint64_t useCount = 0;
+ json &ahist = member["authHistory"];
+ if (ahist.is_array()) {
+ for(unsigned long j=0;j<ahist.size();++j) {
+ json &ah = ahist[j];
+ if ((_jS(ah["ct"],"") == "token")&&(_jS(ah["c"],"") == tstr)&&(_jB(ah["a"],false)))
+ ++useCount;
+ }
+ }
+ usable = (useCount < maxUses);
+ }
+ if (usable) {
+ authorizedBy = "token";
+ member["authorized"] = true;
+ json ah;
+ ah["a"] = true;
+ ah["by"] = authorizedBy;
+ ah["ts"] = now;
+ ah["ct"] = "token";
+ ah["c"] = tstr;
+ member["authHistory"].push_back(ah);
+ member["lastModified"] = now;
+ json &revj = member["revision"];
+ member["revision"] = (revj.is_number() ? ((uint64_t)revj + 1ULL) : 1ULL);
+ }
}
}
}
@@ -924,13 +951,11 @@ NetworkController::ResultCode EmbeddedNetworkController::doNetworkConfigRequest(
}
}
- if (_jB(network["private"],true)) {
- CertificateOfMembership com(now,credentialtmd,nwid,identity.address());
- if (com.sign(signingId)) {
- nc.com = com;
- } else {
- return NETCONF_QUERY_INTERNAL_SERVER_ERROR;
- }
+ CertificateOfMembership com(now,credentialtmd,nwid,identity.address());
+ if (com.sign(signingId)) {
+ nc.com = com;
+ } else {
+ return NETCONF_QUERY_INTERNAL_SERVER_ERROR;
}
_writeJson(memberJP,member);
@@ -1139,16 +1164,15 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
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 (newAuth != _jB(member["authorized"],false)) {
+ member["authorized"] = newAuth;
+ json ah;
+ ah["a"] = newAuth;
+ ah["by"] = "api";
+ ah["ts"] = now;
+ ah["ct"] = json();
+ ah["c"] = json();
+ member["authHistory"].push_back(ah);
}
}
@@ -1429,13 +1453,14 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
if (authTokens.is_array()) {
json nat = json::array();
for(unsigned long i=0;i<authTokens.size();++i) {
- auto token = authTokens[i];
+ json &token = authTokens[i];
if (token.is_object()) {
std::string tstr = token["token"];
if (tstr.length() > 0) {
json t = json::object();
t["token"] = tstr;
t["expires"] = _jI(token["expires"],0ULL);
+ t["maxUsesPerMember"] = _jI(token["maxUsesPerMember"],0ULL);
nat.push_back(t);
}
}
@@ -1585,7 +1610,6 @@ void EmbeddedNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTes
"\t\"upstream\": \"%.10llx\"," ZT_EOL_S
"\t\"current\": \"%.10llx\"," ZT_EOL_S
"\t\"receivedTimestamp\": %llu," ZT_EOL_S
- "\t\"remoteTimestamp\": %llu," ZT_EOL_S
"\t\"sourcePacketId\": \"%.16llx\"," ZT_EOL_S
"\t\"flags\": %llu," ZT_EOL_S
"\t\"sourcePacketHopCount\": %u," ZT_EOL_S
@@ -1606,7 +1630,6 @@ void EmbeddedNetworkController::_circuitTestCallback(ZT_Node *node,ZT_CircuitTes
(unsigned long long)report->upstream,
(unsigned long long)report->current,
(unsigned long long)OSUtils::now(),
- (unsigned long long)report->remoteTimestamp,
(unsigned long long)report->sourcePacketId,
(unsigned long long)report->flags,
report->sourcePacketHopCount,
diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp
index 303a5355..1bfd9577 100644
--- a/controller/EmbeddedNetworkController.hpp
+++ b/controller/EmbeddedNetworkController.hpp
@@ -143,9 +143,7 @@ private:
inline void _initMember(nlohmann::json &member)
{
if (!member.count("authorized")) member["authorized"] = false;
- if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
- if (!member.count("lastAuthorizedBy")) member["lastAuthorizedBy"] = "";
- if (!member.count("lastDeauthorizedTime")) member["lastDeauthorizedTime"] = 0ULL;
+ if (!member.count("authHistory")) member["authHistory"] = nlohmann::json::array();
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;
diff --git a/controller/README.md b/controller/README.md
index 1eb0ca0d..805641d9 100644
--- a/controller/README.md
+++ b/controller/README.md
@@ -229,9 +229,7 @@ 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 |
+| authHistory | array[object] | History of auth changes, latest at end | 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 |