从可信应用程序访问OS X钥匙串项目

4

我正在创建一个钥匙链,然后向其中添加了一个预定义的可信应用程序列表:

SecKeychainCreate([keychainPath UTF8String], (UInt32)strlen(keychainPass), keychainPass, FALSE, NULL, &someKeychain);
OSStatus someStatus = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &list, len, encryptedPass, someKeychain, accessRef, &someKeychainItem);

当我使用钥匙串访问应用程序打开新创建的钥匙串时,我可以在受信任的应用程序列表中看到我的应用程序: acl settings 问题是,当我尝试通过其中一个受信任的应用程序读取该钥匙串中的密钥时,出现了问题。
SecKeychainUnlock(someKeychain, (UInt32)strlen(keychainPass), keychainPass, TRUE);

UInt32 passwordLen = 0;
void *passData = nil;

const char *cUser_name = [NSUserName() cStringUsingEncoding:NSUTF8StringEncoding];

OSStatus genericPassErr = SecKeychainFindGenericPassword(someKeychain, 0, NULL, strlen(cUser_name), cUser_name, &passwordLen, &passData, NULL);

genericPassErr等于-25293,这意味着:Error: 0xFFFF9D33 -25293 您输入的用户名或密码不正确。

在代码中早些时候,我运行了SecKeychainSetUserInteractionAllowed(0),如果我注释掉这一行,系统会提示我允许应用程序访问钥匙串,如果我同意,一切都可以正常运行。然而,整个问题在于我需要能够在不提示用户的情况下完成操作。由于我已将应用程序添加到ACL中,因此我希望它可以像这样工作。您知道我做错了什么吗?

当我在附加的屏幕截图中勾选“所有程序都可以访问此项目”单选框时,一切也可以正常运行,但我不希望每个人都能访问它,只有列出的应用程序才能访问。


SecKeychainUnlock 返回什么内容? - tsnorri
@TuukkaNorri 返回 OSStatus 的值为0,看起来运行良好。 - Michał Siwek
1.) 在将可信应用程序添加到ACL并尝试访问创建的项目之间,您是否重新编译了它? 2.) 您是否正在使用代码签名? - mvanallen
@mvanallen 1) 我不是 - 我正在编译应用程序,将其添加到ACL中,然后尝试从钥匙串中读取,但所有这些都在单个运行中完成。2) 不,我不是,如果可能的话,我想保持这种状态。但是,问题可能是我在创建并将ACL写入钥匙串后将其移动到不同的位置。我将尝试在目标位置创建它而不是移动它,但我需要超级用户权限才能这样做(我需要写入/Library)。在您看来,运行SecKeychainCreate作为root的最佳方法是什么? - Michał Siwek
1个回答

4

我成功地制作了一个类似的测试程序。然而,在每次重建后,我必须将该工具从“始终允许列表”中删除并重新添加。如果不这样做,我会得到相同的错误代码。

以下是代码:

#import <Foundation/Foundation.h>
#import <Security/Security.h>

int main()
{
    @autoreleasepool
    {
        SecKeychainRef kc;
        OSStatus status = SecKeychainSetUserInteractionAllowed(false);
        printf("status: %d\n", status);

        status = SecKeychainOpen("/Users/tsnorri/Library/Keychains/test.keychain", &kc);
        printf("status: %d\n", status);

        {
            char const *keychainPass = "test123";
            status = SecKeychainUnlock(kc, (UInt32) strlen(keychainPass), keychainPass, true);
            CFStringRef err = SecCopyErrorMessageString(status, NULL);
            printf("status: %d err: %s\n", status, [(id) err UTF8String]);
            CFRelease(err);
        }

        UInt32 passwordLen = 0;
        void *passData = NULL;

        char const *userName = "tsnorri";
        char const *serviceName = "test";

        {
            SecKeychainItemRef item = NULL;
            status = SecKeychainFindGenericPassword(kc, strlen(serviceName), serviceName, strlen(userName), userName, &passwordLen, &passData, &item);
            CFStringRef err = SecCopyErrorMessageString(status, NULL);
            printf("status: %d err: %s\n", status, [(id) err UTF8String]);
            CFRelease(err);
        }

        printf("pass: %s\n", passData);
    }
    return 0;
}

看起来问题在于我创建密钥链文件后将其移动到了不同的位置,但是你的回答指引了我正确的方向。谢谢,这是你的50分 :) - Michał Siwek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接