4

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.

Michał Siwek
  • 794
  • 1
  • 10
  • 25
  • What does SecKeychainUnlock return? – tsnorri Jun 25 '14 at 22:37
  • @TuukkaNorri the value of returning OSStatus is 0, it seems to run fine. – Michał Siwek Jun 26 '14 at 10:19
  • 1.) Do you recompile the trusted application between having added it to the ACL and trying to access the created item? // 2.) Are you using code signing? – mvanallen Jun 26 '14 at 22:34
  • @mvanallen 1) I'm not - I'm compiling the application that adds itself to the ACL and then tries to read from the keychain, but all in its single run. 2) No, I'm not, and I'd like to keep it this way if it's possible. However, the problem might be that I'm moving the keychain into different place after creating it and writing the ACLs into it. I'll try to create it at the destination place instead of moving it, but I'll need superuser privileges for that (I need to write to `/Library`). What seems to you to be the best way to run `SecKeychainCreate` as root? – Michał Siwek Jun 28 '14 at 15:29

1 Answers1

4

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;
}
tsnorri
  • 1,966
  • 5
  • 21
  • 29
  • Looks like the problem is that I'm moving the keychain file into different place after its creation, but your answer pointed me into right direction. Thanks and here's your 50pt :) – Michał Siwek Jun 30 '14 at 13:59