AuthorizationExecuteWithPrivileges устарел

#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.