11

我正在制作一个删除日志文件的小应用程序。我正在使用一个运行 rm 和 srm(安全 rm)的 NSTask 实例来删除文件。

我希望能够删除以下文件:

  • /图书馆/日志
  • 〜/图书馆/日志

问题是用户帐户无权访问系统库文件夹中的某些文件,例如 Adob​​e 日志子文件夹等。例如,只有“系统”用户(组?)对 Adob​​e 日志文件夹及其内容具有 r/w 权限,而当前用户甚至在该文件夹的“获取信息”窗口中显示的权限中没有条目.

我希望能够做什么:

  1. 获得管理员权限。
  2. 将密码存储在钥匙串中,这样应用程序就不必每次都唠叨用户(存储密码是个坏主意吗?有可能吗?)
  3. 无论文件权限是什么,都可以删除文件。

我使用 NSTask 是因为它提供任务完成通知、从任务本身获取文本输出等。我需要使用其他东西吗?如果是这样,我如何在以管理员权限运行 rm 和 srm 时复制 NSTask 的完成通知和输出文件句柄?

我正在寻找最安全的方式来处理这种情况。即我不希望我的应用程序成为特权升级攻击的门户。

我查看了授权服务编程指南,但不确定哪种情况适合。起初我认为这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);

从外观上看,“Factored Application”方法似乎最合适。问题是,对我来说,rm 已经看起来像是一个外部帮助工具。我不确定我是否得到了文档中建议的 setuid 替代方法。我可以在 rm 上设置 setuid 位并使用我已经实现的 NSTask 方法运行它吗?这意味着我不需要创建自己的辅助工具。有人可以详细说明这个问题吗?

我还查看了 BetterAuthorizationSample,它被建议作为 setuid 位方法的更安全和最新的替代方案,但发现它对于诸如简单行为之类的非常复杂。有什么提示吗?

提前感谢您的帮助!

4

2 回答 2

9

也许有点晚了,但这可能对其他人的未来参考有用。大部分代码来自这个人

基本上,它与 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;
}
于 2011-06-07T18:29:44.070 回答
4

几个月前我有这种头痛。我试图让一个以管理员权限运行的 shell 脚本在某个时间关闭我的计算机。我感觉到你的痛苦。

我使用了 BetterAuthorizationSample,这是一个彻头彻尾的噩梦。但我采取了最务实的路线——我没有费心去理解正在发生的一切,我只是抓住了代码的核心。

我没花那么长时间就让它做我想做的事。我不记得我究竟做了什么改变,但欢迎您查看我的代码:

http://github.com/johngalagher/TurnItOff

我希望这有助于您寻求安全的应用程序!

于 2010-08-31T17:46:22.137 回答