X-Git-Url: https://git.saurik.com/ldid.git/blobdiff_plain/c4f8d24363d98bae2040ad3f4ddb1ff89e9f7636..9b693b3477abaa13b2915411a8ba77f77fe67c25:/ldid.cpp diff --git a/ldid.cpp b/ldid.cpp index 8010211..1eacfb7 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -982,6 +982,34 @@ class Map { namespace ldid { +std::string Analyze(const void *data, size_t size) { + std::string entitlements; + + FatHeader fat_header(const_cast(data), size); + _foreach (mach_header, fat_header.GetMachHeaders()) + _foreach (load_command, mach_header.GetLoadCommands()) + if (mach_header.Swap(load_command->cmd) == LC_CODE_SIGNATURE) { + auto signature(reinterpret_cast(load_command)); + auto offset(mach_header.Swap(signature->dataoff)); + auto pointer(reinterpret_cast(mach_header.GetBase()) + offset); + auto super(reinterpret_cast(pointer)); + + for (size_t index(0); index != Swap(super->count); ++index) + if (Swap(super->index[index].type) == CSSLOT_ENTITLEMENTS) { + auto begin(Swap(super->index[index].offset)); + auto blob(reinterpret_cast(pointer + begin)); + auto writ(Swap(blob->length) - sizeof(*blob)); + + if (entitlements.empty()) + entitlements.assign(reinterpret_cast(blob + 1), writ); + else + _assert(entitlements.compare(0, entitlements.size(), reinterpret_cast(blob + 1), writ) == 0); + } + } + + return entitlements; +} + static void Allocate(const void *idata, size_t isize, std::streambuf &output, const Functor &allocate, const Functor &save) { FatHeader source(const_cast(idata), isize); @@ -1353,6 +1381,11 @@ class NullBuffer : } }; +class Digest { + public: + uint8_t sha1_[LDID_SHA1_DIGEST_LENGTH]; +}; + class Hash { public: char sha1_[LDID_SHA1_DIGEST_LENGTH]; @@ -1624,14 +1657,14 @@ std::vector Sign(const void *idata, size_t isize, std::streambuf &output, if (!team.empty()) put(data, team.c_str(), team.size() + 1); - uint8_t storage[special + normal][LDID_SHA1_DIGEST_LENGTH]; - uint8_t (*hashes)[LDID_SHA1_DIGEST_LENGTH] = storage + special; + std::vector storage(special + normal); + auto *hashes(&storage[special]); - memset(storage, 0, sizeof(*storage) * special); + memset(storage.data(), 0, sizeof(Digest) * special); _foreach (blob, blobs) { auto local(reinterpret_cast(&blob.second[0])); - sha1((uint8_t *) (hashes - blob.first), local, Swap(local->length)); + sha1((hashes - blob.first)->sha1_, local, Swap(local->length)); } _foreach (slot, posts) { @@ -1641,11 +1674,11 @@ std::vector Sign(const void *idata, size_t isize, std::streambuf &output, if (normal != 1) for (size_t i = 0; i != normal - 1; ++i) - sha1(hashes[i], (PageSize_ * i < overlap.size() ? overlap.data() : top) + PageSize_ * i, PageSize_); + sha1(hashes[i].sha1_, (PageSize_ * i < overlap.size() ? overlap.data() : top) + PageSize_ * i, PageSize_); if (normal != 0) - sha1(hashes[normal - 1], top + PageSize_ * (normal - 1), ((limit - 1) % PageSize_) + 1); + sha1(hashes[normal - 1].sha1_, top + PageSize_ * (normal - 1), ((limit - 1) % PageSize_) + 1); - put(data, storage, sizeof(storage)); + put(data, storage.data(), sizeof(Digest) * storage.size()); const auto &save(insert(blobs, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY, data)); sha1(hash, save.data(), save.size()); @@ -2028,7 +2061,7 @@ static std::vector Sign(const uint8_t *prefix, size_t size, std::streambuf return Sign(data.data(), data.size(), proxy, identifier, entitlements, requirement, key, slots); } -Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std::map &remote, const std::string &entitlements, const std::string &requirement) { +Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std::map &remote, const std::string &requirement, const Functor &alter) { std::string executable; std::string identifier; @@ -2052,6 +2085,17 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std mac = true; } + std::string entitlements; + folder.Open(executable, fun([&](std::streambuf &buffer, const void *flag) { + // XXX: this is a miserable fail + std::stringbuf temp; + auto size(copy(buffer, temp)); + // XXX: this is a stupid hack + pad(temp, 0x10 - (size & 0xf)); + auto data(temp.str()); + entitlements = alter(root, Analyze(data.data(), data.size())); + })); + static const std::string directory("_CodeSignature/"); static const std::string signature(directory + "CodeResources"); @@ -2100,7 +2144,9 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std auto bundle(root + Split(name).dir); bundle.resize(bundle.size() - resources.size()); SubFolder subfolder(folder, bundle); - bundles[nested[1]] = Sign(bundle, subfolder, key, local, "", ""); + + bundles[nested[1]] = Sign(bundle, subfolder, key, local, "", Starts(name, "PlugIns/") ? alter : + static_cast &>(fun([&](const std::string &, const std::string &entitlements) -> std::string { return entitlements; }))); }), fun([&](const std::string &name, const Functor &read) { })); @@ -2287,9 +2333,9 @@ Bundle Sign(const std::string &root, Folder &folder, const std::string &key, std return bundle; } -Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &entitlements, const std::string &requirement) { +Bundle Sign(const std::string &root, Folder &folder, const std::string &key, const std::string &requirement, const Functor &alter) { std::map local; - return Sign(root, folder, key, local, entitlements, requirement); + return Sign(root, folder, key, local, requirement, alter); } #endif @@ -2466,7 +2512,7 @@ int main(int argc, char *argv[]) { #ifndef LDID_NOPLIST _assert(!flag_r); ldid::DiskFolder folder(path); - path += "/" + Sign("", folder, key, entitlements, requirement).path; + path += "/" + Sign("", folder, key, requirement, ldid::fun([&](const std::string &, const std::string &) -> std::string { return entitlements; })).path; #else _assert(false); #endif