summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2017-01-12 13:18:11 -0800
committerAdam Ierymenko <adam.ierymenko@gmail.com>2017-01-12 13:18:11 -0800
commitc6b0b076055f0b9b579c21bbbe83171a554a2600 (patch)
tree236ad6748ffefa829928df791d34c5c93962fccd /service
parentb5b583c39751dbb0ea12e56aa826a28661bd082c (diff)
downloadinfinitytier-c6b0b076055f0b9b579c21bbbe83171a554a2600.tar.gz
infinitytier-c6b0b076055f0b9b579c21bbbe83171a554a2600.zip
More software update work, and settings in local.conf.
Diffstat (limited to 'service')
-rw-r--r--service/OneService.cpp19
-rw-r--r--service/SoftwareUpdater.cpp74
-rw-r--r--service/SoftwareUpdater.hpp33
3 files changed, 82 insertions, 44 deletions
diff --git a/service/OneService.cpp b/service/OneService.cpp
index 9ee05f96..697be24a 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -264,6 +264,7 @@ public:
Phy<OneServiceImpl *> _phy;
Node *_node;
SoftwareUpdater *_updater;
+ bool _updateAutoApply;
unsigned int _primaryPort;
// Local configuration and memo-ized static path definitions
@@ -367,6 +368,7 @@ public:
,_phy(this,false,true)
,_node((Node *)0)
,_updater((SoftwareUpdater *)0)
+ ,_updateAutoApply(false)
,_primaryPort(port)
,_controlPlane((ControlPlane *)0)
,_lastDirectReceiveFromGlobal(0)
@@ -454,9 +456,6 @@ public:
_node = new Node(this,&cb,OSUtils::now());
}
- _updater = new SoftwareUpdater(*_node,_homePath);
- _updater->loadUpdatesToDistribute();
-
// Read local configuration
{
uint64_t trustedPathIds[ZT_MAX_TRUSTED_PATHS];
@@ -982,6 +981,20 @@ public:
_node->setRelayPolicy(ZT_RELAY_POLICY_NEVER);
else _node->setRelayPolicy(ZT_RELAY_POLICY_TRUSTED);
+ const std::string up(OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT));
+ const bool udist = OSUtils::jsonBool(settings["softwareUpdateDist"],false);
+ if (((up == "apply")||(up == "download"))||(udist)) {
+ if (!_updater)
+ _updater = new SoftwareUpdater(*_node,_homePath);
+ _updateAutoApply = (up == "apply");
+ _updater->setUpdateDistribution(udist);
+ _updater->setChannel(OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL));
+ } else {
+ delete _updater;
+ _updater = (SoftwareUpdater *)0;
+ _updateAutoApply = false;
+ }
+
json &ignoreIfs = settings["interfacePrefixBlacklist"];
if (ignoreIfs.is_array()) {
for(unsigned long i=0;i<ignoreIfs.size();++i) {
diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp
index 2e8d1344..f10eb204 100644
--- a/service/SoftwareUpdater.cpp
+++ b/service/SoftwareUpdater.cpp
@@ -257,6 +257,7 @@ SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) :
_node(node),
_lastCheckTime(0),
_homePath(homePath),
+ _channel(ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL),
_latestBinLength(0),
_latestBinValid(false)
{
@@ -266,28 +267,31 @@ SoftwareUpdater::~SoftwareUpdater()
{
}
-void SoftwareUpdater::loadUpdatesToDistribute()
+void SoftwareUpdater::setUpdateDistribution(bool distribute)
{
- std::string udd(_homePath + ZT_PATH_SEPARATOR_S + "update-dist.d");
- std::vector<std::string> ud(OSUtils::listDirectory(udd.c_str()));
- for(std::vector<std::string>::iterator u(ud.begin());u!=ud.end();++u) {
- // Each update has a companion .json file describing it. Other files are ignored.
- if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) {
- std::string buf;
- if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) {
- try {
- _D d;
- d.meta = OSUtils::jsonParse(buf);
- std::string metaHash = OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]);
- if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)).c_str(),d.bin))) {
- uint8_t sha512[ZT_SHA512_DIGEST_LEN];
- SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length());
- if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct
- _dist[Array<uint8_t,16>(sha512)] = d;
- printf("update-dist.d: %s\n",u->c_str());
+ _dist.clear();
+ if (distribute) {
+ std::string udd(_homePath + ZT_PATH_SEPARATOR_S + "update-dist.d");
+ std::vector<std::string> ud(OSUtils::listDirectory(udd.c_str()));
+ for(std::vector<std::string>::iterator u(ud.begin());u!=ud.end();++u) {
+ // Each update has a companion .json file describing it. Other files are ignored.
+ if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) {
+ std::string buf;
+ if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) {
+ try {
+ _D d;
+ d.meta = OSUtils::jsonParse(buf);
+ std::string metaHash = OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]);
+ if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)).c_str(),d.bin))) {
+ uint8_t sha512[ZT_SHA512_DIGEST_LEN];
+ SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length());
+ if (!memcmp(sha512,metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct
+ _dist[Array<uint8_t,16>(sha512)] = d;
+ printf("update-dist.d: %s\n",u->c_str());
+ }
}
- }
- } catch ( ... ) {} // ignore bad meta JSON, etc.
+ } catch ( ... ) {} // ignore bad meta JSON, etc.
+ }
}
}
}
@@ -393,18 +397,17 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
idx |= (unsigned long)*(reinterpret_cast<const uint8_t *>(data) + 18) << 16;
idx |= (unsigned long)*(reinterpret_cast<const uint8_t *>(data) + 19) << 8;
idx |= (unsigned long)*(reinterpret_cast<const uint8_t *>(data) + 20);
+ printf("<< DATA @%u / %u bytes (we now have %u bytes)\n",(unsigned int)idx,(unsigned int)(len - 21),(unsigned int)_latestBin.length());
if (idx == _latestBin.length()) {
_latestBin.append(reinterpret_cast<const char *>(data) + 21,len - 21);
- }
- printf("<< DATA @%u / %u bytes (we now have %u bytes)\n",(unsigned int)idx,(unsigned int)(len - 21),(unsigned int)_latestBin.length());
-
- if (_latestBin.length() < _latestBinLength) {
- Buffer<128> gd;
- gd.append((uint8_t)VERB_GET_DATA);
- gd.append(_latestBinHashPrefix.data,16);
- gd.append((uint32_t)_latestBin.length());
- _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
- printf(">> GET_DATA @%u\n",(unsigned int)_latestBin.length());
+ if (_latestBin.length() < _latestBinLength) {
+ Buffer<128> gd;
+ gd.append((uint8_t)VERB_GET_DATA);
+ gd.append(_latestBinHashPrefix.data,16);
+ gd.append((uint32_t)_latestBin.length());
+ _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
+ printf(">> GET_DATA @%u\n",(unsigned int)_latestBin.length());
+ }
}
}
break;
@@ -417,7 +420,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
}
}
-nlohmann::json SoftwareUpdater::check(const uint64_t now)
+bool SoftwareUpdater::check(const uint64_t now)
{
if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) {
_lastCheckTime = now;
@@ -439,7 +442,7 @@ nlohmann::json SoftwareUpdater::check(const uint64_t now)
ZT_BUILD_PLATFORM,
ZT_BUILD_ARCHITECTURE,
(int)ZT_VENDOR_ZEROTIER,
- "release");
+ _channel.c_str());
_node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,tmp,len);
printf(">> GET_LATEST\n");
}
@@ -449,13 +452,14 @@ nlohmann::json SoftwareUpdater::check(const uint64_t now)
if (_latestBinValid) {
return _latestMeta;
} else {
- // This is the important security verification part!
+ // This is the very important security validation part that makes sure
+ // this software update doesn't have cooties.
try {
// (1) Check the hash itself to make sure the image is basically okay
uint8_t sha512[ZT_SHA512_DIGEST_LEN];
SHA512::hash(sha512,_latestBin.data(),(unsigned int)_latestBin.length());
- if (Utils::hex(sha512,ZT_SHA512_DIGEST_LEN) == OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"")) {
+ if (Utils::hex(sha512,ZT_SHA512_DIGEST_LEN) == OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"~")) {
// (2) Check signature by signing authority
std::string sig(OSUtils::jsonBinFromHex(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE]));
if (Identity(ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY).verify(_latestBin.data(),(unsigned int)_latestBin.length(),sig.data(),(unsigned int)sig.length())) {
@@ -489,7 +493,7 @@ nlohmann::json SoftwareUpdater::check(const uint64_t now)
void SoftwareUpdater::apply()
{
- if ((_latestBin.length() == _latestBinLength)&&(_latestBinLength > 0)&&(_latestBinValid)) {
+ if ((_latestBin.length() > 0)&&(_latestBinValid)) {
}
}
diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp
index 0501ff23..b9cabf23 100644
--- a/service/SoftwareUpdater.hpp
+++ b/service/SoftwareUpdater.hpp
@@ -64,19 +64,25 @@
//#define ZT_SOFTWARE_UPDATE_CHECK_PERIOD (60 * 60 * 1000)
#define ZT_SOFTWARE_UPDATE_CHECK_PERIOD 5000
+/**
+ * Default update channel
+ */
+#define ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL "release"
+
#define ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "versionMajor"
#define ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "versionMinor"
#define ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "versionRev"
-#define ZT_SOFTWARE_UPDATE_JSON_EXPECT_SIGNED_BY "expectedSigner"
#define ZT_SOFTWARE_UPDATE_JSON_PLATFORM "platform"
#define ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE "arch"
#define ZT_SOFTWARE_UPDATE_JSON_VENDOR "vendor"
#define ZT_SOFTWARE_UPDATE_JSON_CHANNEL "channel"
+#define ZT_SOFTWARE_UPDATE_JSON_EXPECT_SIGNED_BY "expectedSigner"
#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNED_BY "updateSigner"
#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE "updateSig"
#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH "updateHash"
#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE "updateSize"
-#define ZT_SOFTWARE_UPDATE_JSON_EXEC_ARGS "updateExecArgs"
+#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_EXEC_ARGS "updateExecArgs"
+#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_URL "updateUrl"
namespace ZeroTier {
@@ -123,9 +129,11 @@ public:
~SoftwareUpdater();
/**
- * Load update-dist.d if it exists
+ * Set whether or not we will distribute updates
+ *
+ * @param distribute If true, scan update-dist.d now and distribute updates found there -- if false, clear and stop distributing
*/
- void loadUpdatesToDistribute();
+ void setUpdateDistribution(bool distribute);
/**
* Handle a software update user message
@@ -141,9 +149,14 @@ public:
*
* It should be called about every 10 seconds.
*
- * @return Null JSON object or update information if there is an update downloaded and ready
+ * @return True if we've downloaded and verified an update
*/
- nlohmann::json check(const uint64_t now);
+ bool check(const uint64_t now);
+
+ /**
+ * @return Meta-data for downloaded update or NULL if none
+ */
+ inline const nlohmann::json &pending() const { return _latestMeta; }
/**
* Apply any ready update now
@@ -153,10 +166,18 @@ public:
*/
void apply();
+ /**
+ * Set software update channel
+ *
+ * @param channel 'release', 'beta', etc.
+ */
+ inline void setChannel(const std::string &channel) { _channel = channel; }
+
private:
Node &_node;
uint64_t _lastCheckTime;
std::string _homePath;
+ std::string _channel;
// Offered software updates if we are an update host (we have update-dist.d and update hosting is enabled)
struct _D