4

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

环顾四周寻找现有示例将我带到AuthorizationExecuteWithPrivileges,现在似乎已弃用。

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

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

编辑:

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

4

2 回答 2

1

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

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

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

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

于 2012-07-19T00:26:43.043 回答
0

我和你有同样的问题,需要它用于 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 连接。

于 2014-07-25T14:25:24.163 回答