AuthorizationExecuteWithPrivileges is deprecated
Solution 1
I know it sounds crazy, but this actually works:
NSDictionary *error = [NSDictionary new];
NSString *script = @"do shell script \"whoami > /tmp/me\" with administrator privileges";
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:script];
if ([appleScript executeAndReturnError:&error]) {
NSLog(@"success!");
} else {
NSLog(@"failure!");
}
I'm executing an Applescript from Objective C. The only disadvantage is that you cannot gain permanent root privileges with this. It will ask for the password each time you run this.
Solution 2
Based on a great find by user950473 I've implemented his/her discovery as a method; thought I'd share the code in case it's helpful.
- (BOOL) runProcessAsAdministrator:(NSString*)scriptPath
withArguments:(NSArray *)arguments
output:(NSString **)output
errorDescription:(NSString **)errorDescription {
NSString * allArgs = [arguments componentsJoinedByString:@" "];
NSString * fullScript = [NSString stringWithFormat:@"'%@' %@", scriptPath, allArgs];
NSDictionary *errorInfo = [NSDictionary new];
NSString *script = [NSString stringWithFormat:@"do shell script \"%@\" with administrator privileges", fullScript];
NSAppleScript *appleScript = [[NSAppleScript new] initWithSource:script];
NSAppleEventDescriptor * eventResult = [appleScript executeAndReturnError:&errorInfo];
// Check errorInfo
if (! eventResult)
{
// Describe common errors
*errorDescription = nil;
if ([errorInfo valueForKey:NSAppleScriptErrorNumber])
{
NSNumber * errorNumber = (NSNumber *)[errorInfo valueForKey:NSAppleScriptErrorNumber];
if ([errorNumber intValue] == -128)
*errorDescription = @"The administrator password is required to do this.";
}
// Set error message from provided message
if (*errorDescription == nil)
{
if ([errorInfo valueForKey:NSAppleScriptErrorMessage])
*errorDescription = (NSString *)[errorInfo valueForKey:NSAppleScriptErrorMessage];
}
return NO;
}
else
{
// Set output to the AppleScript's output
*output = [eventResult stringValue];
return YES;
}
}
Usage example:
NSString * output = nil;
NSString * processErrorDescription = nil;
BOOL success = [self runProcessAsAdministrator:@"/usr/bin/id"
withArguments:[NSArray arrayWithObjects:@"-un", nil]
output:&output
errorDescription:&processErrorDescription];
if (!success) // Process failed to run
{
// ...look at errorDescription
}
else
{
// ...process output
}
It's very slightly hacky, but IMHO is a satisfactory solution.
Solution 3
AuthorizationExecuteWithPrivileges is indeed deprecated.
But fortunately, there is a new recommended way to proceed.
As of 10.6 there is the new API and it is recommended to install a helper tool that will perform the privileged operation. Apple provide a code sample that clearly demonstrate how to manage it.
Make sure you check out their readme.txt since contrarily to other code sample there is more to do than just downloading the project and running it.
From The SMJobBless example introduction
SMJobBless demonstrates how to securely install a helper tool that performs a privileged operation and how to associate the tool with an application that invokes it.
As of Snow Leopard, this is the preferred method of managing privilege escalation on Mac OS X and should be used instead of earlier approaches such as BetterAuthorizationSample or directly calling AuthorizationExecuteWithPrivileges.
SMJobBless uses ServiceManagement.framework that was introduced in Mac OS X v10.6 Snow Leopard.
Source: Apple SMJobBless code sample
Admin
Updated on October 03, 2020Comments
-
Admin over 3 years
Since updating to OSX 10.7 Lion, Xcode tells me that
AuthorizationExecuteWithPrivileges
is deprecated.Can anyone suggest a way my application can write to a directory it doesn't have permission for?
-
Alex Gray about 12 yearsWould ya look at that. so YOU'RE
root
?! Oh wait, I am. No, wait.. AppleScript is? Jesus. That is certainly crazy. The only thing that would be crazier is if it didn't ask for your password, lol. -
ArtOfWarfare almost 12 yearsI attempted to use this but it didn't ask me for my password ever. Instead it just skipped to printing "failure!" When I printed the description of error, I got this: "NSAppleScriptErrorMessage = "The administrator user name or password was incorrect.";" This is in an app with the sandbox enabled... does anyone have suggestions that work with a sandbox enabled app?
-
geowar over 11 yearsFYI: As documented in Technical Note TN2065: do shell script in AppleScript (developer.apple.com/library/mac/#technotes/tn2065/_index.html): Use the administrator privileges, user name and password parameters like this: do shell script "command" user name "me" password "mypassword" with administrator privileges
-
Jim almost 11 yearsThis method fails if there is a space in the path of the script, which is likely if you want to run a script included in your application bundle. To fix this, just change the format when setting fullScript to @"'%@' %@" so the process path name is quoted.
-
cody almost 11 yearsNote, that Threading Programming Guide says that NSAppleScript class must be used only from the main thread of an application. Although I myself using it not only in the main thread and have no problems.
-
Parag Bafna over 10 yearsI am getting DYLD_ environment variables being ignored because main executable (/usr/libexec/security_authtrampoline) is setuid or setgid on 10.8
-
Jean over 10 yearsWhy would you say that? I was able to download the sample code today, using the link I provided and a non-paid developer account.
-
Fast Engy over 10 yearsHave you run a project successfully yet? It was asking for code signing of the app with an OSX developer account.
-
kainjow about 10 yearsYou can gain permanent root privileges if you a) create a separate binary that will do what you want as root, b) copy that binary to a safe writable location (e.g. /Library/Application Support/xxx), c) set the setuid bit on that binary, d) chown the binary as root, and e) chmod the binary appropriately. Maybe I'll create an example project on Github one day...
-
Yann86 almost 10 yearsHi, is there a way to add the app icon in the password prompt in place of the blank file with your solution?
-
Carlos P almost 10 years@Yann86 I don't believe so, as the prompt is delivered by Applescript itself
-
Motti Shneor over 3 yearsI don't know why you and others are surprised. AppleScript is designed to be standalone, and maintain complex flows and scenarios. So it makes things easy (and NOT less secure). It does NOT run as root, and you don't need "root" for copying files to anywhere - you just need the "Full Disk Access" capability. Plus - administrator privileges are NOT root. Macs can run root-less and still copy files anywhere. It's probably the easiest thing to do programmatically, but not a fast or preferable solution.