X-Git-Url: https://git.saurik.com/apple/libsecurity_codesigning.git/blobdiff_plain/d1c1ab47a3465a37e4c243f7a5b11b92737d5b76..refs/heads/master:/lib/SecStaticCode.cpp diff --git a/lib/SecStaticCode.cpp b/lib/SecStaticCode.cpp index e56d188..7cb5a17 100644 --- a/lib/SecStaticCode.cpp +++ b/lib/SecStaticCode.cpp @@ -28,6 +28,7 @@ #include "StaticCode.h" #include #include +#include using namespace CodeSigning; @@ -91,16 +92,31 @@ OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flag // // Check static validity of a StaticCode // +static void validate(SecStaticCode *code, const SecRequirement *req, SecCSFlags flags); +static void validateNested(string location, const SecRequirement *req, SecCSFlags flags, string exclude = "/"); + static void validate(SecStaticCode *code, const SecRequirement *req, SecCSFlags flags) { try { - code->validateDirectory(); + code->validateNonResourceComponents(); // also validates the CodeDirectory if (!(flags & kSecCSDoNotValidateExecutable)) code->validateExecutable(); if (!(flags & kSecCSDoNotValidateResources)) code->validateResources(); if (req) code->validateRequirement(req->requirement(), errSecCSReqFailed); + if (flags & kSecCSCheckNestedCode) + if (CFURLRef baseUrl = code->resourceBase()) { + // CFBundle has no orderly enumerator of these things, so this is somewhat ad-hoc. + // (It should be augmented by information in ResourceDirectory.) + string base = cfString(baseUrl) + "/"; + validateNested(base + "Frameworks", req, flags); + validateNested(base + "SharedFrameworks", req, flags); + validateNested(base + "PlugIns", req, flags); + validateNested(base + "Plug-ins", req, flags); + validateNested(base + "XPCServices", req, flags); + validateNested(base + "MacOS", req, flags, code->mainExecutablePath()); // helpers + } } catch (CSError &err) { if (Universal *fat = code->diskRep()->mainExecutableImage()) // Mach-O if (MachO *mach = fat->architecture()) { @@ -121,6 +137,40 @@ static void validate(SecStaticCode *code, const SecRequirement *req, SecCSFlags } } +static void validateNested(string location, const SecRequirement *req, SecCSFlags flags, string exclude) +{ + DIR *dir = opendir(location.c_str()); + if (dir == 0) { + if (errno == ENOENT) // nothing there (okay) + return; + UnixError::throwMe(); + } + while (struct dirent *dp = readdir(dir)) { + switch (dp->d_type) { + case DT_REG: + case DT_LNK: + case DT_DIR: + break; + default: + continue; + } + if (dp->d_name[0] == '.') + continue; + string path = location + "/" + dp->d_name; + if (path == exclude) // main executable; skip + continue; + try { + SecPointer code = new SecStaticCode(DiskRep::bestGuess(path)); + validate(code, req, flags); + } catch (CSError &err) { + err.augment(kSecCFErrorPath, CFTempURL(path)); + throw; + } + } + closedir(dir); +} + + OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCodeRef, SecCSFlags flags, SecRequirementRef requirementRef) { @@ -136,7 +186,9 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se kSecCSCheckAllArchitectures | kSecCSDoNotValidateExecutable | kSecCSDoNotValidateResources - | kSecCSConsiderExpiration); + | kSecCSConsiderExpiration + | kSecCSEnforceRevocationChecks + | kSecCSCheckNestedCode); SecPointer code = SecStaticCode::requiredStatic(staticCodeRef); const SecRequirement *req = SecRequirement::optional(requirementRef);