From 51ced02370cf602774155b38b0c54830dae100ea Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 25 Aug 2016 22:05:23 -0700 Subject: [PATCH] Add support for signing symbolic links (sort of?). --- ldid.cpp | 99 +++++++++++++++++++++++++++++++++++++++----------------- ldid.hpp | 10 +++--- 2 files changed, 75 insertions(+), 34 deletions(-) diff --git a/ldid.cpp b/ldid.cpp index a721eaa..21e8863 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -1351,15 +1351,9 @@ class NullBuffer : class Hash { public: - bool ready_; char sha1_[LDID_SHA1_DIGEST_LENGTH]; char sha256_[LDID_SHA256_DIGEST_LENGTH]; - Hash() : - ready_(false) - { - } - operator std::vector() const { return {sha1_, sha1_ + sizeof(sha1_)}; } @@ -1385,7 +1379,6 @@ class HashBuffer : ~HashBuffer() { LDID_SHA1_Final(reinterpret_cast(hash_.sha1_), &sha1_); LDID_SHA256_Final(reinterpret_cast(hash_.sha256_), &sha256_); - hash_.ready_ = true; } virtual std::streamsize xsputn(const char_type *data, std::streamsize size) { @@ -1693,7 +1686,23 @@ DiskFolder::~DiskFolder() { Commit(commit.first, commit.second); } -void DiskFolder::Find(const std::string &root, const std::string &base, const Functor &)> &)>&code) { +#ifndef __WIN32__ +std::string readlink(const std::string &path) { + for (size_t size(1024); ; size *= 2) { + std::string data; + data.resize(size); + + int writ(_syscall(::readlink(path.c_str(), &data[0], data.size()))); + if (size_t(writ) >= size) + continue; + + data.resize(writ); + return data; + } +} +#endif + +void DiskFolder::Find(const std::string &root, const std::string &base, const Functor &)> &)> &code, const Functor &)> &link) { std::string path(Path(root) + base); DIR *dir(opendir(path.c_str())); @@ -1727,13 +1736,16 @@ void DiskFolder::Find(const std::string &root, const std::string &base, const Fu case DT_REG: directory = false; break; + case DT_LNK: + link(base + name, fun([&]() { return readlink(path + name); })); + continue; default: _assert_(false, "d_type=%u", child->d_type); } #endif if (directory) - Find(root, base + name + "/", code); + Find(root, base + name + "/", code, link); else code(base + name, fun([&](const Functor &code) { std::string access(root + base + name); @@ -1764,8 +1776,8 @@ bool DiskFolder::Open(const std::string &path, const Functor &)> &)>&code) { - Find(path, "", code); +void DiskFolder::Find(const std::string &path, const Functor &)> &)> &code, const Functor &)> &link) { + Find(path, "", code, link); } #endif @@ -1783,8 +1795,8 @@ bool SubFolder::Open(const std::string &path, const Functor &)> &)> &code) { - return parent_.Find(path_ + path, code); +void SubFolder::Find(const std::string &path, const Functor &)> &)> &code, const Functor &)> &link) { + return parent_.Find(path_ + path, code, link); } std::string UnionFolder::Map(const std::string &path) { @@ -1826,10 +1838,13 @@ bool UnionFolder::Open(const std::string &path, const Functor &)> &)> &code) { +void UnionFolder::Find(const std::string &path, const Functor &)> &)> &code, const Functor &)> &link) { parent_.Find(path, fun([&](const std::string &name, const Functor &)> &save) { if (deletes_.find(path + name) == deletes_.end()) code(name, save); + }), fun([&](const std::string &name, const Functor &read) { + if (deletes_.find(path + name) == deletes_.end()) + link(name, read); })); for (auto &reset : resets_) @@ -1978,7 +1993,7 @@ static void Sign(const uint8_t *prefix, size_t size, std::streambuf &buffer, Has Sign(data.data(), data.size(), proxy, identifier, entitlements, requirement, key, slots); } -std::string Bundle(const std::string &root, Folder &folder, const std::string &key, std::map &remote, const std::string &entitlements, const std::string &requirement) { +std::string Bundle(const std::string &root, Folder &folder, const std::string &key, std::set &remote, const std::string &entitlements, const std::string &requirement) { std::string executable; std::string identifier; @@ -2031,7 +2046,8 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k rules2.insert(Rule{20, NoMode, "^version\\.plist$"}); } - std::map local; + std::map hashes; + std::set local; static Expression nested("^PlugIns/[^/]*\\.appex/Info\\.plist$"); @@ -2041,16 +2057,21 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k auto bundle(root + Split(name).dir); SubFolder subfolder(folder, bundle); Bundle(bundle, subfolder, key, local, "", ""); + }), fun([&](const std::string &name, const Functor &read) { })); + std::map links; + folder.Find("", fun([&](const std::string &name, const Functor &)> &code) { // BundleDiskRep::adjustResources -> builder.addExclusion if (name == executable || Starts(name, directory) || Starts(name, "_MASReceipt/") || name == "CodeResources") return; - auto &hash(local[name]); - if (hash.ready_) + if (local.find(name) != local.end()) return; + local.insert(name); + + auto &hash(hashes[name]); code(fun([&](std::streambuf &data, std::streambuf &save) { union { @@ -2081,8 +2102,9 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k put(proxy, header.bytes, size); copy(data, proxy); })); - - _assert(hash.ready_); + }), fun([&](const std::string &name, const Functor &read) { + links[name] = read(); + local.insert(name); })); auto plist(plist_new_dict()); @@ -2097,7 +2119,7 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k bool old(&version.second == &rules1); - for (const auto &hash : local) + for (const auto &hash : hashes) for (const auto &rule : version.second) if (rule(hash.first)) { if (rule.mode_ == NestedMode) { @@ -2114,6 +2136,22 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k plist_dict_set_item(files, hash.first.c_str(), entry); } + break; + } + + for (const auto &link : links) + for (const auto &rule : version.second) + if (rule(link.first)) { + if (rule.mode_ == NestedMode) { + // XXX: implement + } else if (rule.mode_ != OmitMode) { + auto entry(plist_new_dict()); + plist_dict_set_item(entry, "symlink", plist_new_string(link.second.c_str())); + if (rule.mode_ == OptionalMode) + plist_dict_set_item(entry, "optional", plist_new_bool(true)); + plist_dict_set_item(files, link.first.c_str(), entry); + } + break; } } @@ -2158,7 +2196,7 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k } folder.Save(signature, NULL, fun([&](std::streambuf &save) { - HashProxy proxy(local[signature], save); + HashProxy proxy(hashes[signature], save); char *xml(NULL); uint32_t size; plist_to_xml(plist, &xml, &size); @@ -2169,21 +2207,24 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k folder.Open(executable, fun([&](std::streambuf &buffer, const void *flag) { folder.Save(executable, flag, fun([&](std::streambuf &save) { Slots slots; - slots[1] = local.at(info); - slots[3] = local.at(signature); - Sign(NULL, 0, buffer, local[executable], save, identifier, entitlements, requirement, key, slots); + slots[1] = hashes.at(info); + slots[3] = hashes.at(signature); + Sign(NULL, 0, buffer, hashes[executable], save, identifier, entitlements, requirement, key, slots); })); })); - for (const auto &hash : local) - remote[root + hash.first] = hash.second; + local.insert(signature); + local.insert(executable); + + for (const auto &name : local) + remote.insert(root + name); return executable; } std::string Bundle(const std::string &root, Folder &folder, const std::string &key, const std::string &entitlements, const std::string &requirement) { - std::map hashes; - return Bundle(root, folder, key, hashes, entitlements, requirement); + std::set local; + return Bundle(root, folder, key, local, entitlements, requirement); } #endif diff --git a/ldid.hpp b/ldid.hpp index 0257ff2..3765c9f 100644 --- a/ldid.hpp +++ b/ldid.hpp @@ -51,7 +51,7 @@ class Folder { public: virtual void Save(const std::string &path, const void *flag, const Functor &code) = 0; virtual bool Open(const std::string &path, const Functor &code) = 0; - virtual void Find(const std::string &path, const Functor &)> &)> &code) = 0; + virtual void Find(const std::string &path, const Functor &)> &)> &code, const Functor &)> &link) = 0; }; class DiskFolder : @@ -63,7 +63,7 @@ class DiskFolder : std::string Path(const std::string &path); - void Find(const std::string &root, const std::string &base, const Functor &)> &)>&code); + void Find(const std::string &root, const std::string &base, const Functor &)> &)> &code, const Functor &)> &link); public: DiskFolder(const std::string &path); @@ -71,7 +71,7 @@ class DiskFolder : virtual void Save(const std::string &path, const void *flag, const Functor &code); virtual bool Open(const std::string &path, const Functor &code); - virtual void Find(const std::string &path, const Functor &)> &)> &code); + virtual void Find(const std::string &path, const Functor &)> &)> &code, const Functor &)> &link); }; class SubFolder : @@ -86,7 +86,7 @@ class SubFolder : virtual void Save(const std::string &path, const void *flag, const Functor &code); virtual bool Open(const std::string &path, const Functor &code); - virtual void Find(const std::string &path, const Functor &)> &)> &code); + virtual void Find(const std::string &path, const Functor &)> &)> &code, const Functor &)> &link); }; class UnionFolder : @@ -120,7 +120,7 @@ class UnionFolder : virtual void Save(const std::string &path, const void *flag, const Functor &code); virtual bool Open(const std::string &path, const Functor &code); - virtual void Find(const std::string &path, const Functor &)> &)> &code); + virtual void Find(const std::string &path, const Functor &)> &)> &code, const Functor &)> &link); void operator ()(const std::string &from) { deletes_.insert(from); -- 2.47.1