4

我正在尝试使用 SMJobBless 安装安全帮助工具。当它失败并且在调用 SMJobBless 之前,我正在调用 SMJobRemove,因为我需要删除该工具的旧版本并且这会成功。SMJobBless 返回错误代码 4098。NSError 对象只是告诉我“操作无法完成。CodeSigning 子系统中出现错误。”

如果我重新运行我的代码,SMJobBless 函数就会起作用。我认为这是因为它之前已被删除,但为什么它第一次没有工作?然后我可以与该工具通信,一切正常。观察到一切运行正常,我相信我可以确定我满足文档中描述的 SMJobBless 的五个要求。

如果我增加工具的版本并重试,SMJobRemove 将起作用,但是,SMJobBless 再次出现错误代码 4098。

如果重要的话,我使用的是 OS X 10.7.3。

4

1 回答 1

4

可能是您正在调用CFBundleCopyInfoDictionaryForURL代码签名的帮助工具吗?

如果是这样,看起来这个函数似乎破坏了代码签名的有效性。(大概是因为CFBundle修改了内存中的Info.plist数据,但这只是我的猜测。)

解决方案是使用SecCodeCopySigningInformation读取帮助工具的版本信息:

-(NSString *) bundleVersionForCodeSignedItemAtURL:(NSURL *)url {
    OSStatus status;

    // Sanity check -- nothing begets nothing
    if (!url) {
        return nil;
    }

    // Get the binary's static code
    SecStaticCodeRef codeRef;
    status = SecStaticCodeCreateWithPath((CFURLRef)url, kSecCSDefaultFlags, &codeRef);
    if (status != noErr) {
        NSLog(@"SecStatucCodeCreateWithPath() error for %@: %d", url, status);
        return nil;
    }

    // Get the code signature info
    CFDictionaryRef codeInfo;
    status = SecCodeCopySigningInformation(codeRef, kSecCSDefaultFlags, &codeInfo);
    if (status != noErr) {
        NSLog(@"SecCodeCopySigningInformation() error for %@: %d", url, status);
        CFRelease(codeRef);
        return nil;
    }

    // The code signature info gives us the Info.plist that was signed, and
    // from there we can retrieve the version
    NSDictionary *bundleInfo = (NSDictionary *) CFDictionaryGetValue(codeInfo, kSecCodeInfoPList);
    NSString *version = [bundleInfo objectForKey:@"CFBundleVersion"];

    // We have ownership of the code signature info, so we must release it.
    // Before we do that, we need to hold onto the version otherwise we go
    // crashing and burning.
    [[version retain] autorelease];
    CFRelease(codeInfo);
    CFRelease(codeRef);

    return version;
}

值得称赞的是:有关的重要信息CFBundleCopyInfoDictionaryForURL来自Ian MacLeod'sSMJobKit

于 2013-02-28T18:16:36.857 回答