Получение прав администратора для удаления файлов с помощью rm из приложения Какао - PullRequest
9 голосов
/ 28 августа 2010

Я делаю небольшое приложение, которое удаляет файлы журнала. Я использую экземпляр NSTask, который запускает rm и srm (безопасный rm) для удаления файлов.

Я хочу иметь возможность удалять файлы в:

  • / Library / Logs
  • ~ / Library / Logs

Проблема заключается в том, что у учетной записи пользователя нет прав доступа к некоторым файлам в папке системной библиотеки, таким как подпапка журналов Adobe и другие. Например, только «системный» пользователь (группа?) Имеет права доступа к папке журналов Adobe и ее содержимому, а текущий пользователь даже не имеет записи в разрешениях, отображаемых в окне «Информация» для папки. .

Что я хочу сделать, чтобы точно:

  1. Получение прав администратора.
  2. Сохраните пароль в связке ключей, чтобы приложению не приходилось каждый раз раздражать пользователя. (Является ли хранение пароля плохой идеей? Возможно ли это?)
  3. Удалите файл, какими бы ни были разрешения для файла.

Я использую NSTask, потому что он предлагает уведомления о завершении задачи, получении текста от самой задачи и т. Д. Нужно ли мне использовать что-то еще? Если да, то как я могу реплицировать уведомления о завершении NSTask и дескриптор выходного файла при запуске rm и srm с правами администратора?

Я ищу самый безопасный способ справиться с ситуацией. то есть я не хочу, чтобы мое приложение стало дверью для атак на повышение привилегий.

Я посмотрел Руководство по программированию служб авторизации, но не уверен, какой случай подходит. Сначала я подумал, что AuthorizationExecuteWithPrivileges будет хорошей идеей, но после прочтения этой темы, похоже, что этот метод не рекомендуется по соображениям безопасности.

Подробный ответ будет приветствоваться. Я уверен, что некоторым из вас уже приходилось делать что-то подобное, и у них есть какой-то код и знания, которыми можно поделиться.

Заранее спасибо!

Обновление:

Теперь я могу сделать диалоговое окно аутентификации всплывающим и получить привилегии, например:

OSStatus status;
AuthorizationRef authRef;
    status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef);

AuthorizationRights authRights;
AuthorizationItem authItems[1];

authItems[0].name = kAuthorizationRightExecute;

authRights.count = sizeof(authItems) / sizeof(authItems[0]);
authRights.items = authItems;

AuthorizationFlags authFlags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed;

status = AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, authFlags, NULL);

Судя по всему, метод «Факторизованного приложения» выглядит наиболее подходящим. Дело в том, что мне rm уже кажется внешним помощником . Я не уверен, что мне предложили альтернативу setuid в документации. Могу ли я установить бит setuid для rm и запустить его, используя метод NSTask, который я уже реализовал? Это будет означать, что мне не нужно будет создавать свой собственный вспомогательный инструмент. Может ли кто-нибудь уточнить эту тему?

Я также посмотрел на образец BetterAuthorizationS, который предлагается в качестве более безопасной и недавней альтернативы битовому методу setuid, но нашел его чрезвычайно сложным для такого простого поведения. Есть подсказки?

Заранее спасибо за любую помощь!

Ответы [ 2 ]

8 голосов
/ 07 июня 2011

Возможно, немного поздно, но это может быть полезно для дальнейшего использования другими людьми. Большая часть кода от этого человека .

По сути, это во многом связано с авторизацией на Mac. Вы можете прочитать больше об этом здесь и здесь .

Код, который использует инструмент rm:

+ (BOOL)removeFileWithElevatedPrivilegesFromLocation:(NSString *)location
{
    // Create authorization reference
    OSStatus status;
    AuthorizationRef authorizationRef;

    // AuthorizationCreate and pass NULL as the initial
    // AuthorizationRights set so that the AuthorizationRef gets created
    // successfully, and then later call AuthorizationCopyRights to
    // determine or extend the allowable rights.
    // http://developer.apple.com/qa/qa2001/qa1172.html
    status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
    if (status != errAuthorizationSuccess)
    {
        NSLog(@"Error Creating Initial Authorization: %d", status);
        return NO;
    }

    // kAuthorizationRightExecute == "system.privilege.admin"
    AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0};
    AuthorizationRights rights = {1, &right};
    AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed |
                                kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;

    // Call AuthorizationCopyRights to determine or extend the allowable rights.
    status = AuthorizationCopyRights(authorizationRef, &rights, NULL, flags, NULL);
    if (status != errAuthorizationSuccess)
    {
        NSLog(@"Copy Rights Unsuccessful: %d", status);
        return NO;
    }

    // use rm tool with -rf
    char *tool = "/bin/rm";
    char *args[] = {"-rf", (char *)[location UTF8String], NULL};
    FILE *pipe = NULL;

    status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe);
    if (status != errAuthorizationSuccess)
    {
        NSLog(@"Error: %d", status);
        return NO;
    }

    // The only way to guarantee that a credential acquired when you
    // request a right is not shared with other authorization instances is
    // to destroy the credential.  To do so, call the AuthorizationFree
    // function with the flag kAuthorizationFlagDestroyRights.
    // http://developer.apple.com/documentation/Security/Conceptual/authorization_concepts/02authconcepts/chapter_2_section_7.html
    status = AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights);
    return YES;
}
4 голосов
/ 31 августа 2010

У меня была эта головная боль несколько месяцев назад.Я пытался запустить скрипт оболочки с правами администратора, который выключал мой компьютер в определенное время.Я чувствую твою боль.

Я использовал Образец BetterAuthorization, который был полным кошмаром, чтобы пройти через него.Но я выбрал самый прагматичный путь - я не стал пытаться понять все, что происходит, я просто ухватился за внутренности кода.Я хотел.Я не помню точно, что я изменил, но вы можете проверить мой код:

http://github.com/johngallagher/TurnItOff

Надеюсь, это поможет вам в поиске безопасного приложения!*

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...