Доступ к элементу цепочки ключей OS X из доверенного приложения
Я создаю цепочку для ключей, а затем добавляю элемент с предопределенным списком доверенных приложений:
SecKeychainCreate([keychainPath UTF8String], (UInt32)strlen(keychainPass), keychainPass, FALSE, NULL, &someKeychain);
OSStatus someStatus = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &list, len, encryptedPass, someKeychain, accessRef, &someKeychainItem);
Когда я открываю вновь созданную цепочку для ключей с помощью приложения Keychain Access, я вижу свое приложение в списке доверенных приложений:
Проблема в том, что когда я пытаюсь прочитать ключ из этой цепочки для ключей через одно из доверенных приложений
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
равняется -25293
, что значит Error: 0xFFFF9D33 -25293 The user name or passphrase you entered is not correct.
Раньше в коде я запускаю SecKeychainSetUserInteractionAllowed(0)
и, если я закомментирую эту строку, система запросит у меня разрешение на доступ приложения к цепочке для ключей, и если я предоставлю ее, все будет работать нормально. Тем не менее, все дело в том, что я должен быть в состоянии сделать это без запроса пользователя. И я ожидаю, что это будет работать так, как я добавил приложение в ACL. Вы знаете, что я делаю не так?
Также все работает без подсказок, когда я отмечаю переключатель "все программы имеют доступ к этому элементу" на прикрепленном скриншоте. Но я не хочу, чтобы все могли получить к нему доступ, только перечисленные приложения.
1 ответ
Мне удалось заставить подобную тестовую программу работать. Однако мне приходилось удалять и повторно добавлять инструмент в список всегда разрешенных после каждого перестроения. Я получил тот же код ошибки, когда я этого не делал.
Вот код:
#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;
}