X-Git-Url: https://git.saurik.com/ldid.git/blobdiff_plain/8dfe0afc0d0d6b99d433e62c83485fe3fb97fb76..35229d065ce164cc3d8a3b37446f27c9d85deddc:/ldid.cpp?ds=inline diff --git a/ldid.cpp b/ldid.cpp index c59ecdb..4ac0012 100644 --- a/ldid.cpp +++ b/ldid.cpp @@ -42,13 +42,34 @@ #include #include +#ifndef LDID_NOSMIME #include #include #include #include +#endif + +#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 +#ifndef LDID_NOPLIST #include +#endif #include "ldid.hpp" @@ -57,11 +78,20 @@ #define _assert__(line) \ _assert___(line) +#ifdef __EXCEPTIONS #define _assert_(expr, format, ...) \ do if (!(expr)) { \ fprintf(stderr, "%s(%u): _assert(): " format "\n", __FILE__, __LINE__, ## __VA_ARGS__); \ throw __FILE__ "(" _assert__(__LINE__) "): _assert(" #expr ")"; \ } while (false) +#else +// XXX: this is not acceptable +#define _assert_(expr, format, ...) \ + do if (!(expr)) { \ + fprintf(stderr, "%s(%u): _assert(): " format "\n", __FILE__, __LINE__, ## __VA_ARGS__); \ + exit(-1); \ + } while (false) +#endif #define _assert(expr) \ _assert_(expr, "%s", #expr) @@ -135,6 +165,27 @@ Scope _scope(const Function_ &function) { #define _scope(function) \ _scope_(__COUNTER__, function) +#define CPU_ARCH_MASK uint32_t(0xff000000) +#define CPU_ARCH_ABI64 uint32_t(0x01000000) + +#define CPU_TYPE_ANY uint32_t(-1) +#define CPU_TYPE_VAX uint32_t( 1) +#define CPU_TYPE_MC680x0 uint32_t( 6) +#define CPU_TYPE_X86 uint32_t( 7) +#define CPU_TYPE_MC98000 uint32_t(10) +#define CPU_TYPE_HPPA uint32_t(11) +#define CPU_TYPE_ARM uint32_t(12) +#define CPU_TYPE_MC88000 uint32_t(13) +#define CPU_TYPE_SPARC uint32_t(14) +#define CPU_TYPE_I860 uint32_t(15) +#define CPU_TYPE_POWERPC uint32_t(18) + +#define CPU_TYPE_I386 CPU_TYPE_X86 + +#define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM) +#define CPU_TYPE_POWERPC64 (CPU_ARCH_ABI64 | CPU_TYPE_POWERPC) +#define CPU_TYPE_X86_64 (CPU_ARCH_ABI64 | CPU_TYPE_X86) + struct fat_header { uint32_t magic; uint32_t nfat_arch; @@ -197,6 +248,16 @@ struct load_command { #define LC_DYLD_INFO_ONLY uint32_t(0x22 | LC_REQ_DYLD) #define LC_ENCRYPTION_INFO_64 uint32_t(0x2c) +union Version { + struct { + uint8_t patch; + uint8_t minor; + uint16_t major; + } _packed; + + uint32_t value; +}; + struct dylib { uint32_t name; uint32_t timestamp; @@ -364,6 +425,7 @@ struct section_64 { uint32_t flags; uint32_t reserved1; uint32_t reserved2; + uint32_t reserved3; } _packed; struct linkedit_data_command { @@ -481,9 +543,6 @@ static inline int64_t Swap(int64_t value) { return Swap(static_cast(value)); } -template -class Pointer; - class Swapped { protected: bool swapped_; @@ -608,85 +667,30 @@ class MachHeader : return load_commands; } - std::vector GetSegments(const char *segment_name) const { - std::vector segment_commands; - - _foreach (load_command, GetLoadCommands()) { - if (Swap(load_command->cmd) == LC_SEGMENT) { - segment_command *segment_command = reinterpret_cast(load_command); - if (strncmp(segment_command->segname, segment_name, 16) == 0) - segment_commands.push_back(segment_command); - } - } - - return segment_commands; - } - - std::vector GetSegments64(const char *segment_name) const { - std::vector segment_commands; - - _foreach (load_command, GetLoadCommands()) { - if (Swap(load_command->cmd) == LC_SEGMENT_64) { - segment_command_64 *segment_command = reinterpret_cast(load_command); - if (strncmp(segment_command->segname, segment_name, 16) == 0) - segment_commands.push_back(segment_command); - } - } - - return segment_commands; - } - - std::vector
GetSections(const char *segment_name, const char *section_name) const { - std::vector
sections; - - _foreach (segment, GetSegments(segment_name)) { - section *section = (struct section *) (segment + 1); + void ForSection(const ldid::Functor &code) const { + _foreach (load_command, GetLoadCommands()) + switch (Swap(load_command->cmd)) { + case LC_SEGMENT: { + auto segment(reinterpret_cast(load_command)); + code(segment->segname, NULL, GetOffset(segment->fileoff), segment->filesize); + auto section(reinterpret_cast(segment + 1)); + for (uint32_t i(0), e(Swap(segment->nsects)); i != e; ++i, ++section) + code(segment->segname, section->sectname, GetOffset(segment->fileoff + section->offset), section->size); + } break; - uint32_t sect; - for (sect = 0; sect != Swap(segment->nsects); ++sect) { - if (strncmp(section->sectname, section_name, 16) == 0) - sections.push_back(section); - ++section; + case LC_SEGMENT_64: { + auto segment(reinterpret_cast(load_command)); + code(segment->segname, NULL, GetOffset(segment->fileoff), segment->filesize); + auto section(reinterpret_cast(segment + 1)); + for (uint32_t i(0), e(Swap(segment->nsects)); i != e; ++i, ++section) + code(segment->segname, section->sectname, GetOffset(segment->fileoff + section->offset), section->size); + } break; } - } - - return sections; } template - Pointer GetPointer(uint32_t address, const char *segment_name = NULL) const { - load_command *load_command = (struct load_command *) (mach_header_ + 1); - uint32_t cmd; - - for (cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) { - if (Swap(load_command->cmd) == LC_SEGMENT) { - segment_command *segment_command = (struct segment_command *) load_command; - if (segment_name != NULL && strncmp(segment_command->segname, segment_name, 16) != 0) - goto next_command; - - section *sections = (struct section *) (segment_command + 1); - - uint32_t sect; - for (sect = 0; sect != Swap(segment_command->nsects); ++sect) { - section *section = §ions[sect]; - //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size); - if (address >= Swap(section->addr) && address < Swap(section->addr) + Swap(section->size)) { - //printf("0x%.8x %s\n", address, segment_command->segname); - return Pointer(this, reinterpret_cast(address - Swap(section->addr) + Swap(section->offset) + (char *) mach_header_)); - } - } - } - - next_command: - load_command = (struct load_command *) ((char *) load_command + Swap(load_command->cmdsize)); - } - - return Pointer(this); - } - - template - Pointer GetOffset(uint32_t offset) { - return Pointer(this, reinterpret_cast(offset + (uint8_t *) mach_header_)); + Target_ *GetOffset(uint32_t offset) const { + return reinterpret_cast(offset + (uint8_t *) mach_header_); } }; @@ -757,38 +761,6 @@ class FatHeader : } }; -template -class Pointer { - private: - const MachHeader *framework_; - const Target_ *pointer_; - - public: - Pointer(const MachHeader *framework = NULL, const Target_ *pointer = NULL) : - framework_(framework), - pointer_(pointer) - { - } - - operator const Target_ *() const { - return pointer_; - } - - const Target_ *operator ->() const { - return pointer_; - } - - Pointer &operator ++() { - ++pointer_; - return *this; - } - - template - Value_ Swap(Value_ value) { - return framework_->Swap(value); - } -}; - #define CSMAGIC_REQUIREMENT uint32_t(0xfade0c00) #define CSMAGIC_REQUIREMENTS uint32_t(0xfade0c01) #define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02) @@ -840,10 +812,17 @@ struct CodeDirectory { uint32_t spare2; } _packed; +#ifndef LDID_NOFLAGT extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval); +#endif 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); +} + +static void sha1(std::vector &hash, const void *data, size_t size) { + hash.resize(LDID_SHA1_DIGEST_LENGTH); + sha1(reinterpret_cast(hash.data()), data, size); } struct CodesignAllocation { @@ -865,6 +844,7 @@ struct CodesignAllocation { } }; +#ifndef LDID_NOTOOLS class File { private: int file_; @@ -963,10 +943,11 @@ class Map { return std::string(static_cast(data_), size_); } }; +#endif namespace ldid { -static void Allocate(const void *idata, size_t isize, std::streambuf &output, const Functor &allocate, const Functor &save) { +static void Allocate(const void *idata, size_t isize, std::streambuf &output, const Functor &allocate, const Functor &save) { FatHeader source(const_cast(idata), isize); size_t offset(0); @@ -1002,10 +983,29 @@ static void Allocate(const void *idata, size_t isize, std::streambuf &output, co size = end; } - size_t alloc(allocate(size)); + size_t alloc(allocate(mach_header, size)); auto *fat_arch(mach_header.GetFatArch()); - uint32_t align(fat_arch == NULL ? 0 : source.Swap(fat_arch->align)); + uint32_t align; + + if (fat_arch != NULL) + align = source.Swap(fat_arch->align); + else switch (mach_header.GetCPUType()) { + case CPU_TYPE_POWERPC: + case CPU_TYPE_POWERPC64: + case CPU_TYPE_X86: + case CPU_TYPE_X86_64: + align = 0xc; + break; + case CPU_TYPE_ARM: + case CPU_TYPE_ARM64: + align = 0xe; + break; + default: + align = 0x0; + break; + } + offset = Align(offset, 1 << align); uint32_t limit(size); @@ -1062,7 +1062,7 @@ static void Allocate(const void *idata, size_t isize, std::streambuf &output, co break; size_t size(mach_header.Swap(allocation.limit_ + allocation.alloc_ - mach_header.Swap(segment_command->fileoff))); segment_command->filesize = size; - segment_command->vmsize = Align(size, PageSize_); + segment_command->vmsize = Align(size, 1 << allocation.align_); } break; case LC_SEGMENT_64: { @@ -1071,7 +1071,7 @@ static void Allocate(const void *idata, size_t isize, std::streambuf &output, co break; size_t size(mach_header.Swap(allocation.limit_ + allocation.alloc_ - mach_header.Swap(segment_command->fileoff))); segment_command->filesize = size; - segment_command->vmsize = Align(size, PageSize_); + segment_command->vmsize = Align(size, 1 << allocation.align_); } break; } @@ -1133,7 +1133,7 @@ static void Allocate(const void *idata, size_t isize, std::streambuf &output, co pad(output, allocation.limit_ - allocation.size_); position += allocation.limit_ - allocation.size_; - size_t saved(save(output, allocation.limit_, overlap, top)); + size_t saved(save(mach_header, output, allocation.limit_, overlap, top)); if (allocation.alloc_ > saved) pad(output, allocation.alloc_ - saved); position += allocation.alloc_; @@ -1185,6 +1185,7 @@ static size_t put(std::streambuf &output, uint32_t magic, const Blobs &blobs) { return offset; } +#ifndef LDID_NOSMIME class Buffer { private: BIO *bio_; @@ -1298,6 +1299,7 @@ class Signature { return value_; } }; +#endif class NullBuffer : public std::streambuf @@ -1317,22 +1319,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; } @@ -1364,6 +1366,7 @@ class HashProxy : } }; +#ifndef LDID_NOTOOLS static bool Starts(const std::string &lhs, const std::string &rhs) { return lhs.size() >= rhs.size() && lhs.compare(0, rhs.size(), rhs) == 0; } @@ -1418,11 +1421,12 @@ static void Commit(const std::string &path, const std::string &temp) { _syscall(rename(temp.c_str(), path.c_str())); } +#endif namespace ldid { void Sign(const void *idata, size_t isize, std::streambuf &output, const std::string &identifier, const std::string &entitlements, const std::string &key, const Slots &slots) { - Allocate(idata, isize, output, fun([&](size_t size) -> size_t { + Allocate(idata, isize, output, fun([&](const MachHeader &mach_header, size_t size) -> size_t { size_t alloc(sizeof(struct SuperBlob)); uint32_t special(0); @@ -1454,10 +1458,15 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st _foreach (slot, slots) special = std::max(special, slot.first); + mach_header.ForSection(fun([&](const char *segment, const char *section, void *data, size_t size) { + if (strcmp(segment, "__TEXT") == 0 && section != NULL && strcmp(section, "__info_plist") == 0) + special = std::max(special, CSSLOT_INFOSLOT); + })); + 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 { + }), fun([&](const MachHeader &mach_header, std::streambuf &output, size_t limit, const std::string &overlap, const char *top) -> size_t { Blobs blobs; if (true) { @@ -1478,22 +1487,29 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st if (true) { std::stringbuf data; + Slots posts(slots); + + mach_header.ForSection(fun([&](const char *segment, const char *section, void *data, size_t size) { + if (strcmp(segment, "__TEXT") == 0 && section != NULL && strcmp(section, "__info_plist") == 0) + sha1(posts[CSSLOT_INFOSLOT], data, size); + })); + uint32_t special(0); _foreach (blob, blobs) special = std::max(special, blob.first); - _foreach (slot, slots) + _foreach (slot, posts) special = std::max(special, slot.first); uint32_t normal((limit + PageSize_ - 1) / PageSize_); 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 +1518,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); @@ -1512,7 +1528,7 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st sha1((uint8_t *) (hashes - blob.first), local, Swap(local->length)); } - _foreach (slot, slots) { + _foreach (slot, posts) { _assert(sizeof(*hashes) == slot.second.size()); memcpy(hashes - slot.first, slot.second.data(), slot.second.size()); } @@ -1528,6 +1544,7 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st insert(blobs, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY, data); } +#ifndef LDID_NOSMIME if (!key.empty()) { std::stringbuf data; const std::string &sign(blobs[CSSLOT_CODEDIRECTORY]); @@ -1542,15 +1559,17 @@ void Sign(const void *idata, size_t isize, std::streambuf &output, const std::st insert(blobs, CSSLOT_SIGNATURESLOT, CSMAGIC_BLOBWRAPPER, data); } +#endif return put(output, CSMAGIC_EMBEDDED_SIGNATURE, blobs); })); } +#ifndef LDID_NOTOOLS static void Unsign(void *idata, size_t isize, std::streambuf &output) { - Allocate(idata, isize, output, fun([](size_t size) -> size_t { + Allocate(idata, isize, output, fun([](const MachHeader &mach_header, size_t size) -> size_t { return 0; - }), fun([](std::streambuf &output, size_t limit, const std::string &overlap, const char *top) -> size_t { + }), fun([](const MachHeader &mach_header, std::streambuf &output, size_t limit, const std::string &overlap, const char *top) -> size_t { return 0; })); } @@ -1642,25 +1661,63 @@ bool DiskFolder::Open(const std::string &path, const Functor &)> &)>&code) { Find(path, "", code); } +#endif -SubFolder::SubFolder(Folder *parent, const std::string &path) : +SubFolder::SubFolder(Folder &parent, const std::string &path) : parent_(parent), path_(path) { } void SubFolder::Save(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(path + name) == files_.end()) + code(name, save); + })); + + for (auto &file : files_) + if (file.first.size() >= path.size() && file.first.substr(0, path.size()) == path) + code(file.first.substr(path.size()), fun([&](const Functor &code) { + parent_.Save(file.first, fun([&](std::streambuf &save) { + file.second.pubseekpos(0, std::ios::in); + code(file.second, save); + })); + })); } +#ifndef LDID_NOTOOLS static size_t copy(std::streambuf &source, std::streambuf &target) { size_t total(0); for (;;) { @@ -1674,6 +1731,7 @@ static size_t copy(std::streambuf &source, std::streambuf &target) { return total; } +#ifndef LDID_NOPLIST static plist_t plist(const std::string &data) { plist_t plist(NULL); if (Starts(data, "bplist00")) @@ -1701,6 +1759,7 @@ static std::string plist_s(plist_t node) { _scope({ free(data); }); return data; } +#endif enum Mode { NoMode, @@ -1777,7 +1836,8 @@ struct RuleCode { } }; -std::string Bundle(const std::string &root, Folder &folder, const std::string &key, std::map> &remote) { +#ifndef LDID_NOPLIST +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; @@ -1837,8 +1897,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) { @@ -1854,7 +1914,7 @@ 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); })); auto plist(plist_new_dict()); @@ -1943,7 +2003,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); })); })); @@ -1952,11 +2012,16 @@ std::string Bundle(const std::string &root, Folder &folder, const std::string &k return executable; } +#endif +#endif } +#ifndef LDID_NOTOOLS int main(int argc, char *argv[]) { +#ifndef LDID_NOSMIME OpenSSL_add_all_algorithms(); +#endif union { uint16_t word; @@ -1968,7 +2033,9 @@ int main(int argc, char *argv[]) { bool flag_r(false); bool flag_e(false); +#ifndef LDID_NOFLAGT bool flag_T(false); +#endif bool flag_S(false); bool flag_s(false); @@ -1978,13 +2045,17 @@ int main(int argc, char *argv[]) { bool flag_A(false); bool flag_a(false); + bool flag_u(false); + uint32_t flag_CPUType(_not(uint32_t)); uint32_t flag_CPUSubtype(_not(uint32_t)); const char *flag_I(NULL); +#ifndef LDID_NOFLAGT bool timeh(false); uint32_t timev(0); +#endif Map entitlements; Map key; @@ -2020,9 +2091,7 @@ int main(int argc, char *argv[]) { char *arge; unsigned number(strtoul(slot, &arge, 0)); _assert(arge == colon); - std::vector &hash(slots[number]); - hash.resize(SHA_DIGEST_LENGTH); - sha1(reinterpret_cast(hash.data()), file.data(), file.size()); + sha1(slots[number], file.data(), file.size()); } break; case 'D': flag_D = true; break; @@ -2061,9 +2130,11 @@ int main(int argc, char *argv[]) { break; case 'K': - key.open(argv[argi] + 2, O_RDONLY, PROT_READ, MAP_PRIVATE); + if (argv[argi][2] != '\0') + key.open(argv[argi] + 2, O_RDONLY, PROT_READ, MAP_PRIVATE); break; +#ifndef LDID_NOFLAGT case 'T': { flag_T = true; if (argv[argi][2] == '-') @@ -2074,6 +2145,11 @@ int main(int argc, char *argv[]) { _assert(arge == argv[argi] + strlen(argv[argi])); } } break; +#endif + + case 'u': { + flag_u = true; + } break; case 'I': { flag_I = argv[argi] + 2; @@ -2099,10 +2175,14 @@ int main(int argc, char *argv[]) { _syscall(stat(path.c_str(), &info)); if (S_ISDIR(info.st_mode)) { +#ifndef LDID_NOPLIST _assert(!flag_r); ldid::DiskFolder folder(path); std::map> hashes; - path += "/" + Bundle("", folder, key, hashes); + path += "/" + Bundle("", folder, key, hashes, entitlements); +#else + _assert(false); +#endif } else if (flag_S || flag_r) { Map input(path, O_RDONLY, PROT_READ, MAP_PRIVATE); @@ -2120,7 +2200,15 @@ int main(int argc, char *argv[]) { Commit(path, temp); } - Map mapping(path, flag_T || flag_s); + bool modify(false); +#ifndef LDID_NOFLAGT + if (flag_T) + modify = true; +#endif + if (flag_s) + modify = true; + + Map mapping(path, modify); FatHeader fat_header(mapping.data(), mapping.size()); _foreach (mach_header, fat_header.GetMachHeaders()) { @@ -2145,6 +2233,19 @@ int main(int argc, char *argv[]) { signature = reinterpret_cast(load_command); else if (cmd == LC_ENCRYPTION_INFO || cmd == LC_ENCRYPTION_INFO_64) encryption = reinterpret_cast(load_command); + else if (cmd == LC_LOAD_DYLIB) { + volatile struct dylib_command *dylib_command(reinterpret_cast(load_command)); + const char *name(reinterpret_cast(load_command) + mach_header.Swap(dylib_command->dylib.name)); + + if (strcmp(name, "/System/Library/Frameworks/UIKit.framework/UIKit") == 0) { + if (flag_u) { + Version version; + version.value = mach_header.Swap(dylib_command->dylib.current_version); + printf("uikit=%u.%u.%u\n", version.major, version.minor, version.patch); + } + } + } +#ifndef LDID_NOFLAGT else if (cmd == LC_ID_DYLIB) { volatile struct dylib_command *dylib_command(reinterpret_cast(load_command)); @@ -2161,6 +2262,7 @@ int main(int argc, char *argv[]) { dylib_command->dylib.timestamp = mach_header.Swap(timed); } } +#endif } if (flag_D) { @@ -2199,7 +2301,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) @@ -2219,3 +2321,4 @@ int main(int argc, char *argv[]) { return filee; } +#endif