diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-09-15 13:17:37 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-09-15 13:17:37 -0700 |
commit | 68e549233ddba17ec686a0462e2630580ee3d2a7 (patch) | |
tree | 3f35f2088675162436a4dec8373fbe539908deb7 | |
parent | 24fce0be8632549ecd6061259d00ee786d0a2299 (diff) | |
download | infinitytier-68e549233ddba17ec686a0462e2630580ee3d2a7.tar.gz infinitytier-68e549233ddba17ec686a0462e2630580ee3d2a7.zip |
Revise bearer token code in controller, and add relay policy as a meta-data item presented to controller by nodes (to facilitate future meshiness).
-rw-r--r-- | controller/EmbeddedNetworkController.cpp | 103 | ||||
-rw-r--r-- | controller/EmbeddedNetworkController.hpp | 4 | ||||
-rw-r--r-- | controller/README.md | 4 | ||||
-rw-r--r-- | node/Network.cpp | 2 | ||||
-rw-r--r-- | node/NetworkConfig.hpp | 10 |
5 files changed, 77 insertions, 46 deletions
diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 861792ed..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); + } } } } @@ -1137,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); } } @@ -1427,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); } } 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 | diff --git a/node/Network.cpp b/node/Network.cpp index 22aca0d8..197841d9 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1001,6 +1001,7 @@ void Network::requestConfiguration() Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> rmd; rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_VENDOR,(uint64_t)ZT_VENDOR_ZEROTIER); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,(uint64_t)ZT_PROTO_VERSION); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MAJOR); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MINOR); @@ -1011,6 +1012,7 @@ void Network::requestConfiguration() rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS,(uint64_t)ZT_MAX_NETWORK_TAGS); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,(uint64_t)ZT_RULES_ENGINE_REVISION); + rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_RELAY_POLICY,(uint64_t)RR->node->relayPolicy()); if (ctrl == RR->identity.address()) { if (RR->localNetworkController) { diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index ad1cafa5..5ad86855 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -108,9 +108,13 @@ namespace ZeroTier { #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION "v" // Protocol version (see Packet.hpp) #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION "pv" -// Software major, minor, revision +// Software vendor +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_VENDOR "vend" +// Software major version #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION "majv" +// Software minor version #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION "minv" +// Software revision #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION "revv" // Rules engine revision #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV "revr" @@ -123,9 +127,11 @@ namespace ZeroTier { // Maximum number of tags this node can accept #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS "mt" // Network join authorization token (if any) -#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH_TOKEN "atok" +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH "a" // Network configuration meta-data flags #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS "f" +// Relay policy for this node +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_RELAY_POLICY "rp" // These dictionary keys are short so they don't take up much room. // By convention we use upper case for binary blobs, but it doesn't really matter. |