Извлечь имя пользователя из SecKeychainItemRef, заданного SecKeychainFindGenericPassword`? - PullRequest
4 голосов
/ 11 декабря 2011

Из этого вопроса я знаю, что вы можете использовать SecKeychainFindGenericPassword без значения имени пользователя.Это все еще возвратит элемент цепочки для ключей для данной услуги.Но как мне тогда получить имя пользователя? Получить имена пользователей, хранящиеся в связке ключей, используя только ServiceName?ИЛИ: Где вы должны хранить имя пользователя?

//SecKeychainFindGenericPassword
//Finds the first generic password based on the attributes passed.

OSStatus SecKeychainFindGenericPassword (
   CFTypeRef keychainOrArray,
   UInt32 serviceNameLength,
   const char *serviceName,
   UInt32 accountNameLength,
   const char *accountName,
   UInt32 *passwordLength,
   void **passwordData,
   SecKeychainItemRef *itemRef
);

Мой код выглядит следующим образом:

UInt32 passwordLength = 0;
char *password = nil;

SecKeychainItemRef item = nil;

OSStatus returnStatus = SecKeychainFindGenericPassword(NULL, 9, @"MyAppName", 0, NULL, &passwordLength, (void **)&password, &item);

//Get password
NSString *passwordString = [[[NSString alloc] initWithData:[NSData dataWithBytes:password length:passwordLength] encoding:NSUTF8StringEncoding] autorelease];
SecKeychainItemFreeContent(NULL, password);

//Get username (not yet working)
UInt32 attributeTags[1];
*attributeTags = 'acct';// TODO: populate with the kSecAttrAccount constant (NOT a string cast to a UInt32)
//kSecAccountItemAttr = 'acct',

UInt32 formatConstants[1];
*formatConstants = 0; // TODO: populate with a format constant found in "cssmtype.h". I'm picking "0" = "string" in list below...

//SecKeychainAttributeInfo doc says: "A pointer to the first attribute format in the array. Attribute formats are of type CSSM_DB_ATTRIBUTE_FORMAT."

/* //found in "cssmtype.h"
 typedef uint32 CSSM_DB_ATTRIBUTE_FORMAT, *CSSM_DB_ATTRIBUTE_FORMAT_PTR;
 enum {
 CSSM_DB_ATTRIBUTE_FORMAT_STRING =          0,
 CSSM_DB_ATTRIBUTE_FORMAT_SINT32 =          1,
 CSSM_DB_ATTRIBUTE_FORMAT_UINT32 =          2,
 CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM =         3,
 CSSM_DB_ATTRIBUTE_FORMAT_REAL =                4,
 CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE =       5,
 CSSM_DB_ATTRIBUTE_FORMAT_BLOB =                6,
 CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32 =        7,
 CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX =         8
 };
*/

struct SecKeychainAttributeInfo attributeInfo, 1, *attributeTags, *formatConstants; //ERROR: "Expected ';' at end of declaration list.
//OR:
/*
struct SecKeychainAttributeInfo
{
    UInt32 1; //ERROR: "Expected ';' at end of declaration list.
    UInt32 *attributeTags;
    UInt32 *formatConstants;
}attributeInfo;
*/

/*
SecKeychainAttributeInfo *attributeInfo; //TODO: "change it to hold the structure directly"
attributeInfo->count = 1;
attributeInfo->tag = attributeTags;
attributeInfo->format = formatConstants;
*/

SecKeychainAttributeList *attributeList = nil;
OSStatus attributeStatus = SecKeychainItemCopyAttributesAndData(item, &attributeInfo, NULL, &attributeList, 0, NULL);

if (attributeStatus != noErr)
{
    if (_logsErrors)
        NSLog(@"Error (%@) - %s", NSStringFromSelector(_cmd), GetMacOSStatusErrorString(attributeStatus));
    return nil;
}


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

Как получить значение NSString имени пользователя, содержащегося вчто SecKeychainItemRef?

Ответы [ 2 ]

5 голосов
/ 12 декабря 2011
+ (EMGenericKeychainItem *)genericKeychainItemForService:(NSString *)serviceName
{
    if (!serviceName)
        return nil;

    const char *serviceNameCString = [serviceName UTF8String];

    UInt32 passwordLength = 0;
    char *password = nil;

    SecKeychainItemRef item = nil;
    OSStatus returnStatus = SecKeychainFindGenericPassword(NULL, strlen(serviceNameCString), serviceNameCString, 0, NULL, &passwordLength, (void **)&password, &item);

    UInt32 attributeTags[1];
    *attributeTags = kSecAccountItemAttr;

    UInt32 formatConstants[1];
    *formatConstants = CSSM_DB_ATTRIBUTE_FORMAT_STRING; //From "cssmtype.h" under "CSSM_DB_ATTRIBUTE_FORMAT".

    struct SecKeychainAttributeInfo
    {
        UInt32 count;
        UInt32 *tag;
        UInt32 *format;
    }attributeInfo;

    attributeInfo.count = 1;
    attributeInfo.tag = attributeTags;
    attributeInfo.format = formatConstants;

    SecKeychainAttributeList *attributeList = nil;
    OSStatus attributeStatus = SecKeychainItemCopyAttributesAndData(item, &attributeInfo, NULL, &attributeList, 0, NULL);

    if (attributeStatus != noErr || !item)
    {
        if (_logsErrors)
            NSLog(@"Error (%@) - %s", NSStringFromSelector(_cmd), GetMacOSStatusErrorString(returnStatus));
        return nil;
    }

    SecKeychainAttribute accountNameAttribute = attributeList->attr[0];

    NSString* accountName = [[[NSString alloc] initWithData:[NSData dataWithBytes:accountNameAttribute.data length:accountNameAttribute.length] encoding:NSUTF8StringEncoding] autorelease];

    NSString *passwordString = [[[NSString alloc] initWithData:[NSData dataWithBytes:password length:passwordLength] encoding:NSUTF8StringEncoding] autorelease];
    SecKeychainItemFreeContent(NULL, password);         

    return [EMGenericKeychainItem _genericKeychainItemWithCoreKeychainItem:item forServiceName:serviceName username:accountName password:passwordString];
}
0 голосов
/ 11 декабря 2011

Используйте функцию SecKeychainItemCopyAttributesAndData , чтобы получить имя учетной записи и любые другие интересующие вас атрибуты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...