Создание элемента цепочки для ключей с типом «Пароль веб-формы» в Mac OS X - PullRequest
4 голосов
/ 20 октября 2011

Я работаю над приложением, в котором когда пользователь выбирает пункт меню, он переносится на веб-страницу. Веб-страница требует аутентификации, и чтобы упростить для пользователя задачу, я хотел бы передать их аутентификационные данные в Safari / Firefox / Chrome, который хранится в моем приложении.

Я пытался создавать общие и интернет-элементы цепочки для ключей, которые прекрасно отображаются в Keychain Access, но ни один веб-браузер не уловил их.

Я заметил, что элементы цепочки для ключей, сохраняемые для браузеров, имеют тип "Пароль веб-формы".

Когда я пытаюсь создать элемент цепочки для ключей с типом 'kSecAuthenticationTypeHTMLForm', он отображается в Доступе цепочки для ключей как 'интернет-пароль'. Я изменил код из класса EMKeychain:

+ (EMInternetKeychainItem *)addInternetKeychainItemForServer:(NSString *)server
                                            withUsername:(NSString *)username
                                                password:(NSString *)password
                                                    path:(NSString *)path
                                                    port:(NSInteger)port
                                                protocol:(SecProtocolType)protocol
{
if (!username || !server || !password)
    return nil;

const char *serverCString = [server UTF8String];
const char *usernameCString = [username UTF8String];
const char *passwordCString = [password UTF8String];
const char *pathCString = [path UTF8String];

if (!path || [path length] == 0)
    pathCString = "";

SecKeychainItemRef item = nil;
OSStatus returnStatus = SecKeychainAddInternetPassword(NULL, strlen(serverCString), serverCString, 0, NULL, strlen(usernameCString), usernameCString, strlen(pathCString), pathCString, port, protocol, kSecAuthenticationTypeHTMLForm, strlen(passwordCString), (void *)passwordCString, &item);

if (returnStatus != noErr || !item)
{
    if (_logsErrors)
        NSLog(@"Error (%@) - %s", NSStringFromSelector(_cmd), GetMacOSStatusErrorString(returnStatus));
    return nil;
}
return [EMInternetKeychainItem _internetKeychainItemWithCoreKeychainItem:item forServer:server username:username password:password path:path port:port protocol:protocol];
}

1 Ответ

10 голосов
/ 29 октября 2011

Наиболее вероятная проблема состоит в том, что запись цепочки для ключей создается с ACL, который не предоставляет доступ к его содержимому Safari.(Я думаю, что Chrome и Firefox используют свои собственные проприетарные базы паролей вместо цепочки для ключей, поэтому изменение цепочки для ключей не повлияет на эти браузеры.)

Попробуйте использовать SecKeychainItemSetAccess для разрешения доступа ко всем приложениям.Я использую следующий код для создания такого разрешающего объекта SecAccess:

// Create an access object.
SecAccessRef access;
status = SecAccessCreate(CFSTR("item description"), 
                         NULL, // Only this app has access (this'll get changed in a moment)
                         &access);
if (status) { ... }

// Override access control to provide full access to all applications.
NSArray *aclList = nil;
status = SecAccessCopyACLList(access, (CFArrayRef *)&aclList);
if (status) { ... }
for (id object in aclList) { // will do just one iteration
    SecACLRef acl = (SecACLRef)object;

    CFArrayRef applist = NULL;
    CFStringRef desc = NULL;
    CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cakps;

    status = SecACLCopySimpleContents(acl, &applist, &desc, &cakps);
    if (status)  { ... }

    status = SecACLSetSimpleContents(acl, 
                                     NULL, // All applications.
                                     desc,
                                     &cakps);
    if (status) { ... }

    if (applist != NULL)
        CFRelease(applist);
    if (desc != NULL)
        CFRelease(desc);
}
...