以root用户编程方式启动OSX

时间:2014-08-19 09:26:20

标签: objective-c macos cocoa shell

我正在尝试以root身份从OSX应用程序使用launchctl启动samba服务,但我收到错误状态-60031。我可以毫无问题地运行终端中的命令:

sudo launchctl load -F /System/Library/LaunchDaemons/com.apple.smbd.plist

在Objective-c代码中,我正在使用(我知道它已被弃用,但这不应该是这里的问题)AuthorizationExecuteWithPrivileges方法。

以下是代码:

    NSString *command = @"launchctl";

    // Conversion of NSArray args to char** args here (not relevant part of the code)

    OSStatus authStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &_authRef);
    if (authStatus != errAuthorizationSuccess) {
        NSLog(@"Failed to create application authorization: %d", (int)authStatus);
        return;
    }

    FILE* pipe = NULL;
    AuthorizationFlags flags = kAuthorizationFlagDefaults;
    AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0};
    AuthorizationRights rights = {1, &right};

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

    OSStatus status = AuthorizationExecuteWithPrivileges(_authRef,
                                                         command.UTF8String,
                                                         flags,
                                                         args,
                                                         &pipe);
    if (status != errAuthorizationSuccess) {
        NSLog(@"Error executing command %@ with status %d", command, status);
    } else {
        // some other stuff
    }

我还尝试使用不同的标志然后使用kAuthorizationFlagDefaults,但这导致了相同的问题或错误代码-60011 - >无效的旗帜。

我在这做错了什么,拜托?

2 个答案:

答案 0 :(得分:4)

我建议使用STPrivilegedTask - https://github.com/sveinbjornt/STPrivilegedTask

我有类似的问题,我在上面找到了写得很好的包装器。它很简单直接。 如果必须,您可以根据需要对其进行修改,否则请将其用作!!!

它对我有用,我希望它也能为你提供帮助。

感谢。

更新(2014年8月28日): 执行命令 root权限之间存在差异,执行命令 root!

在您的特定情况下,您正在尝试加载/卸载守护程序(必须属于root)。在这种情况下,您必须以root身份执行命令 。如果您尝试仅使用root权限加载/卸载,那么您将在用户下运行守护程序! - 不好!

现在,您的代码示例和我对STPrivilegedTask的引用都使用相同的代码,并允许用户使用root权限执行以root身份执行任务!为了以root身份执行,您有几个选择。首先,您可能希望查看Apple Docs的推荐方式。在我的情况下,我不能采用推荐的方式,因为我的应用程序没有签名,也没有签名+它需要在旧的OSX上工作。

所以我的解决方案很简单。创建一个命令实用程序帮助工具,让它假定为root并执行通过参数传递给它的任何内容。现在请注意(这不是非常安全的做事方式)。另请注意,您将使用root权限调用helper工具,并将采用root身份。

<强>代码:

 int main(int argc, const char * argv[])
 {

@autoreleasepool {

    if (argc >= 2)
    {
        setuid(0);  // Here is a key - set user id to 0 - meaning become a root and everything below executes as root.

        NSMutableArray *arguments = [[NSMutableArray alloc] init];
        NSString *command = [[NSString alloc] initWithFormat:@"%s", argv[1]];

        for (int idx = 2; idx < argc; idx++) {
            NSString *tmp = [[NSString alloc] initWithFormat:@"%s", argv[idx]];
            [arguments addObject:tmp];
        }

        NSTask *task = [[NSTask alloc] init];
        [task setLaunchPath:command];
        [task setArguments:arguments];

        NSPipe * out = [NSPipe pipe];
        [task setStandardOutput:out];
        [task launch];

        [task waitUntilExit];

        NSFileHandle * read = [out fileHandleForReading];
        NSData * dataRead = [read readDataToEndOfFile];
        NSString * stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];

        printf("%s", [stringRead UTF8String]);

        }
     return 0;
     }
 }

答案 1 :(得分:0)

查看the documentation,您的代码似乎缺少kAuthorizationFlagExtendRights标记,这在安全管理服务器授予请求的权限时是必需的。相关摘录;

  

... kAuthorizationFlagDefaults常量将位掩码归零。该   kAuthorizationFlagExtendRights常量指示安全管理服务器   授予权利。 没有此标记,AuthorizationCopyRights   和AuthorizationCreate函数将返回相应的错误   代码,但没有权利扩展到用户 ...

来自kAuthorizationFlagExtendRights的文档:

  

kAuthorizationFlagExtendRights

     

如果设置了此掩码指定的位,安全管理服务器将尝试   授予所要求的权利   ...

尝试在调用flags之前将此标记添加到AuthorizationCopyRights(),并且可能还包括kAuthorizationFlagPartialRights以限制授予的权限。