Подтвердить что ты не робот

АвторизацияExecuteWithPrivileges устарела

Начиная с обновления до OSX 10.7 Lion, Xcode сообщает мне, что AuthorizationExecuteWithPrivileges устарел.

Может ли кто-нибудь предложить способ, которым мое приложение может писать в каталог, на который у него нет разрешения?

4b9b3361

Ответ 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:&error]) {
  NSLog(@"success!"); 
} else {
  NSLog(@"failure!"); 
}

Я выполняю Applescript из Objective C. Единственным недостатком является то, что вы не можете получить постоянные привилегии root с этим. Он будет запрашивать пароль каждый раз, когда вы его запускаете.

Ответ 2

Фактически, AuthorizationExecuteWithPrivileges() устарел в течение очень долгого времени, только недавно заголовочный файл догнал этот факт.

Вы можете создать привилегированный вспомогательный инструмент как часть вашего приложения. Вы можете использовать функцию ServiceManagement.framework SMJobBless(), чтобы помощник был развернут в контексте системы launchd: тогда, когда вам нужно выполнять привилегированные задачи, вы просто передаете привилегированный помощник для выполнения этой работы.

Там немного скрытая сложность, так как приложение и помощник должны объявить подпись подписи другого, прежде чем SMJobBless() полагает, что они должны использоваться вместе, и вам нужно заставить компоновщик писать вспомогательный инструмент Info.plist в двоичный файл. Все, что охватывалось Apple Documentation, и Apple предоставили примерный проект тоже.

I написал пример приложения, в котором используется SMJobBless() для развертывания своего привилегированного помощника.

Ответ 3

Основываясь на отличной находке 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 - удовлетворительное решение.

Ответ 4

Авторизация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