#include "codesign.h"
#include <Security/SecRequirementPriv.h>
#include <Security/SecCodePriv.h>
#include <sys/codesign.h>
using namespace UnixPlusPlus;
static void displayGuestChain(SecCodeRef code);
SecRequirementRef testReqs;
void prepareToVerify()
{
if (testReq)
testReqs = readRequirement(testReq);
}
void verify(const char *target)
{
CFRef<SecCodeRef> code = codePath(target); CFRef<SecStaticCodeRef> staticCode;
if (code)
MacOSError::check(SecCodeCopyStaticCode(code, kSecCSDefaultFlags, &staticCode.aref()));
else
MacOSError::check(SecStaticCodeCreateWithPath(CFTempURL(target), kSecCSDefaultFlags, &staticCode.aref()));
if (detached)
if (CFRef<CFDataRef> dsig = cfLoadFile(detached))
MacOSError::check(SecCodeSetDetachedSignature(staticCode, dsig, kSecCSDefaultFlags));
else
fail("%s: cannot load detached signature", detached);
if (code) {
ErrorCheck check;
check(SecCodeCheckValidityWithErrors(code, kSecCSDefaultFlags, NULL, check));
note(1, "%s: dynamically valid", target);
}
if (!code || verbose > 0) { ErrorCheck check;
check(SecStaticCodeCheckValidityWithErrors(staticCode, verifyOptions, NULL, check));
if (verifyOptions & kSecCSBasicValidateOnly)
note(1, "%s: valid on disk (not all contents verified)", target);
else
note(1, "%s: valid on disk", target);
}
if (verbose > 0) { CFRef<SecRequirementRef> designated = NULL;
if (OSStatus rc = SecCodeCopyDesignatedRequirement(staticCode, kSecCSDefaultFlags, &designated.aref())) {
cssmPerror(target, rc);
fail("%s: cannot retrieve designated requirement", target);
} else if (rc = SecStaticCodeCheckValidity(staticCode, kSecCSBasicValidateOnly, designated)) {
note(0, "%s: does not satisfy its designated Requirement", target);
if (!exitcode)
exitcode = exitNoverify;
} else
note(1, "%s: satisfies its Designated Requirement", target);
}
if (testReqs) { if (OSStatus rc = SecStaticCodeCheckValidity(staticCode, verifyOptions, testReqs)) {
cssmPerror("test-requirement", rc);
if (!exitcode)
exitcode = exitNoverify;
} else {
note(1, "%s: explicit requirement satisfied", target);
}
}
}
void hostinginfo(const char *target)
{
CFRef<SecCodeRef> code = codePath(target);
if (!code)
fail("%s: not a dynamic code specification", target);
do {
CFDictionary info(noErr);
MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDynamicInformation, &info.aref()));
printf("%s", cfString(info.get<CFURLRef>(kSecCodeInfoMainExecutable)).c_str());
if (verbose > 0) {
printf("\t");
if (info.get<CFStringRef>(kSecCodeInfoIdentifier))
printf("(");
else
printf("UNSIGNED (");
if (CFNumberRef state = info.get<CFNumberRef>(kSecCodeInfoStatus)) {
uint32_t status = cfNumber(state);
if (status & CS_VALID)
printf("valid");
else
printf("INVALID");
if (status & CS_KILL)
printf(" kill");
if (status & CS_HARD)
printf(" hard");
if (status & ~(CS_VALID | CS_KILL | CS_HARD)) printf(" 0x%x", status);
} else
printf("UNKNOWN");
printf(")");
}
printf("\n");
CFRef<SecCodeRef> host;
MacOSError::check(SecCodeCopyHost(code, kSecCSDefaultFlags, &host.aref()));
code = host;
} while (code);
}