Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Attributes of Keychain Items

I'm trying to get the attributes of a keychain item. This code should look up all the available attributes, then print off their tags and contents.

According to the docs I should be seeing tags like 'cdat', but instead they just look like an index (i.e., the first tag is 0, next is 1). This makes it pretty useless since I can't tell which attribute is the one I'm looking for.

    SecItemClass itemClass;
    SecKeychainItemCopyAttributesAndData(itemRef, NULL, &itemClass, NULL, NULL, NULL);

    SecKeychainRef keychainRef;
    SecKeychainItemCopyKeychain(itemRef, &keychainRef);

    SecKeychainAttributeInfo *attrInfo;
    SecKeychainAttributeInfoForItemID(keychainRef, itemClass, &attrInfo);

    SecKeychainAttributeList *attributes;
    SecKeychainItemCopyAttributesAndData(itemRef, attrInfo, NULL, &attributes, 0, NULL);

    for (int i = 0; i < attributes->count; i ++)
    {
        SecKeychainAttribute attr = attributes->attr[i];
        NSLog(@"%08x %@", attr.tag, [NSData dataWithBytes:attr.data length:attr.length]);
    }

    SecKeychainFreeAttributeInfo(attrInfo);
    SecKeychainItemFreeAttributesAndData(attributes, NULL);
    CFRelease(itemRef);
    CFRelease(keychainRef);
like image 917
rgov Avatar asked Oct 15 '22 14:10

rgov


2 Answers

There are two things you should be doing here. Firstly, you need to handle "generic" itemClasses before the call to SecKeychainAttributeInfoForItemID...

switch (itemClass)
{
    case kSecInternetPasswordItemClass:
        itemClass = CSSM_DL_DB_RECORD_INTERNET_PASSWORD;
        break;
    case kSecGenericPasswordItemClass:
        itemClass = CSSM_DL_DB_RECORD_GENERIC_PASSWORD;
        break;
    case kSecAppleSharePasswordItemClass:
        itemClass = CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD;
        break;
    default:
        // No action required
}

Second, you need to convert the attr.tag from a FourCharCode to a string, i.e.

NSLog(@"%c%c%c%c %@",
    ((char *)&attr.tag)[3],
    ((char *)&attr.tag)[2],
    ((char *)&attr.tag)[1],
    ((char *)&attr.tag)[0],
    [[[NSString alloc]
        initWithData:[NSData dataWithBytes:attr.data length:attr.length]
        encoding:NSUTF8StringEncoding]
    autorelease]]);

Notice that I've also output the data as a string -- it almost always is UTF8 encoded data.

like image 96
Matt Gallagher Avatar answered Oct 26 '22 23:10

Matt Gallagher


I think the documentation leads to a bit of confusion.

The numbers I'm seeing appear to be keychain item attribute constants for keys.

However, SecKeychainItemCopyAttributesAndData returns a SecKeychainAttributeList struct, which contains an array of SecKeychainAttributes. From TFD:

tag A 4-byte attribute tag. See “Keychain Item Attribute Constants” for valid attribute types.

The attribute constants (of the non-"for keys" variety) are the 4-char values I expected to see.

like image 21
rgov Avatar answered Oct 27 '22 01:10

rgov