Minor software updater cleanup.

This commit is contained in:
Adam Ierymenko 2017-03-07 09:18:00 -08:00
parent 7ea7e1898a
commit 3859533e73

View file

@ -102,18 +102,22 @@ void SoftwareUpdater::setUpdateDistribution(bool distribute)
_dist.clear(); _dist.clear();
if (distribute) { if (distribute) {
_distLog = fopen((_homePath + ZT_PATH_SEPARATOR_S "update-dist.log").c_str(),"a"); _distLog = fopen((_homePath + ZT_PATH_SEPARATOR_S "update-dist.log").c_str(),"a");
std::string udd(_homePath + ZT_PATH_SEPARATOR_S "update-dist.d");
std::vector<std::string> ud(OSUtils::listDirectory(udd.c_str())); const std::string udd(_homePath + ZT_PATH_SEPARATOR_S "update-dist.d");
for(std::vector<std::string>::iterator u(ud.begin());u!=ud.end();++u) { const std::vector<std::string> ud(OSUtils::listDirectory(udd.c_str()));
for(std::vector<std::string>::const_iterator u(ud.begin());u!=ud.end();++u) {
// Each update has a companion .json file describing it. Other files are ignored. // Each update has a companion .json file describing it. Other files are ignored.
if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) { if ((u->length() > 5)&&(u->substr(u->length() - 5,5) == ".json")) {
std::string buf; std::string buf;
if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) { if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(),buf)) {
try { try {
_D d; _D d;
d.meta = OSUtils::jsonParse(buf); d.meta = OSUtils::jsonParse(buf); // throws on invalid JSON
std::string metaHash = OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]);
std::string binPath(udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5)); // If update meta is called e.g. foo.exe.json, then foo.exe is the update itself
const std::string binPath(udd + ZT_PATH_SEPARATOR_S + u->substr(0,u->length() - 5));
const std::string metaHash(OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]));
if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile(binPath.c_str(),d.bin))) { if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile(binPath.c_str(),d.bin))) {
uint8_t sha512[ZT_SHA512_DIGEST_LEN]; uint8_t sha512[ZT_SHA512_DIGEST_LEN];
SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length()); SHA512::hash(sha512,d.bin.data(),(unsigned int)d.bin.length());
@ -128,6 +132,7 @@ void SoftwareUpdater::setUpdateDistribution(bool distribute)
} }
} catch ( ... ) {} // ignore bad meta JSON, etc. } catch ( ... ) {} // ignore bad meta JSON, etc.
} }
} }
} }
} else { } else {
@ -141,12 +146,13 @@ void SoftwareUpdater::setUpdateDistribution(bool distribute)
void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void *data,unsigned int len) void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void *data,unsigned int len)
{ {
if (!len) return; if (!len) return;
const MessageVerb v = (MessageVerb)reinterpret_cast<const uint8_t *>(data)[0];
try { try {
const MessageVerb v = (MessageVerb)reinterpret_cast<const uint8_t *>(data)[0];
switch(v) { switch(v) {
case VERB_GET_LATEST: case VERB_GET_LATEST:
case VERB_LATEST: { case VERB_LATEST: {
nlohmann::json req = OSUtils::jsonParse(std::string(reinterpret_cast<const char *>(data) + 1,len - 1)); nlohmann::json req = OSUtils::jsonParse(std::string(reinterpret_cast<const char *>(data) + 1,len - 1)); // throws on invalid JSON
if (req.is_object()) { if (req.is_object()) {
const unsigned int rvMaj = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR],0); const unsigned int rvMaj = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR],0);
const unsigned int rvMin = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR],0); const unsigned int rvMin = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR],0);
@ -156,6 +162,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
const unsigned int rvArch = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE],0); const unsigned int rvArch = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE],0);
const unsigned int rvVendor = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VENDOR],0); const unsigned int rvVendor = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VENDOR],0);
const std::string rvChannel(OSUtils::jsonString(req[ZT_SOFTWARE_UPDATE_JSON_CHANNEL],"")); const std::string rvChannel(OSUtils::jsonString(req[ZT_SOFTWARE_UPDATE_JSON_CHANNEL],""));
if (v == VERB_GET_LATEST) { if (v == VERB_GET_LATEST) {
if (_dist.size() > 0) { if (_dist.size() > 0) {
@ -226,8 +233,8 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
} }
} }
} }
} }
} }
} break; } break;
@ -273,10 +280,17 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
break; break;
default: default:
if (_distLog) {
fprintf(_distLog,"%.10llx WARNING: bad update message verb==%u length==%u (unrecognized verb)" ZT_EOL_S,origin,(unsigned int)v,len);
fflush(_distLog);
}
break; break;
} }
} catch ( ... ) { } catch ( ... ) {
// Discard bad messages if (_distLog) {
fprintf(_distLog,"%.10llx WARNING: bad update message verb==%u length==%u (unexpected exception, likely invalid JSON)" ZT_EOL_S,origin,(unsigned int)v,len);
fflush(_distLog);
}
} }
} }
@ -324,9 +338,9 @@ bool SoftwareUpdater::check(const uint64_t now)
// (1) Check the hash itself to make sure the image is basically okay // (1) Check the hash itself to make sure the image is basically okay
uint8_t sha512[ZT_SHA512_DIGEST_LEN]; uint8_t sha512[ZT_SHA512_DIGEST_LEN];
SHA512::hash(sha512,_download.data(),(unsigned int)_download.length()); 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],"~")) { if (Utils::hex(sha512,ZT_SHA512_DIGEST_LEN) == OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"")) {
// (2) Check signature by signing authority // (2) Check signature by signing authority
std::string sig(OSUtils::jsonBinFromHex(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE])); const 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 (Identity(ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY).verify(_download.data(),(unsigned int)_download.length(),sig.data(),(unsigned int)sig.length())) {
// (3) Try to save file, and if so we are good. // (3) Try to save file, and if so we are good.
if (OSUtils::writeFile(metaPath.c_str(),OSUtils::jsonDump(_latestMeta)) && OSUtils::writeFile(binPath.c_str(),_download)) { if (OSUtils::writeFile(metaPath.c_str(),OSUtils::jsonDump(_latestMeta)) && OSUtils::writeFile(binPath.c_str(),_download)) {
@ -382,8 +396,8 @@ void SoftwareUpdater::apply()
char *argv[256]; char *argv[256];
unsigned long ac = 0; unsigned long ac = 0;
argv[ac++] = const_cast<char *>(updatePath.c_str()); argv[ac++] = const_cast<char *>(updatePath.c_str());
std::vector<std::string> argsSplit(OSUtils::split(OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_EXEC_ARGS],"").c_str()," ","\\","\"")); const std::vector<std::string> argsSplit(OSUtils::split(OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_EXEC_ARGS],"").c_str()," ","\\","\""));
for(std::vector<std::string>::iterator a(argsSplit.begin());a!=argsSplit.end();++a) { for(std::vector<std::string>::const_iterator a(argsSplit.begin());a!=argsSplit.end();++a) {
argv[ac] = const_cast<char *>(a->c_str()); argv[ac] = const_cast<char *>(a->c_str());
if (++ac == 255) break; if (++ac == 255) break;
} }