#objective-c #cocoa #deprecated
#objective-c #xcode #macos
Вопрос:
После обновления до OSX 10.7 Lion Xcode сообщает мне, что AuthorizationExecuteWithPrivileges
это устарело.
Кто-нибудь может предложить способ, которым мое приложение может выполнять запись в каталог, для которого у него нет разрешения?
Ответ №1:
Я знаю, это звучит безумно, но это действительно работает:
NSDictionary *error = [NSDictionary new];
NSString *script = @"do shell script "whoami > /tmp/me" with administrator privileges";
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:script];
if ([appleScript executeAndReturnError:amp;error]) {
NSLog(@"success!");
} else {
NSLog(@"failure!");
}
Я выполняю Applescript из Objective C. Единственным недостатком является то, что вы не можете получить постоянные привилегии root с помощью этого. Он будет запрашивать пароль при каждом запуске этого.
Комментарии:
1. Ты бы посмотрел на это. так ТЫ
root
?! О, подождите, я. Нет, подождите .. AppleScript есть ? Господи. Это, конечно, безумие. Единственное, что было бы безумнее, это если бы он не запрашивал ваш пароль, lol.2. Я попытался использовать это, но он никогда не запрашивал у меня мой пароль. Вместо этого он просто перешел к печати «сбой!» Когда я напечатал описание ошибки, я получил следующее: «NSAppleScriptErrorMessage = «Имя пользователя или пароль администратора были неверными.»;» Это в приложении с включенной песочницей … есть ли у кого-нибудь предложения, которые работают с приложением с включенной песочницей?
3. К вашему сведению: как описано в техническом примечании TN2065: выполните сценарий оболочки в AppleScript ( developer.apple.com/library/mac/#technotes/tn2065/_index.html ): Используйте права администратора, имя пользователя и параметры пароля следующим образом: выполните сценарий оболочки «command» имя пользователя «me» пароль «mypassword» с правами администратора
4. Обратите внимание, что в руководстве по программированию потоков говорится, что класс NSAppleScript должен использоваться только из основного потока приложения. Хотя я сам использую его не только в основном потоке и не имею проблем.
5. Я получаю, что переменные среды DYLD_ игнорируются, потому что основной исполняемый файл (/usr/libexec/security_authtrampoline) имеет значение setuid или setgid на 10.8
Ответ №2:
На самом деле, AuthorizationExecuteWithPrivileges()
он устарел уже очень давно, и только недавно заголовочный файл осознал этот факт.
Вы можете создать привилегированный вспомогательный инструмент как часть вашего приложения. Вы можете использовать ServiceManagement.framework
SMJobBless()
функцию ‘s для развертывания помощника в системном launchd
контексте: затем, когда вам нужно выполнить привилегированные задачи, вы просто отправляете сообщение привилегированному помощнику для выполнения этой работы.
Существует небольшая скрытая сложность, заключающаяся в том, что приложение и помощник должны объявить идентификатор подписи другого, прежде SMJobBless()
чем считать, что они должны использоваться вместе, и вам нужно заставить компоновщик записать файл вспомогательного инструмента Info.plist
в двоичный файл. Все это описано в документации Apple, и Apple также предоставила образец проекта.
Я написал пример приложения, которое использует SMJobBless()
для развертывания своего привилегированного помощника.
Комментарии:
1. Привет, спасибо за ответ. Если AuthorizationExecuteWithPrivileges() устарела в течение длительного времени, должна ли она продолжать работать? По сути, это перестало работать в моем приложении с момента обновления Lion, и я предположил, что это потому, что теперь оно помечено как устаревшее… Должно ли это все еще работать, и моя проблема заключается в другом? Большое спасибо
2. Вы не должны полагаться на
AuthorizationExecuteWithPrivileges()
, это ужасная дыра в безопасности. Способ сделать то, что вы хотите сделать, — это сSMJobBless()
помощью .3. @GrahamLee А как насчет использования
AuthorizationExecuteWithPrivileges
для установщика? В ссылке говорится, что «Вы должны использовать эту функцию только для того, чтобы разрешить установщикам запускаться от имени root и разрешить инструменту setuid восстанавливать свой бит setuid в случае утери», а в руководстве по программированию служб авторизации предлагается использовать эту функцию для запуска установщиков (хотя она несколько устарела).). Есть ли какая-либо альтернатива запуску установщика в простом приложении, таком как инструмент командной строки?4. Это тоже устарело. Если вы используете управление системой, вы можете развернуть привилегированные компоненты без установки.
5. @GrahamLee. Ну хорошо, а что, если у меня есть файл pkg, и я хочу запустить
installer
утилиту для него? Как я могу это сделать, не используя устаревшую функциональность. Могу ли я использовать системные утилиты в качестве вспомогательного инструмента? Я понимаю, что могу запустить установщик с классом NSWorkspace. Но мне не нужно приложение для установки с графическим интерфейсом, я хочу сделать это тихо, и мне нужен код завершения процесса установки, поэтому мне нужно его дождаться. Что вы можете предложить в таком случае?
Ответ №3:
Основываясь на замечательной находке пользователя 950473, я реализовал его / ее открытие как метод; подумал, что поделюсь кодом, если это полезно.
- (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:amp;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;
}
}
Пример использования:
NSString * output = nil;
NSString * processErrorDescription = nil;
BOOL success = [self runProcessAsAdministrator:@"/usr/bin/id"
withArguments:[NSArray arrayWithObjects:@"-un", nil]
output:amp;output
errorDescription:amp;processErrorDescription];
if (!success) // Process failed to run
{
// ...look at errorDescription
}
else
{
// ...process output
}
Это очень немного халтурно, но ИМХО является удовлетворительным решением.
Комментарии:
1. Этот метод завершается с ошибкой, если в пути к скрипту есть пробел, что вероятно, если вы хотите запустить скрипт, включенный в ваш пакет приложений. Чтобы исправить это, просто измените формат при установке fullScript на @»‘%@’ %@», чтобы имя пути процесса было заключено в кавычки.
2. Привет, есть ли способ добавить значок приложения в запрос пароля вместо пустого файла с вашим решением?
3. @Yann86 Я в это не верю, поскольку приглашение доставляется самим Applescript
Ответ №4:
AuthorizationExecuteWithPrivileges действительно устарел.
Но, к счастью, есть новый рекомендуемый способ продолжить.
Начиная с версии 10.6, появился новый API, и рекомендуется установить вспомогательный инструмент, который будет выполнять привилегированную операцию. Apple предоставила пример кода, который наглядно демонстрирует, как им управлять.
Убедитесь, что вы проверили их readme.txt поскольку, в отличие от других примеров кода, нужно сделать больше, чем просто загрузить проект и запустить его.
Из введения примера без SMJobBless
SMJobBless демонстрирует, как безопасно установить вспомогательный инструмент, который выполняет привилегированную операцию, и как связать инструмент с приложением, которое его вызывает.
Начиная со Snow Leopard, это предпочтительный метод управления повышением привилегий в Mac OS X, и его следует использовать вместо более ранних подходов, таких как BetterAuthorizationSample или прямой вызов AuthorizationExecuteWithPrivileges.
SMJobBless использует ServiceManagement.framework, который был представлен в Mac OS X версии 10.6 Snow Leopard.
Источник: пример кода Apple без SMJobBless
Комментарии:
1. Почему вы так говорите? Сегодня я смог загрузить пример кода, используя предоставленную мной ссылку и бесплатную учетную запись разработчика.
2. Вы уже успешно запустили проект? Он запрашивал подпись кода приложения с помощью учетной записи разработчика OSX.