X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/d64be36ead0ce792f249208635bc8db368d6cdd2..67d61d2eddbf13b089421b1c08b0353e50c467d7:/RegressionTests/secsecstaticcodeapitest.c diff --git a/RegressionTests/secsecstaticcodeapitest.c b/RegressionTests/secsecstaticcodeapitest.c new file mode 100644 index 00000000..3dc2b590 --- /dev/null +++ b/RegressionTests/secsecstaticcodeapitest.c @@ -0,0 +1,229 @@ +// +// secsecstaticcodeapitest.c +// secsecstaticcodeapitest +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BEGIN() \ +({ \ + fprintf(stdout, "[BEGIN] %s\n", __FUNCTION__); \ +}) + +#define INFO(fmt, ...) \ +({ \ + fprintf(stdout, fmt "\n", ##__VA_ARGS__); \ +}) + +#define PASS(fmt, ...) \ +({ \ + fprintf(stdout, "[PASS] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define FAIL(fmt, ...) \ +({ \ + fprintf(stdout, "[FAIL] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define SAFE_RELEASE(x) \ +({ \ + if (x) { \ + CFRelease(x); \ + x = NULL; \ + } \ +}) + +#define kCommandRedirectOutputToDevNULL " >/dev/null 2>&1" +#define BUILD_COMMAND(x) x kCommandRedirectOutputToDevNULL + +#define kFAT32DiskImageFileDirectory "/tmp" +#define kFAT32DiskImageFileName "Security_SecStaticCodeAPITest.dmg" +#define kFAT32DiskImageFilePath kFAT32DiskImageFileDirectory "/" kFAT32DiskImageFileName + +#define kFAT32DiskImageVolumeDirectory "/Volumes" +#define kFAT32DiskImageVolumeName "SEC_TEST" +#define kFAT32DiskImageVolumePath kFAT32DiskImageVolumeDirectory "/" kFAT32DiskImageVolumeName + +#define kApplicationsPath "/Applications" +#define kSafariBundleName "Safari.app" +#define kSafariBundleOnSystemPath kApplicationsPath "/" kSafariBundleName +#define kSafariBundleOnVolumePath kFAT32DiskImageVolumePath "/" kSafariBundleName + +static void +_cleanUpFAT32DiskImage(void) +{ + // Delete disk image. + const char *command = BUILD_COMMAND("rm -rf " kFAT32DiskImageFilePath); + system(command); + + // Detach volume. + command = BUILD_COMMAND("hdiutil detach " kFAT32DiskImageVolumePath); + system(command); +} + +static int +_createFAT32DiskImage(void) +{ + const char *command = BUILD_COMMAND("hdiutil create -fs FAT32 -size 256m -volname " kFAT32DiskImageVolumeName " " kFAT32DiskImageFilePath); + return system(command); +} + +static int +_attachFAT32DiskImage(void) +{ + const char *command = BUILD_COMMAND("hdiutil attach " kFAT32DiskImageFilePath); + return system(command); +} + +static int +_copySafariBundleToVolume(void) +{ + const char *command = BUILD_COMMAND("cp -R " kSafariBundleOnSystemPath " " kSafariBundleOnVolumePath); + return system(command); +} + +static int +_confirmValidationPolicy(const char *path) +{ + int ret = -1; + SecStaticCodeRef codeRef = NULL; + SecCSFlags createFlags = kSecCSDefaultFlags; + SecCSFlags validateFlags = kSecCSDefaultFlags | kSecCSStrictValidateStructure; + + CFStringRef stringRef = NULL; + CFURLRef pathRef = NULL; + + require(path, done); + + stringRef = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)path, strlen(path), kCFStringEncodingASCII, false); + require(stringRef, done); + + pathRef = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, stringRef, kCFURLPOSIXPathStyle, false); + require(pathRef, done); + + OSStatus status = SecStaticCodeCreateWithPath(pathRef, createFlags, &codeRef); + require_noerr(status, done); + require(codeRef, done); + + // Validate binary without kSecCSSkipXattrFiles. Expectation is this should fail. + status = SecStaticCodeCheckValidity(codeRef, validateFlags, NULL); + if (!status) { + INFO("%s validated without kSecCSSkipXattrFiles flag", path); + goto done; + } + SAFE_RELEASE(codeRef); + + // Create codeRef again to clear state. + status = SecStaticCodeCreateWithPath(pathRef, createFlags, &codeRef); + require_noerr(status, done); + require(codeRef, done); + + // Validate binary with kSecCSSkipXattrFiles. Expectation is this should pass. + validateFlags |= kSecCSSkipXattrFiles; + status = SecStaticCodeCheckValidity(codeRef, validateFlags, NULL); + if (status) { + INFO("%s is not valid even with kSecCSSkipXattrFiles flag", path); + goto done; + } + + // Complete. + ret = 0; + +done: + SAFE_RELEASE(codeRef); + SAFE_RELEASE(stringRef); + SAFE_RELEASE(pathRef); + return ret; +} + +static int +CheckCheckValidity_kSecCSSkipXattrFiles(void) +{ + BEGIN(); + + int ret = -1; + + // Create FAT32 disk image. + if (_createFAT32DiskImage()) { + FAIL("_createFAT32DiskImage error"); + goto done; + } + INFO("Created " kFAT32DiskImageFilePath); + + // Attach disk image to the system. + if (_attachFAT32DiskImage()) { + FAIL("_attachFAT32DiskImage error"); + goto done; + } + INFO("Attached " kFAT32DiskImageFilePath " as " kFAT32DiskImageVolumePath); + + // Copy Safari.app to the attached volume. + if (_copySafariBundleToVolume()) { + FAIL("_copySafariBundleToVolume error"); + goto done; + } + INFO("Copied " kSafariBundleOnSystemPath " to " kSafariBundleOnVolumePath); + + // Write "com.apple.dummy" xattr to Safari. + const char *xattrName = "com.apple.dummy"; + const uint32_t xattrValue = 0; + + const char *safariBinary = kSafariBundleOnVolumePath "/Contents/MacOS/Safari"; + if (setxattr(safariBinary, xattrName, &xattrValue, sizeof(xattrValue), 0, 0)) { + FAIL("%s setxattr error: %d [%s]", safariBinary, errno, strerror(errno)); + goto done; + } + INFO("Wrote xattr \'%s\' to %s", xattrName, safariBinary); + + const char *safariCodeResources = kSafariBundleOnVolumePath "/Contents/_CodeSignature/CodeResources"; + if (setxattr(safariCodeResources, xattrName, &xattrValue, sizeof(xattrValue), 0, 0)) { + FAIL("%s setxattr error: %d [%s]", safariCodeResources, errno, strerror(errno)); + goto done; + } + INFO("Wrote xattr \'%s\' to %s", xattrName, safariCodeResources); + + // Validate Safari.app with and without kSecCSSkipXattrFiles flag. + if (_confirmValidationPolicy(kSafariBundleOnVolumePath)) { + FAIL("%s _confirmValidationPolicy error", kSafariBundleOnVolumePath); + goto done; + } + INFO("Validation policy on %s confirmed", kSafariBundleOnVolumePath); + + PASS("Completed validation policy check with kSecCSSkipXattrFiles"); + ret = 0; + +done: + _cleanUpFAT32DiskImage(); + return ret; +} + +int main(void) +{ + fprintf(stdout, "[TEST] secsecstaticcodeapitest\n"); + + int i; + int (*testList[])(void) = { + CheckCheckValidity_kSecCSSkipXattrFiles + }; + const int numberOfTests = sizeof(testList) / sizeof(*testList); + int testResults[numberOfTests] = {0}; + + for (i = 0; i < numberOfTests; i++) { + testResults[i] = testList[i](); + } + + fprintf(stdout, "[SUMMARY]\n"); + for (i = 0; i < numberOfTests; i++) { + fprintf(stdout, "%d. %s\n", i+1, testResults[i] == 0 ? "Passed" : "Failed"); + } + + return 0; +}