X-Git-Url: https://git.saurik.com/ldid.git/blobdiff_plain/b6d8da4eedd3fa6c2a7365fa5396f6e961dc1c39..661226a83c9f0879c3c3064883b7a3d61dd4d6fa:/ldid.cpp diff --git a/ldid.cpp b/ldid.cpp index bfa97b4..b863b35 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -46,9 +46,26 @@ #include #include #include + +#ifdef __APPLE__ +#include +#define LDID_SHA1_DIGEST_LENGTH CC_SHA1_DIGEST_LENGTH +#define LDID_SHA1 CC_SHA1 +#define LDID_SHA1_CTX CC_SHA1_CTX +#define LDID_SHA1_Init CC_SHA1_Init +#define LDID_SHA1_Update CC_SHA1_Update +#define LDID_SHA1_Final CC_SHA1_Final +#else #include +#define LDID_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH +#define LDID_SHA1 SHA1 +#define LDID_SHA1_CTX SHA_CTX +#define LDID_SHA1_Init SHA1_Init +#define LDID_SHA1_Update SHA1_Update +#define LDID_SHA1_Final SHA1_Final +#endif -#include +#include #include "ldid.hpp" @@ -843,7 +860,7 @@ struct CodeDirectory { extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval); static void sha1(uint8_t *hash, const void *data, size_t size) { - SHA1(static_cast(data), size, hash); + LDID_SHA1(static_cast(data), size, hash); } struct CodesignAllocation { @@ -1317,22 +1334,22 @@ class HashBuffer : { private: std::vector &hash_; - SHA_CTX context_; + LDID_SHA1_CTX context_; public: HashBuffer(std::vector &hash) : hash_(hash) { - SHA1_Init(&context_); + LDID_SHA1_Init(&context_); } ~HashBuffer() { - hash_.resize(SHA_DIGEST_LENGTH); - SHA1_Final(reinterpret_cast(hash_.data()), &context_); + hash_.resize(LDID_SHA1_DIGEST_LENGTH); + LDID_SHA1_Final(reinterpret_cast(hash_.data()), &context_); } virtual std::streamsize xsputn(const char_type *data, std::streamsize size) { - SHA1_Update(&context_, data, size); + LDID_SHA1_Update(&context_, data, size); return size; } @@ -1455,7 +1472,7 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st special = std::max(special, slot.first); uint32_t normal((size + PageSize_ - 1) / PageSize_); - alloc = Align(alloc + (special + normal) * SHA_DIGEST_LENGTH, 16); + alloc = Align(alloc + (special + normal) * LDID_SHA1_DIGEST_LENGTH, 16); return alloc; }), fun([&](std::streambuf &output, size_t limit, const std::string &overlap, const char *top) -> size_t { Blobs blobs; @@ -1488,12 +1505,12 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st CodeDirectory directory; directory.version = Swap(uint32_t(0x00020001)); directory.flags = Swap(uint32_t(0)); - directory.hashOffset = Swap(uint32_t(sizeof(Blob) + sizeof(CodeDirectory) + identifier.size() + 1 + SHA_DIGEST_LENGTH * special)); + directory.hashOffset = Swap(uint32_t(sizeof(Blob) + sizeof(CodeDirectory) + identifier.size() + 1 + LDID_SHA1_DIGEST_LENGTH * special)); directory.identOffset = Swap(uint32_t(sizeof(Blob) + sizeof(CodeDirectory))); directory.nSpecialSlots = Swap(special); directory.codeLimit = Swap(uint32_t(limit)); directory.nCodeSlots = Swap(normal); - directory.hashSize = SHA_DIGEST_LENGTH; + directory.hashSize = LDID_SHA1_DIGEST_LENGTH; directory.hashType = CS_HASHTYPE_SHA1; directory.spare1 = 0x00; directory.pageSize = PageShift_; @@ -1502,8 +1519,8 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st put(data, identifier.c_str(), identifier.size() + 1); - uint8_t storage[special + normal][SHA_DIGEST_LENGTH]; - uint8_t (*hashes)[SHA_DIGEST_LENGTH] = storage + special; + uint8_t storage[special + normal][LDID_SHA1_DIGEST_LENGTH]; + uint8_t (*hashes)[LDID_SHA1_DIGEST_LENGTH] = storage + special; memset(storage, 0, sizeof(*storage) * special); @@ -1643,22 +1660,57 @@ void DiskFolder::Find(const std::string &path, const Functor &code) { - return parent_->Save(path_ + path, code); + return parent_.Save(path_ + path, code); } bool SubFolder::Open(const std::string &path, const Functor &code) { - return parent_->Open(path_ + path, code); + return parent_.Open(path_ + path, code); } void SubFolder::Find(const std::string &path, const Functor &)> &)> &code) { - return parent_->Find(path_ + path, code); + return parent_.Find(path_ + path, code); +} + +UnionFolder::UnionFolder(Folder &parent) : + parent_(parent) +{ +} + +void UnionFolder::Save(const std::string &path, const Functor &code) { + return parent_.Save(path, code); +} + +bool UnionFolder::Open(const std::string &path, const Functor &code) { + auto file(files_.find(path)); + if (file == files_.end()) + return parent_.Open(path, code); + + auto &data(file->second); + data.pubseekpos(0, std::ios::in); + code(data); + return true; +} + +void UnionFolder::Find(const std::string &path, const Functor &)> &)> &code) { + parent_.Find(path, fun([&](const std::string &name, const Functor &)> &save) { + if (files_.find(name) == files_.end()) + code(name, save); + })); + + for (auto &file : files_) + code(file.first, fun([&](const Functor &code) { + parent_.Save(file.first, fun([&](std::streambuf &save) { + file.second.pubseekpos(0, std::ios::in); + code(file.second, save); + })); + })); } static size_t copy(std::streambuf &source, std::streambuf &target) { @@ -1674,27 +1726,32 @@ static size_t copy(std::streambuf &source, std::streambuf &target) { return total; } -static PList::Structure *plist(const std::string &data) { - if (!Starts(data, "bplist00")) - return PList::Structure::FromXml(data); - std::vector bytes(data.data(), data.data() + data.size()); - return PList::Structure::FromBin(bytes); +static plist_t plist(const std::string &data) { + plist_t plist(NULL); + if (Starts(data, "bplist00")) + plist_from_bin(data.data(), data.size(), &plist); + else + plist_from_xml(data.data(), data.size(), &plist); + _assert(plist != NULL); + return plist; } -static void plist_d(std::streambuf &buffer, const Functor &code) { +static void plist_d(std::streambuf &buffer, const Functor &code) { std::stringbuf data; copy(buffer, data); - PList::Structure *structure(plist(data.str())); - _scope({ delete structure; }); - auto dictionary(dynamic_cast(structure)); - _assert(dictionary != NULL); - code(dictionary); + auto node(plist(data.str())); + _scope({ plist_free(node); }); + _assert(plist_get_node_type(node) == PLIST_DICT); + code(node); } -static std::string plist_s(PList::Node *node) { - auto value(dynamic_cast(node)); - _assert(value != NULL); - return value->GetValue(); +static std::string plist_s(plist_t node) { + _assert(node != NULL); + _assert(plist_get_node_type(node) == PLIST_STRING); + char *data; + plist_get_string_val(node, &data); + _scope({ free(data); }); + return data; } enum Mode { @@ -1772,16 +1829,16 @@ struct RuleCode { } }; -std::string Bundle(const std::string &root, Folder &folder, const std::string &key, std::map> &remote) { +std::string Bundle(const std::string &root, Folder &folder, const std::string &key, std::map> &remote, const std::string &entitlements) { std::string executable; std::string identifier; static const std::string info("Info.plist"); _assert_(folder.Open(info, fun([&](std::streambuf &buffer) { - plist_d(buffer, fun([&](PList::Dictionary *dictionary) { - executable = plist_s(((*dictionary)["CFBundleExecutable"])); - identifier = plist_s(((*dictionary)["CFBundleIdentifier"])); + plist_d(buffer, fun([&](plist_t node) { + executable = plist_s(plist_dict_get_item(node, "CFBundleExecutable")); + identifier = plist_s(plist_dict_get_item(node, "CFBundleIdentifier")); })); })), "open(): Info.plist"); @@ -1793,7 +1850,7 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k static const std::string signature("_CodeSignature/CodeResources"); folder.Open(signature, fun([&](std::streambuf &buffer) { - plist_d(buffer, fun([&](PList::Dictionary *dictionary) { + plist_d(buffer, fun([&](plist_t node) { // XXX: maybe attempt to preserve existing rules })); })); @@ -1832,8 +1889,8 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k if (!nested(name)) return; auto bundle(root + Split(name).dir); - SubFolder subfolder(&folder, bundle); - Bundle(bundle, subfolder, key, local); + SubFolder subfolder(folder, bundle); + Bundle(bundle, subfolder, key, local, ""); })); folder.Find("", fun([&](const std::string &name, const Functor &)> &code) { @@ -1849,13 +1906,15 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k copy(data, proxy); })); - _assert(hash.size() == SHA_DIGEST_LENGTH); + _assert(hash.size() == LDID_SHA1_DIGEST_LENGTH); })); - PList::Dictionary plist; + auto plist(plist_new_dict()); + _scope({ plist_free(plist); }); for (const auto &version : versions) { - PList::Dictionary files; + auto files(plist_new_dict()); + plist_dict_set_item(plist, ("files" + version.first).c_str(), files); for (const auto &rule : version.second) rule.Compile(); @@ -1864,22 +1923,21 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k for (const auto &rule : version.second) if (rule(hash.first)) { if (rule.mode_ == NoMode) - files.Set(hash.first, PList::Data(hash.second)); + plist_dict_set_item(files, hash.first.c_str(), plist_new_data(hash.second.data(), hash.second.size())); else if (rule.mode_ == OptionalMode) { - PList::Dictionary entry; - entry.Set("hash", PList::Data(hash.second)); - entry.Set("optional", PList::Boolean(true)); - files.Set(hash.first, entry); + auto entry(plist_new_dict()); + plist_dict_set_item(entry, "hash", plist_new_data(hash.second.data(), hash.second.size())); + plist_dict_set_item(entry, "optional", plist_new_bool(true)); + plist_dict_set_item(files, hash.first.c_str(), entry); } break; } - - plist.Set("files" + version.first, files); } for (const auto &version : versions) { - PList::Dictionary rules; + auto rules(plist_new_dict()); + plist_dict_set_item(plist, ("rules" + version.first).c_str(), rules); std::multiset ordered; for (const auto &rule : version.second) @@ -1887,42 +1945,42 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k for (const auto &rule : ordered) if (rule->weight_ == 1 && rule->mode_ == NoMode) - rules.Set(rule->code_, PList::Boolean(true)); + plist_dict_set_item(rules, rule->code_.c_str(), plist_new_bool(true)); else { - PList::Dictionary entry; + auto entry(plist_new_dict()); + plist_dict_set_item(rules, rule->code_.c_str(), entry); switch (rule->mode_) { case NoMode: break; case OmitMode: - entry.Set("omit", PList::Boolean(true)); + plist_dict_set_item(entry, "omit", plist_new_bool(true)); break; case OptionalMode: - entry.Set("optional", PList::Boolean(true)); + plist_dict_set_item(entry, "optional", plist_new_bool(true)); break; case NestedMode: - entry.Set("nested", PList::Boolean(true)); + plist_dict_set_item(entry, "nested", plist_new_bool(true)); break; case TopMode: - entry.Set("top", PList::Boolean(true)); + plist_dict_set_item(entry, "top", plist_new_bool(true)); break; } if (rule->weight_ >= 10000) - entry.Set("weight", PList::Integer(rule->weight_)); + plist_dict_set_item(entry, "weight", plist_new_uint(rule->weight_)); else if (rule->weight_ != 1) - entry.Set("weight", PList::Real(rule->weight_)); - - rules.Set(rule->code_, entry); + plist_dict_set_item(entry, "weight", plist_new_real(rule->weight_)); } - - plist.Set("rules" + version.first, rules); } folder.Save(signature, fun([&](std::streambuf &save) { HashProxy proxy(local[signature], save); - auto xml(plist.ToXml()); - put(proxy, xml.data(), xml.size()); + char *xml(NULL); + uint32_t size; + plist_to_xml(plist, &xml, &size); + _scope({ free(xml); }); + put(proxy, xml, size); })); folder.Open(executable, fun([&](std::streambuf &buffer) { @@ -1937,7 +1995,7 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k slots[3] = local.at(signature); HashProxy proxy(local[executable], save); - Sign(data.data(), data.size(), proxy, identifier, "", key, slots); + Sign(data.data(), data.size(), proxy, identifier, entitlements, key, slots); })); })); @@ -2015,7 +2073,7 @@ int main(int argc, char *argv[]) { unsigned number(strtoul(slot, &arge, 0)); _assert(arge == colon); std::vector &hash(slots[number]); - hash.resize(SHA_DIGEST_LENGTH); + hash.resize(LDID_SHA1_DIGEST_LENGTH); sha1(reinterpret_cast(hash.data()), file.data(), file.size()); } break; @@ -2096,7 +2154,7 @@ int main(int argc, char *argv[]) { _assert(!flag_r); ldid::DiskFolder folder(path); std::map> hashes; - path += "/" + Bundle("", folder, key, hashes); + path += "/" + Bundle("", folder, key, hashes, entitlements); } else if (flag_S || flag_r) { Map input(path, O_RDONLY, PROT_READ, MAP_PRIVATE); @@ -2193,7 +2251,7 @@ int main(int argc, char *argv[]) { uint32_t begin = Swap(super->index[index].offset); struct CodeDirectory *directory = reinterpret_cast(blob + begin); - uint8_t (*hashes)[SHA_DIGEST_LENGTH] = reinterpret_cast(blob + begin + Swap(directory->hashOffset)); + uint8_t (*hashes)[LDID_SHA1_DIGEST_LENGTH] = reinterpret_cast(blob + begin + Swap(directory->hashOffset)); uint32_t pages = Swap(directory->nCodeSlots); if (pages != 1)