4

キーチェーンを作成してから、事前定義された信頼できるアプリケーション リストを含む項目を追加しています。

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

Keychain Access アプリケーションで新しく作成したキーチェーンを開くと、信頼できるアプリのリストに自分のアプリケーションが表示されます。

ACL 設定

問題は、信頼できるアプリケーションの 1 つを介してそのキーチェーンからキーを読み取ろうとしたときです。

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 The user name or passphrase you entered is not correct.

コードの前半で を実行SecKeychainSetUserInteractionAllowed(0)し、この行をコメントアウトすると、アプリケーションがキーチェーンにアクセスする許可を求めるプロンプトがシステムから表示されます。許可すると、すべて正常に実行されます。ただし、要点は、ユーザーにプロンプ​​トを表示せずにそれを実行できる必要があるということです。アプリを ACL に追加したので、このように動作することを期待しています。私が間違っていることを知っていますか?

添付のスクリーンショットで「すべてのプログラムがこのアイテムにアクセスできる」ラジオボックスにチェックを入れると、すべてがプロンプトなしで機能します。しかし、リストされているアプリだけにアクセスできるようにしたくありません。

4

1 に答える 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;
}
于 2014-06-26T22:02:16.147 に答える