运行具有提升权限的进程OS X 10.7& 10.8

时间:2012-07-16 03:32:57

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

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

查看现有的示例会引导我AuthorizationExecuteWithPrivileges,现在似乎已被弃用。

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

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

编辑:

最后是否有一些方法只需运行一个具有权限的命令而无需永久安装任何东西?虽然这种新方法更安全,但看起来非常沉重。

2 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分:0)

我遇到了与你相同的问题,需要它为MacOS X的OpenVPN管理器应用程序。你的解决方案远非最佳,因为你为每个人设置setuid root打开openvpn二进制文件。 这是一个安全漏洞,应该避免使用,因为当你使用smjobbless helper时完全没必要。这个帮助程序以root身份运行,可以为您执行所有操作并具有管理权限,因此您可以通过此帮助程序启动openvpn,而无需在openvpn二进制文件上设置setuid root。

Apple设计此流程时,只有您的应用程序(主应用程序)可以与此帮助程序进行通信,因为您的主应用程序和助手已使用您的开发人员证书进行签名。 任何恶意App都无法使用此帮助程序。

当你看到Nathans代码时,你会看到,他设法向这个助手发送消息并从这个助手那里得到答案。 在他的例子中,有类似的"嘿那里有Helper App"答案是"嘿那里有Host App"。

所以为了得到有用的东西你只需要向帮助应用程序发送命令,在帮助程序端提取这些命令并使用提升的权限启动它们,因为帮助程序App以提升的权限运行。

看看Nathans的代码,有类似的风格(在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连接。