Michał Siwek
Michał Siwek

Reputation: 804

Accessing OS X keychain item from trusted application

I'm creating a keychain and then I'm adding an item with predefined trusted aplication list to it:

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

When I open the newly created keychain with Keychain Access application, I can see my application on the trusted app list:

acl settings

The problem is, when I try to read the key from that keychain through one of the trusted applications

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 equals -25293, which means Error: 0xFFFF9D33 -25293 The user name or passphrase you entered is not correct.

Earlier in the code, I run SecKeychainSetUserInteractionAllowed(0), and if I comment this line out, I get prompted by the system for my permission for the application to access the keychain, and if I grant it, everything runs fine. However, the whole point is that I need to be able to do that without prompting the user. And I expect it to work like this since I added the app to the ACL. Do you know what am I doing wrong?

Everything works without prompt as well when I tick the "all programs have access to this item" radio box in the attached screenshot. But I don't want everyone to be able to access it, just the listed apps.

Upvotes: 4

Views: 2184

Answers (1)

tsnorri
tsnorri

Reputation: 2097

I was able to make a similar test program work. However, I had to remove and re-add the tool to the always allowed list after each time I had rebuilt it. I did get the same error code when not doing that.

Here's the code:

#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;
}

Upvotes: 4

Related Questions