Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue #3: Read code signing entitlements from the application binary #16

Merged
merged 3 commits into from
Jan 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 55 additions & 5 deletions ProvisionQL/GeneratePreviewForURL.m
Original file line number Diff line number Diff line change
Expand Up @@ -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 <AppBinary> --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
Expand All @@ -242,13 +265,16 @@ 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]) {
// get the embedded provisioning & plist for the iOS app
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 <currentTempDirFolder> <URL> <files to unzip>
NSTask *unzipTask = [NSTask new];
Expand All @@ -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
Expand Down Expand Up @@ -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:@"<pre>%@</pre>", 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:@"<pre>%@</pre>", dictionaryFormatted];

[synthesizedInfo setObject:synthesizedValue forKey:@"EntitlementsFormatted"];
} else {
[synthesizedInfo setObject:@"No Entitlements" forKey:@"EntitlementsFormatted"];
}
}

value = [propertyList objectForKey:@"DeveloperCertificates"];
Expand Down
2 changes: 1 addition & 1 deletion ProvisionQL/Shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#import <NSBezierPath+IOS7RoundedRect.h>

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";
Expand Down
2 changes: 1 addition & 1 deletion ProvisionQL/Supporting-files/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<key>CFBundleShortVersionString</key>
<string>1</string>
<key>CFBundleVersion</key>
<string>1.3.0</string>
<string>1.3.1</string>
<key>CFPlugInDynamicRegisterFunction</key>
<string></string>
<key>CFPlugInDynamicRegistration</key>
Expand Down