summaryrefslogtreecommitdiff
path: root/service/SoftwareUpdater.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'service/SoftwareUpdater.cpp')
-rw-r--r--service/SoftwareUpdater.cpp121
1 files changed, 66 insertions, 55 deletions
diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp
index 0f5b4fca..c47a5faf 100644
--- a/service/SoftwareUpdater.cpp
+++ b/service/SoftwareUpdater.cpp
@@ -258,9 +258,10 @@ SoftwareUpdater::SoftwareUpdater(Node &node,const std::string &homePath) :
_lastCheckTime(0),
_homePath(homePath),
_channel(ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL),
- _latestBinLength(0),
- _latestBinValid(false)
+ _latestValid(false),
+ _downloadLength(0)
{
+ // Check for a cached newer update. If there's a cached update that is not newer, delete.
}
SoftwareUpdater::~SoftwareUpdater()
@@ -286,6 +287,7 @@ void SoftwareUpdater::setUpdateDistribution(bool distribute)
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
+ d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE] = d.bin.length(); // override with correct value -- setting this in meta json is optional
_dist[Array<uint8_t,16>(sha512)] = d;
printf("update-dist.d: %s\n",u->c_str());
}
@@ -351,19 +353,24 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
if ((len <= ZT_SOFTWARE_UPDATE_MAX_SIZE)&&(hash.length() >= 16)) {
if (_latestMeta != req) {
_latestMeta = req;
- _latestBin = "";
- memcpy(_latestBinHashPrefix.data,hash.data(),16);
- _latestBinLength = len;
- _latestBinValid = false;
- printf("<< LATEST\n%s\n",OSUtils::jsonDump(req).c_str());
+ _latestValid = false;
+
+ OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S + ZT_SOFTWARE_UPDATE_META_FILENAME).c_str());
+ OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S + ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str());
+
+ _download = std::string();
+ memcpy(_downloadHashPrefix.data,hash.data(),16);
+ _downloadLength = len;
}
- 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 ((_downloadLength > 0)&&(_download.length() < _downloadLength)) {
+ Buffer<128> gd;
+ gd.append((uint8_t)VERB_GET_DATA);
+ gd.append(_downloadHashPrefix.data,16);
+ gd.append((uint32_t)_download.length());
+ _node.sendUserMessage(ZT_SOFTWARE_UPDATE_SERVICE,ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE,gd.data(),gd.size());
+ printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
+ }
}
}
@@ -379,7 +386,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
idx |= (unsigned long)*(reinterpret_cast<const uint8_t *>(data) + 20);
printf("<< GET_DATA @%u from %.10llx for %s\n",(unsigned int)idx,origin,Utils::hex(reinterpret_cast<const uint8_t *>(data) + 1,16).c_str());
std::map< Array<uint8_t,16>,_D >::iterator d(_dist.find(Array<uint8_t,16>(reinterpret_cast<const uint8_t *>(data) + 1)));
- if ((d != _dist.end())&&(idx < d->second.bin.length())) {
+ if ((d != _dist.end())&&(idx < (unsigned long)d->second.bin.length())) {
Buffer<ZT_SOFTWARE_UPDATE_CHUNK_SIZE + 128> buf;
buf.append((uint8_t)VERB_DATA);
buf.append(reinterpret_cast<const uint8_t *>(data) + 1,16);
@@ -392,21 +399,21 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
break;
case VERB_DATA:
- if ((len >= 21)&&(!memcmp(_latestBinHashPrefix.data,reinterpret_cast<const uint8_t *>(data) + 1,16))) {
+ if ((len >= 21)&&(_downloadLength > 0)&&(!memcmp(_downloadHashPrefix.data,reinterpret_cast<const uint8_t *>(data) + 1,16))) {
unsigned long idx = (unsigned long)*(reinterpret_cast<const uint8_t *>(data) + 17) << 24;
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);
- if (_latestBin.length() < _latestBinLength) {
+ printf("<< DATA @%u / %u bytes (we now have %u bytes)\n",(unsigned int)idx,(unsigned int)(len - 21),(unsigned int)_download.length());
+ if (idx == (unsigned long)_download.length()) {
+ _download.append(reinterpret_cast<const char *>(data) + 21,len - 21);
+ if (_download.length() < _downloadLength) {
Buffer<128> gd;
gd.append((uint8_t)VERB_GET_DATA);
- gd.append(_latestBinHashPrefix.data,16);
- gd.append((uint32_t)_latestBin.length());
+ gd.append(_downloadHashPrefix.data,16);
+ gd.append((uint32_t)_download.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());
+ printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
}
}
}
@@ -447,44 +454,50 @@ bool SoftwareUpdater::check(const uint64_t now)
printf(">> GET_LATEST\n");
}
- if (_latestBinLength > 0) {
- if (_latestBin.length() >= _latestBinLength) {
- if (_latestBinValid) {
- return true;
- } else {
- // 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],"~")) {
- // (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())) {
- // If we passed both of these, the update is good!
- _latestBinValid = true;
+ if (_latestValid)
+ return true;
+
+ if (_downloadLength > 0) {
+ if (_download.length() >= _downloadLength) {
+ // 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,_download.data(),(unsigned int)_download.length());
+ 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(_download.data(),(unsigned int)_download.length(),sig.data(),(unsigned int)sig.length())) {
+ // If we passed both of these, the update is good!
+ if (OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + ZT_SOFTWARE_UPDATE_META_FILENAME).c_str(),OSUtils::jsonDump(_latestMeta)) && OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str(),_download)) {
+ _latestValid = true;
printf("VALID UPDATE\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
- return true;
+ } else {
+ _latestMeta = nlohmann::json();
+ _latestValid = false;
}
+ _download = std::string();
+ _downloadLength = 0;
+ return _latestValid;
}
- } catch ( ... ) {} // any exception equals verification failure
- printf("INVALID UPDATE (!!!)\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
-
- // If we get here, checks failed.
- _latestMeta = nlohmann::json();
- _latestBin = "";
- _latestBinLength = 0;
- _latestBinValid = false;
- }
+ }
+ } catch ( ... ) {} // any exception equals verification failure
+
+ // If we get here, checks failed.
+ printf("INVALID UPDATE (!!!)\n%s\n",OSUtils::jsonDump(_latestMeta).c_str());
+ _latestMeta = nlohmann::json();
+ _latestValid = false;
+ _download = std::string();
+ _downloadLength = 0;
} else {
Buffer<128> gd;
gd.append((uint8_t)VERB_GET_DATA);
- gd.append(_latestBinHashPrefix.data,16);
- gd.append((uint32_t)_latestBin.length());
+ gd.append(_downloadHashPrefix.data,16);
+ gd.append((uint32_t)_download.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());
+ printf(">> GET_DATA @%u\n",(unsigned int)_download.length());
}
}
@@ -493,8 +506,6 @@ bool SoftwareUpdater::check(const uint64_t now)
void SoftwareUpdater::apply()
{
- if ((_latestBin.length() > 0)&&(_latestBinValid)) {
- }
}
} // namespace ZeroTier