【问题标题】:Is there anyway to access system keychain in OS X from objective C无论如何从目标C访问OS X中的系统钥匙串
【发布时间】:2014-11-21 12:06:47
【问题描述】:

我正在尝试将密码保存在系统钥匙串中,但它给出了“写入权限错误”,有没有办法以 root 身份访问它并使用 AuthorizationRef 或任何东西保存密码?

+ (int) createItem:(NSString*)label withService:(NSString*)service account:(NSString*)account description:(NSString*)description andPassword:(NSString*)password {

// This variable will hold all sorts of operation status responses
OSStatus status;

// Converting the NSStrings to char* variables which we will need later
const char *labelUTF8 = [label UTF8String];
const char *serviceUTF8 = [service UTF8String];
const char *accountUTF8 = [account UTF8String];
const char *descriptionUTF8 = [description UTF8String];
const char *passwordUTF8 = [password UTF8String];

// This variable is soon to hold the System Keychain
SecKeychainRef keychain = NULL;

status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &keychain);
if (status == errSecSuccess) {
    NSLog(@"Succeeded opening System Keychain");
} else {
    NSLog(@"Could not obtain System Keychain: %@", SecCopyErrorMessageString(status, NULL));
    return 60;
}

NSLog(@"Unlocking System Keychain");
status = SecKeychainUnlock(keychain, 0, NULL, FALSE);
if (status == errSecSuccess) {
    NSLog(@"Succeeded unlocking System Keychain");
} else {
    NSLog(@"Could not unlock System Keychain: %@", SecCopyErrorMessageString(status, NULL));
    return 61;
}

// This variable is going to hold our new Keychain Item
SecKeychainItemRef item = nil;

SecAccessRef access = nil;
status = SecAccessCreate(CFSTR("Some VPN Test"), (__bridge CFArrayRef)(self.trustedApps), &access);

if(status == noErr) {
    NSLog(@"Created empty Keychain access object");
} else {
    NSLog(@"Could not unlock System Keychain: %@", SecCopyErrorMessageString(status, NULL));
    return 62;
}

// Putting together the configuration options
SecKeychainAttribute attrs[] = {
    {kSecLabelItemAttr, (int)strlen(labelUTF8), (char *)labelUTF8},
    {kSecAccountItemAttr, (int)strlen(accountUTF8), (char *)accountUTF8},
    {kSecServiceItemAttr, (int)strlen(serviceUTF8), (char *)serviceUTF8},
    {kSecDescriptionItemAttr, (int)strlen(descriptionUTF8), (char *)descriptionUTF8},
};

SecKeychainAttributeList attributes = {sizeof(attrs) / sizeof(attrs[0]), attrs};
status = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, (int)strlen(passwordUTF8), passwordUTF8, keychain, access, &item);
NSLog(@"item %@", item);
if(status == noErr) {
    NSLog(@"Successfully created Keychain Item");
} else {
    NSLog(@"Creating Keychain item failed: %@", SecCopyErrorMessageString(status, NULL));
    return 63;
}

return 0;

}

当我向 NSTask 发出命令并启动它时,我也尝试使用 shell 脚本来执行此操作,它会产生相同的输出。有谁知道应该怎么做?

【问题讨论】:

    标签: objective-c macos keychain


    【解决方案1】:

    试试这个:

    //first check if item already exists, if it is - it might cause an error while trying to save data
    if([self tryToFetchForService:service account:account])
      [self deleteItemForService:service account:account];
    NSDictionary *query=@{(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
                          (__bridge id)kSecAttrService:service,
                          (__bridge id)kSecAttrAccount:account,
                          (__bridge id)kSecValueData:password,
                          (__bridge id)kSecAttrLabel:description};
    status=SecItemAdd((__bridge CFDictionaryRef)query,NULL);
    if(status!=errSecSuccess && error!=NULL)
        *error=...; // error initialize
    

    您需要包含安全框架。 如果您需要从钥匙串中删除对象,请查看以下内容

    NSDictionary *query=@{(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
                          (__bridge id)kSecAttrService:service,
                          (__bridge id)kSecAttrAccount:account,
                          (__bridge id)kSecReturnRef:@YES};
    CFTypeRef result=NULL;
    status=SecItemCopyMatching((__bridge CFDictionaryRef)query,&result);
    if(status==errSecSuccess)
     {
        status=SecKeychainItemDelete((SecKeychainItemRef)result);
        CFRelease(result); // release core foundation class instance
     }
    if(status!=errSecSuccess && error!=NULL)
        *error=...; // failed operation
    

    【讨论】:

      【解决方案2】:

      只有管理员帐户才能写入系统钥匙串。

      将访问钥匙串的代码分解为使用XPC Helper Services 的 XPC 助手应用程序,以便助手可以以 root 权限运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-16
        • 2014-08-25
        • 2018-05-14
        • 2014-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多