Начиная с обновления до OSX 10.7 Lion, Xcode сообщает мне, что AuthorizationExecuteWithPrivileges
устарел.
Может ли кто-нибудь предложить способ, которым мое приложение может писать в каталог, на который у него нет разрешения?
Начиная с обновления до OSX 10.7 Lion, Xcode сообщает мне, что AuthorizationExecuteWithPrivileges
устарел.
Может ли кто-нибудь предложить способ, которым мое приложение может писать в каталог, на который у него нет разрешения?
Я знаю, что это звучит безумно, но на самом деле это работает:
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!");
}
Я выполняю Applescript из Objective C. Единственным недостатком является то, что вы не можете получить постоянные привилегии root с этим. Он будет запрашивать пароль каждый раз, когда вы его запускаете.
Фактически, AuthorizationExecuteWithPrivileges()
устарел в течение очень долгого времени, только недавно заголовочный файл догнал этот факт.
Вы можете создать привилегированный вспомогательный инструмент как часть вашего приложения. Вы можете использовать функцию ServiceManagement.framework
SMJobBless()
, чтобы помощник был развернут в контексте системы launchd
: тогда, когда вам нужно выполнять привилегированные задачи, вы просто передаете привилегированный помощник для выполнения этой работы.
Там немного скрытая сложность, так как приложение и помощник должны объявить подпись подписи другого, прежде чем SMJobBless()
полагает, что они должны использоваться вместе, и вам нужно заставить компоновщик писать вспомогательный инструмент Info.plist
в двоичный файл. Все, что охватывалось Apple Documentation, и Apple предоставили примерный проект тоже.
I написал пример приложения, в котором используется SMJobBless()
для развертывания своего привилегированного помощника.
Основываясь на отличной находке user950473, я реализовал свое открытие как метод; подумал, что я бы разделил код на случай, если он будет полезен.
- (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 output
*output = [eventResult stringValue];
return YES;
}
}
Пример использования:
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
}
Это очень немного взломанно, но IMHO - удовлетворительное решение.
АвторизацияExecuteWithPrivileges действительно устарела.
Но, к счастью, есть новый рекомендуемый способ продолжения.
Начиная с версии 10.6 появился новый API, и рекомендуется установить вспомогательный инструмент, который будет выполнять привилегированную операцию. Apple предоставляет образец кода, который четко демонстрирует, как управлять им.
Убедитесь, что вы просмотрите их readme.txt, поскольку в противоположность другому образцу кода есть больше, чем просто загрузка проекта и его запуск.
Из примера внедрения SMJobBless
SMJobBless демонстрирует, как безопасно установить вспомогательный инструмент, который выполняет привилегированную операцию и как связать инструмент с приложением, которое вызывает его.
Как и Snow Leopard, это предпочтительный метод управления привилегиями эскалацию в Mac OS X и следует использовать вместо ранее такие как BetterAuthorizationSample или прямой вызов AuthorizationExecuteWithPrivileges.
SMJobBless использует ServiceManagement.framework, который был представлен на Mac OS X v10.6 Snow Leopard.
Источник: Пример кода Apple SMJobBless