From 4aaa5c8f5777910ace7d4c65908d42f16f446c30 Mon Sep 17 00:00:00 2001 From: Thomas Dankert Date: Mon, 8 Jan 2018 17:22:15 +0100 Subject: [PATCH 1/3] Set bundle identifier constant to be identical to Info.plist --- ProvisionQL/Shared.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProvisionQL/Shared.h b/ProvisionQL/Shared.h index dfc7273..420c600 100644 --- a/ProvisionQL/Shared.h +++ b/ProvisionQL/Shared.h @@ -8,7 +8,7 @@ #import -static NSString * const kPluginBundleId = @"com.FerretSyndicate.ProvisionQL"; +static NSString * const kPluginBundleId = @"com.ealeksandrov.ProvisionQL"; static NSString * const kDataType_ipa = @"com.apple.itunes.ipa"; static NSString * const kDataType_app = @"com.apple.application-bundle"; static NSString * const kDataType_ios_provision = @"com.apple.mobileprovision"; From cdc76e6d26c50a176d8c5286cff5ee3677c810eb Mon Sep 17 00:00:00 2001 From: Thomas Dankert Date: Mon, 8 Jan 2018 17:22:24 +0100 Subject: [PATCH 2/3] Update version to 1.3.1 --- ProvisionQL/Supporting-files/Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProvisionQL/Supporting-files/Info.plist b/ProvisionQL/Supporting-files/Info.plist index 8e3779b..bb72ea1 100644 --- a/ProvisionQL/Supporting-files/Info.plist +++ b/ProvisionQL/Supporting-files/Info.plist @@ -31,7 +31,7 @@ CFBundleShortVersionString 1 CFBundleVersion - 1.3.0 + 1.3.1 CFPlugInDynamicRegisterFunction CFPlugInDynamicRegistration From 0e2cdb8debee4b7de2a8943f4638f3a13bd0de91 Mon Sep 17 00:00:00 2001 From: Thomas Dankert Date: Mon, 8 Jan 2018 17:24:21 +0100 Subject: [PATCH 3/3] Fix #3: Read code signing entitlements from the application binary Read the code signing entitlements directly from the application binary (using "codesign" application). Fallback to reading the provisioning profile if the binary has no entitlements set. --- ProvisionQL/GeneratePreviewForURL.m | 60 ++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/ProvisionQL/GeneratePreviewForURL.m b/ProvisionQL/GeneratePreviewForURL.m index aae9dee..30a51e2 100644 --- a/ProvisionQL/GeneratePreviewForURL.m +++ b/ProvisionQL/GeneratePreviewForURL.m @@ -230,6 +230,29 @@ void displayKeyAndValue(NSUInteger level, NSString *key, id value, NSMutableStri return string; } +NSData *codesignEntitlementsDataFromApp(NSData *infoPlistData, NSString *basePath) { + // read the CFBundleExecutable and extract it + NSDictionary *appPropertyList = [NSPropertyListSerialization propertyListWithData:infoPlistData options:0 format:NULL error:NULL]; + NSString *bundleExecutable = [appPropertyList objectForKey:@"CFBundleExecutable"]; + + NSString *binaryPath = [basePath stringByAppendingPathComponent:bundleExecutable]; + // get entitlements: codesign -d --entitlements :- + NSPipe *codesignPipe = [NSPipe pipe]; + NSFileHandle *codesignOutputFile = [codesignPipe fileHandleForReading]; + NSTask *codesignTask = [NSTask new]; + [codesignTask setLaunchPath:@"/usr/bin/codesign"]; + [codesignTask setStandardOutput:codesignPipe]; + [codesignTask setArguments:@[@"-d", binaryPath, @"--entitlements", @":-"]]; + [codesignTask launch]; + [codesignTask waitUntilExit]; + + // save output of codesign task + NSData *codesignEntitlementsData = [codesignOutputFile readDataToEndOfFile]; + [codesignOutputFile closeFile]; + + return codesignEntitlementsData; +} + OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) { @autoreleasepool { // create temp directory @@ -242,6 +265,7 @@ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, NSString *dataType = (__bridge NSString *)contentTypeUTI; NSData *provisionData = nil; NSData *appPlist = nil; + NSData *codesignEntitlementsData = nil; NSImage *appIcon = nil; if([dataType isEqualToString:kDataType_app]) { @@ -249,6 +273,8 @@ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, provisionData = [NSData dataWithContentsOfURL:[URL URLByAppendingPathComponent:@"embedded.mobileprovision"]]; appPlist = [NSData dataWithContentsOfURL:[URL URLByAppendingPathComponent:@"Info.plist"]]; + codesignEntitlementsData = codesignEntitlementsDataFromApp(appPlist, URL.path); + } else if([dataType isEqualToString:kDataType_ipa]) { // get the embedded provisioning & plist from an app archive using: unzip -u -j -d NSTask *unzipTask = [NSTask new]; @@ -263,6 +289,19 @@ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, NSString *plistPath = [currentTempDirFolder stringByAppendingPathComponent:@"Info.plist"]; appPlist = [NSData dataWithContentsOfFile:plistPath]; + // read codesigning entitlements from application binary (extract it first) + NSDictionary *appPropertyList = [NSPropertyListSerialization propertyListWithData:appPlist options:0 format:NULL error:NULL]; + NSString *bundleExecutable = [appPropertyList objectForKey:@"CFBundleExecutable"]; + + NSTask *unzipAppTask = [NSTask new]; + [unzipAppTask setLaunchPath:@"/usr/bin/unzip"]; + [unzipAppTask setStandardOutput:[NSPipe pipe]]; + [unzipAppTask setArguments:@[@"-u", @"-j", @"-d", currentTempDirFolder, [URL path], [@"Payload/*.app/" stringByAppendingPathComponent:bundleExecutable]]]; + [unzipAppTask launch]; + [unzipAppTask waitUntilExit]; + + codesignEntitlementsData = codesignEntitlementsDataFromApp(appPlist, currentTempDirFolder); + [fileManager removeItemAtPath:tempDirFolder error:nil]; } else { // use provisioning directly @@ -428,16 +467,27 @@ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, [synthesizedInfo setObject:synthesizedValue forKey:@"TeamIds"]; } - value = [propertyList objectForKey:@"Entitlements"]; - if ([value isKindOfClass:[NSDictionary class]]) { - NSDictionary *dictionary = (NSDictionary *)value; + if (codesignEntitlementsData != nil) { + // read the entitlements directly from the codesign output + NSDictionary *entitlementsPropertyList = [NSPropertyListSerialization propertyListWithData:codesignEntitlementsData options:0 format:NULL error:NULL]; NSMutableString *dictionaryFormatted = [NSMutableString string]; - displayKeyAndValue(0, nil, dictionary, dictionaryFormatted); + displayKeyAndValue(0, nil, entitlementsPropertyList, dictionaryFormatted); synthesizedValue = [NSString stringWithFormat:@"
%@
", dictionaryFormatted]; [synthesizedInfo setObject:synthesizedValue forKey:@"EntitlementsFormatted"]; } else { - [synthesizedInfo setObject:@"No Entitlements" forKey:@"EntitlementsFormatted"]; + // read the entitlements from the provisioning profile instead + value = [propertyList objectForKey:@"Entitlements"]; + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictionary = (NSDictionary *)value; + NSMutableString *dictionaryFormatted = [NSMutableString string]; + displayKeyAndValue(0, nil, dictionary, dictionaryFormatted); + synthesizedValue = [NSString stringWithFormat:@"
%@
", dictionaryFormatted]; + + [synthesizedInfo setObject:synthesizedValue forKey:@"EntitlementsFormatted"]; + } else { + [synthesizedInfo setObject:@"No Entitlements" forKey:@"EntitlementsFormatted"]; + } } value = [propertyList objectForKey:@"DeveloperCertificates"];