From e6b4fb5af7c4f2220824ebfa67d253deb51c4073 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Fri, 4 Jun 2021 16:29:03 -0700 Subject: [PATCH] add "ssoRedirectURL" to local.conf plumbed it through to the central controller code --- controller/DB.hpp | 2 +- controller/DBMirrorSet.cpp | 4 +-- controller/DBMirrorSet.hpp | 2 +- controller/EmbeddedNetworkController.cpp | 32 +++++++++++++++++++++++- controller/EmbeddedNetworkController.hpp | 3 +++ controller/PostgreSQL.cpp | 5 ++-- controller/PostgreSQL.hpp | 2 +- service/OneService.cpp | 7 ++++++ 8 files changed, 48 insertions(+), 9 deletions(-) diff --git a/controller/DB.hpp b/controller/DB.hpp index fb8ac6133..0776c13bd 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -104,7 +104,7 @@ public: virtual void eraseNetwork(const uint64_t networkId) = 0; virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0; virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0; - virtual std::string getSSOAuthURL(const nlohmann::json &member) { return ""; } + virtual std::string getSSOAuthURL(const nlohmann::json &member, const std::string &redirectURL) { return ""; } inline void addListener(DB::ChangeListener *const listener) { diff --git a/controller/DBMirrorSet.cpp b/controller/DBMirrorSet.cpp index 341c2d8ca..c89b7762d 100644 --- a/controller/DBMirrorSet.cpp +++ b/controller/DBMirrorSet.cpp @@ -125,11 +125,11 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,std::vect return false; } -std::string DBMirrorSet::getSSOAuthURL(const nlohmann::json &member) +std::string DBMirrorSet::getSSOAuthURL(const nlohmann::json &member, const std::string &redirectURL) { std::lock_guard l(_dbs_l); for(auto d=_dbs.begin();d!=_dbs.end();++d) { - std::string url = (*d)->getSSOAuthURL(member); + std::string url = (*d)->getSSOAuthURL(member, redirectURL); if (!url.empty()) { return url; } diff --git a/controller/DBMirrorSet.hpp b/controller/DBMirrorSet.hpp index bf1106e8f..d6dd0744a 100644 --- a/controller/DBMirrorSet.hpp +++ b/controller/DBMirrorSet.hpp @@ -51,7 +51,7 @@ public: virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member); virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId); - std::string getSSOAuthURL(const nlohmann::json &member); + std::string getSSOAuthURL(const nlohmann::json &member, const std::string &redirectURL); inline void addDB(const std::shared_ptr &db) { diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index 04222272b..490dddc12 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include "../include/ZeroTierOne.h" #include "../version.h" @@ -60,6 +63,29 @@ namespace ZeroTier { namespace { +std::string url_encode(const std::string &value) { + std::ostringstream escaped; + escaped.fill('0'); + escaped << std::hex; + + for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) { + std::string::value_type c = (*i); + + // Keep alphanumeric and other accepted characters intact + if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { + escaped << c; + continue; + } + + // Any other characters are percent-encoded + escaped << std::uppercase; + escaped << '%' << std::setw(2) << int((unsigned char) c); + escaped << std::nouppercase; + } + + return escaped.str(); +} + static json _renderRule(ZT_VirtualNetworkRule &rule) { char tmp[128]; @@ -476,6 +502,10 @@ EmbeddedNetworkController::~EmbeddedNetworkController() t->join(); } +void EmbeddedNetworkController::setSSORedirectURL(const std::string &url) { + _ssoRedirectURL = url_encode(url); +} + void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender) { char tmp[64]; @@ -1338,7 +1368,7 @@ void EmbeddedNetworkController::_request( int64_t authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0); fprintf(stderr, "authExpiryTime: %lld\n", authenticationExpiryTime); if ((authenticationExpiryTime == 0) || (authenticationExpiryTime < now)) { - std::string authenticationURL = _db.getSSOAuthURL(member); + std::string authenticationURL = _db.getSSOAuthURL(member, _ssoRedirectURL); if (!authenticationURL.empty()) { Dictionary<3072> authInfo; authInfo.add("aU", authenticationURL.c_str()); diff --git a/controller/EmbeddedNetworkController.hpp b/controller/EmbeddedNetworkController.hpp index e499dd647..fc18cbded 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/controller/EmbeddedNetworkController.hpp @@ -57,6 +57,8 @@ public: virtual void init(const Identity &signingId,Sender *sender); + void setSSORedirectURL(const std::string &url); + virtual void request( uint64_t nwid, const InetAddress &fromAddr, @@ -151,6 +153,7 @@ private: std::mutex _memberStatus_l; RedisConfig *_rc; + std::string _ssoRedirectURL; }; } // namespace ZeroTier diff --git a/controller/PostgreSQL.cpp b/controller/PostgreSQL.cpp index 271916be1..86a3a688e 100644 --- a/controller/PostgreSQL.cpp +++ b/controller/PostgreSQL.cpp @@ -309,7 +309,7 @@ void PostgreSQL::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, } } -std::string PostgreSQL::getSSOAuthURL(const nlohmann::json &member) +std::string PostgreSQL::getSSOAuthURL(const nlohmann::json &member, const std::string &redirectURL) { // NONCE is just a random character string. no semantic meaning // state = HMAC SHA384 of Nonce based on shared sso key @@ -387,11 +387,10 @@ std::string PostgreSQL::getSSOAuthURL(const nlohmann::json &member) char state_hex[256]; Utils::hex(state, 48, state_hex); - const char *redirect_url = "https%3A%2F%2Fmy.zerotier.com%2Fapi%2Fnetwork%2Fsso-auth"; // TODO: this should be configurable OSUtils::ztsnprintf(authenticationURL, sizeof(authenticationURL), "%s?response_type=id_token&response_mode=form_post&scope=openid+email+profile&redriect_uri=%s&nonce=%s&state=%s&client_id=%s", authorization_endpoint.c_str(), - redirect_url, + redirectURL.c_str(), nonce.c_str(), state_hex, client_id.c_str()); diff --git a/controller/PostgreSQL.hpp b/controller/PostgreSQL.hpp index 6e5e8a97b..637b29749 100644 --- a/controller/PostgreSQL.hpp +++ b/controller/PostgreSQL.hpp @@ -107,7 +107,7 @@ public: virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress); - virtual std::string getSSOAuthURL(const nlohmann::json &member); + virtual std::string getSSOAuthURL(const nlohmann::json &member, const std::string &redirectURL); protected: struct _PairHasher diff --git a/service/OneService.cpp b/service/OneService.cpp index 9067ffc17..e545a2cc0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -575,6 +575,7 @@ public: Mutex _run_m; RedisConfig *_rc; + std::string _ssoRedirectURL; // end member variables ---------------------------------------------------- @@ -612,6 +613,7 @@ public: #endif ,_run(true) ,_rc(NULL) + ,_ssoRedirectURL() { _ports[0] = 0; _ports[1] = 0; @@ -790,6 +792,9 @@ public: // Network controller is now enabled by default for desktop and server _controller = new EmbeddedNetworkController(_node,_homePath.c_str(),_controllerDbPath.c_str(),_ports[0], _rc); + if (!_ssoRedirectURL.empty()) { + _controller->setSSORedirectURL(_ssoRedirectURL); + } _node->setNetconfMaster((void *)_controller); // Join existing networks in networks.d @@ -1048,6 +1053,8 @@ public: if (cdbp.length() > 0) _controllerDbPath = cdbp; + _ssoRedirectURL = OSUtils::jsonString(settings["ssoRedirectURL"], ""); + #ifdef ZT_CONTROLLER_USE_LIBPQ // TODO: Redis config json &redis = settings["redis"];