【问题标题】:Running a process with elevated privileges OS X 10.7 & 10.8以提升的权限运行 OS X 10.7 和 10.8 的进程
【发布时间】:2012-07-14 22:00:18
【问题描述】:

我正在尝试以提升的权限运行一个进程 - 特别是 OpenVPN,它需要 root 权限才能将路由添加到系统。

四处寻找现有示例将我引向AuthorizationExecuteWithPrivileges,它现在似乎已被弃用。

我尝试了新的SMJobBless 方法,但我对它的可行性有一些疑问。据我了解,我可以创建一个单独的特权工具并通过套接字与其通信,以要求该工具执行特权命令。但是,我似乎无法弄清楚如何启动 OpenVPN 进程并实时捕获其标准输出,因为主应用程序本身不会启动该进程。

另一个选项是在 OpenVPN 可执行文件上使用 setuid。我可以使用SMJobBless安装的helper来设置可执行文件的文件权限和setuid,然后通过NSTask正常运行吗?

编辑:

最后有没有什么方法可以只运行一个具有特权的命令而无需永久安装任何东西?虽然这种新方法更安全,但看起来很笨重。

【问题讨论】:

    标签: objective-c xcode macos cocoa osx-lion


    【解决方案1】:

    我设法通过使用帮助程序并将其与 XPC 通信(Nathan de Vries's Blog 上显示的方法)来使用 SMJobBless 方法。使用这个助手,我将外部进程的权限设置为 04555(setuid,rx)。然后移除 SMJob,因为它不再需要。本质上是在模仿“一次性”特权工作。

    在我能够使用 NSTask 启动进程并在我的主应用程序中捕获其输出之后。

    此外,我在开始时检查是否在可执行文件上设置了正确的权限,如果没有,则重新祝福 SMJob 助手并设置权限。

    如果有人有更清洁的解决方案,请随时分享。谢谢!

    【讨论】:

    • 你好,你能在gist.github上放一些源代码吗?我正在处理几乎相同的问题,我认为很多其他开发人员会喜欢这个:)。
    • 当然,有什么特别的部分让你卡住了吗?只是想知道要粘贴哪个部分。
    • 您好,您已经分享了您的解决方案了吗?我有完全一样的问题。你是如何从主进程调用 openvpn 的?
    【解决方案2】:

    我遇到了和你一样的问题,需要它用于 MacOs X 的 OpenVPN 管理器应用程序。你的解决方案远非最佳,因为你为每个设置 setuid root 的人打开了 openvpn 二进制文件。 这是一个安全漏洞,应该避免,因为当您使用 smjobbless 助手时,这是完全没有必要的。这个助手以 root 身份运行,可以为你做任何你想做的事情,并且具有管理权限,所以你可以通过这个助手启动 openvpn,而无需在 openvpn 二进制文件上设置 setuid root。

    Apple 将此过程设计为只有您的应用程序,即主应用程序,才能与此助手进行通信,因为您的主应用程序和您的助手使用您的开发人员证书进行签名。 任何恶意 App 都无法使用此助手。

    当您查看 Nathans 代码时,您会发现他设法将消息发送给该助手并从该助手那里获得答案。 在他的示例中,有类似“Hey there Helper App”之类的东西,答案是“Hey there Host App”。

    因此,要从中获得有用的信息,您只需向助手应用程序发送命令,在助手端提取这些命令并在助手应用程序以提升的权限运行时以提升的权限启动它们。

    查看 Nathans 代码,有类似的 sty(在 smjobblessappcontroller.m 中):

    xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
        const char* request = "openvpn --config OpenvpnConnection.ovpn";
        xpc_dictionary_set_string(message, "request", request);
    
        [self appendLog:[NSString stringWithFormat:@"Sending request: %s", request]];
    
        xpc_connection_send_message_with_reply(connection, message, dispatch_get_main_queue(), ^(xpc_object_t event) {
            const char* response = xpc_dictionary_get_string(event, "reply");
            [self appendLog:[NSString stringWithFormat:@"Received response: %s.", response]];
        });
    

    通过这个,您可以将 openvpn 命令发送到您的助手应用程序。您只需在助手端提取此命令即可以提升的权限启动进程。

    查看 smjobblesshelper.c 并做某事(在 __XPC_Peer_Event_Handler else 分支中):

    const char *response = xpc_dictionary_get_string(event, "request");
    

    在字符串响应中你有你的 openvpn 命令,现在简单地启动它:

    system(response);
    

    就是这样,这与提升的权限有关。现在您可以在您的应用程序中使用它,或者在您的主​​应用程序的 IBAction 按钮中使用它,以便在每次用户单击此按钮时根据需要启动 openvpn 连接。

    【讨论】:

    • 如果你想要 openvpn 的输出,你可以简单地将它重定向到一个 txt 文件中,你可以从你的主应用程序访问,看看是否一切正常。
    猜你喜欢
    • 2020-05-21
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 2011-12-16
    • 2013-05-31
    • 1970-01-01
    相关资源
    最近更新 更多