Handle GateKeeper and write permissions in the auto updater
This commit is contained in:
parent
3c4bfd2a1b
commit
004c20d8e2
@ -5,6 +5,7 @@
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <JoyKit/JoyKit.h>
|
||||
#import <WebKit/WebKit.h>
|
||||
#import <mach-o/dyld.h>
|
||||
|
||||
#define UPDATE_SERVER "https://sameboy.github.io"
|
||||
|
||||
@ -31,6 +32,7 @@ static uint32_t color_to_int(NSColor *color)
|
||||
UPDATE_FAILED,
|
||||
} _updateState;
|
||||
NSString *_downloadDirectory;
|
||||
AuthorizationRef _auth;
|
||||
}
|
||||
|
||||
- (void) applicationDidFinishLaunching:(NSNotification *)notification
|
||||
@ -366,8 +368,55 @@ static uint32_t color_to_int(NSColor *color)
|
||||
[self.updateWindow performClose:sender];
|
||||
}
|
||||
|
||||
- (bool)executePath:(NSString *)path withArguments:(NSArray <NSString *> *)arguments
|
||||
{
|
||||
if (!_auth) {
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
task.launchPath = path;
|
||||
task.arguments = arguments;
|
||||
[task launch];
|
||||
[task waitUntilExit];
|
||||
return task.terminationStatus == 0 && task.terminationReason == NSTaskTerminationReasonExit;
|
||||
}
|
||||
|
||||
char *argv[arguments.count + 1];
|
||||
argv[arguments.count] = NULL;
|
||||
for (unsigned i = 0; i < arguments.count; i++) {
|
||||
argv[i] = (char *)arguments[i].UTF8String;
|
||||
}
|
||||
|
||||
return AuthorizationExecuteWithPrivileges(_auth, path.UTF8String, kAuthorizationFlagDefaults, argv, NULL) == errAuthorizationSuccess;
|
||||
}
|
||||
|
||||
- (void)deauthorize
|
||||
{
|
||||
if (_auth) {
|
||||
AuthorizationFree(_auth, kAuthorizationFlagDefaults);
|
||||
_auth = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)installUpdate:(id)sender
|
||||
{
|
||||
bool needsAuthorization = false;
|
||||
if ([self executePath:@"/usr/sbin/spctl" withArguments:@[@"--status"]]) { // Succeeds when GateKeeper is on
|
||||
// GateKeeper is on, we need to --add ourselves as root, else we might get a GateKeeper crash
|
||||
needsAuthorization = true;
|
||||
}
|
||||
else if (access(_dyld_get_image_name(0), W_OK)) {
|
||||
// We don't have write access, so we need authorization to update as root
|
||||
needsAuthorization = true;
|
||||
}
|
||||
|
||||
if (needsAuthorization && !_auth) {
|
||||
AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagPreAuthorize | kAuthorizationFlagInteractionAllowed, &_auth);
|
||||
// Make sure we can modify the bundle
|
||||
if (![self executePath:@"/usr/sbin/chown" withArguments:@[@"-R", [NSString stringWithFormat:@"%d:%d", getuid(), getgid()], [NSBundle mainBundle].bundlePath]]) {
|
||||
[self deauthorize];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[self.updateProgressSpinner startAnimation:nil];
|
||||
self.updateProgressButton.title = @"Cancel";
|
||||
self.updateProgressButton.enabled = true;
|
||||
@ -386,8 +435,8 @@ static uint32_t color_to_int(NSColor *color)
|
||||
appropriateForURL:[[NSBundle mainBundle] bundleURL]
|
||||
create:true
|
||||
error:nil] path];
|
||||
NSTask *unzipTask;
|
||||
if (!_downloadDirectory) {
|
||||
[self deauthorize];
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
self.updateProgressButton.enabled = false;
|
||||
self.updateProgressLabel.stringValue = @"Failed to extract update.";
|
||||
@ -399,12 +448,14 @@ static uint32_t color_to_int(NSColor *color)
|
||||
return;
|
||||
}
|
||||
|
||||
NSTask *unzipTask;
|
||||
unzipTask = [[NSTask alloc] init];
|
||||
unzipTask.launchPath = @"/usr/bin/unzip";
|
||||
unzipTask.arguments = @[location.path, @"-d", _downloadDirectory];
|
||||
[unzipTask launch];
|
||||
[unzipTask waitUntilExit];
|
||||
if (unzipTask.terminationStatus != 0 || unzipTask.terminationReason != NSTaskTerminationReasonExit) {
|
||||
[self deauthorize];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
self.updateProgressButton.enabled = false;
|
||||
@ -449,6 +500,7 @@ static uint32_t color_to_int(NSColor *color)
|
||||
NSError *error = nil;
|
||||
[[NSFileManager defaultManager] moveItemAtPath:contentsPath toPath:contentsTempPath error:&error];
|
||||
if (error) {
|
||||
[self deauthorize];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
|
||||
_downloadDirectory = nil;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
@ -463,6 +515,7 @@ static uint32_t color_to_int(NSColor *color)
|
||||
}
|
||||
[[NSFileManager defaultManager] moveItemAtPath:updateContentsPath toPath:contentsPath error:&error];
|
||||
if (error) {
|
||||
[self deauthorize];
|
||||
[[NSFileManager defaultManager] moveItemAtPath:contentsTempPath toPath:contentsPath error:nil];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
|
||||
_downloadDirectory = nil;
|
||||
|
2
Makefile
2
Makefile
@ -163,7 +163,7 @@ endif
|
||||
|
||||
CFLAGS += -F/Library/Frameworks -mmacosx-version-min=10.9 -isysroot $(SYSROOT)
|
||||
OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT)
|
||||
LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -weak_framework Metal -weak_framework MetalKit -mmacosx-version-min=10.9 -isysroot $(SYSROOT)
|
||||
LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -framework Security -weak_framework Metal -weak_framework MetalKit -mmacosx-version-min=10.9 -isysroot $(SYSROOT)
|
||||
GL_LDFLAGS := -framework OpenGL
|
||||
endif
|
||||
CFLAGS += -Wno-deprecated-declarations
|
||||
|
Loading…
Reference in New Issue
Block a user