diff --git a/idtool.cpp b/idtool.cpp index a74aaf219..0731e4c15 100644 --- a/idtool.cpp +++ b/idtool.cpp @@ -34,6 +34,8 @@ #include "node/Identity.hpp" #include "node/Utils.hpp" #include "node/C25519.hpp" +#include "node/SHA512.hpp" +#include "node/Dictionary.hpp" using namespace ZeroTier; @@ -46,6 +48,7 @@ static void printHelp(char *pn) std::cout << "\tgetpublic " << std::endl; std::cout << "\tsign " << std::endl; std::cout << "\tverify " << std::endl; + std::cout << "\tsignupdate " << std::endl; } static Identity getIdFromArg(char *arg) @@ -166,6 +169,41 @@ int main(int argc,char **argv) std::cerr << argv[3] << " signature check FAILED" << std::endl; return -1; } + } else if (!strcmp(argv[1],"signupdate")) { + Identity id = getIdFromArg(argv[2]); + if (!id) { + std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl; + return -1; + } + + std::string update; + if (!Utils::readFile(argv[3],update)) { + std::cerr << argv[3] << " is not readable" << std::endl; + return -1; + } + + unsigned char sha512[64]; + SHA512::hash(sha512,update.data(),update.length()); + + char *atLastSep = strrchr(argv[3],ZT_PATH_SEPARATOR); + std::string nameAndSha((atLastSep) ? (atLastSep + 1) : argv[3]); + std::cout << "Signing filename '" << nameAndSha << "' plus SHA-512 digest " << Utils::hex(sha512,64) << std::endl; + nameAndSha.append((const char *)sha512,64); + C25519::Signature signature(id.sign(nameAndSha.data(),nameAndSha.length())); + + Dictionary sig; + sig["sha512"] = Utils::hex(sha512,64); + sig["sha512_ed25519"] = Utils::hex(signature.data,signature.size()); + sig["signedBy"] = id.address().toString(); + std::cout << "-- .sig file contents:" << std::endl << sig.toString() << "--" << std::endl; + + std::string sigPath(argv[3]); + sigPath.append(".sig"); + if (!Utils::writeFile(sigPath.c_str(),sig.toString())) { + std::cerr << "Could not write " << sigPath << std::endl; + return -1; + } + std::cout << "Wrote " << sigPath << std::endl; } else { printHelp(argv[0]); return -1; diff --git a/node/Updater.cpp b/node/Updater.cpp index 22eda925e..2de64c11d 100644 --- a/node/Updater.cpp +++ b/node/Updater.cpp @@ -76,28 +76,14 @@ void Updater::refreshShared() shared.filename = u->first; std::string sha512(Utils::unhex(sig.get("sha512",std::string()))); - if (sha512.length() < sizeof(shared.sha512)) { + std::string signature(Utils::unhex(sig.get("sha512_ed25519",std::string()))); + Address signedBy(sig.get("signedBy",std::string())); + if ((sha512.length() < sizeof(shared.sha512))||(signature.length() < shared.sig.size())||(!signedBy)) { TRACE("skipped shareable update due to missing fields in companion .sig: %s",fullPath.c_str()); continue; } memcpy(shared.sha512,sha512.data(),sizeof(shared.sha512)); - - std::string signature(Utils::unhex(sig.get("sha512sig_ed25519",std::string()))); - if (signature.length() < shared.sig.size()) { - TRACE("skipped shareable update due to missing fields in companion .sig: %s",fullPath.c_str()); - continue; - } memcpy(shared.sig.data,signature.data(),shared.sig.size()); - - // Check signature to guard against updates.d being used as a data - // exfiltration mechanism. We will only share properly signed updates, - // nothing else. - Address signedBy(sig.get("signedBy",std::string())); - std::map< Address,Identity >::const_iterator authority(ZT_DEFAULTS.updateAuthorities.find(signedBy)); - if ((authority == ZT_DEFAULTS.updateAuthorities.end())||(!authority->second.verify(shared.sha512,64,shared.sig))) { - TRACE("skipped shareable update: not signed by valid authority or signature invalid: %s",fullPath.c_str()); - continue; - } shared.signedBy = signedBy; int64_t fs = Utils::getFileSize(fullPath.c_str());