如何向OSX系统钥匙串写入信息?

4
作为在OSX上使用Cocoa编程创建VPN连接程序的一部分,我需要将PPP密码存储在系统钥匙串中。当我尝试使用钥匙串API执行此操作时,调用SecKeychainAddGenericPassword后出现以下错误:
“无法写入文件。可能已使用不足的访问权限打开。”
这是我正在使用的代码:
- (void)storePasswordInKeychain
{
    SecKeychainRef keychain = nil;
    err = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &keychain);
    if (err != errSecSuccess) {
        NSLog(@"Error getting system keychain: %@", SecCopyErrorMessageString(err, NULL));
    } else {
        NSLog(@"Succeeded opening keychain: %@", SecCopyErrorMessageString(err, NULL));
        SecKeychainItemRef item = nil;        
        err = SecKeychainUnlock(keychain, 0, NULL, FALSE);
        NSLog(@"Keychain unlocked: %@", SecCopyErrorMessageString(err, NULL));

        err = SecKeychainAddGenericPassword (keychain, 
                                         3, "VPN", 
                                         8, "username",
                                         8, "password",
                                         &item);
        NSLog(@"Result of storing password: %@", SecCopyErrorMessageString(err, NULL));
    }
}

这个讨论如何写入System.keychain?似乎表明我需要在程序内部调用/usr/bin/security命令行,但是Keychain API的目的似乎是避免那种破解。

有人能指导我在System keychain中存储新密码的正确方法吗?谢谢。

4个回答

1

确实需要将凭据放入系统钥匙串而不是用户钥匙串。您不需要使用SMJobBless来完成此操作。

在解锁钥匙串后,可以像这样创建SecAccessRef:

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

然后构建您的钥匙链条目。
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);

在Github上有一个项目可以实现这个功能。请查看VPNKeychain.m文件以查看整个实现过程。https://github.com/halo/macosvpn

先生,我正在使用macosvpn项目,代码成功运行并创建了新的网络,但它没有显示我传递的数据,例如服务器地址、帐户名。 - Sawan Cool
我已经成功在Mac应用程序中安装了helperTool,并使用https://github.com/halo/macosvpn代码,但是当我将Debug Process设置为(Me)时,源代码仍然没有将密码存储在系统钥匙串中。有人可以帮助我吗? - Sawan Cool

1
当您向系统钥匙串写入内容时,需要具备root权限。对于xcode调试,您只需通过“编辑方案”(从菜单中的“产品-> EditScheme ... -> Run-> Info-> Debug process as-> root”)即可。好吧,我的xcode版本是6.1,不同的xcode版本可能存在一些差异。或者只需通过sudo命令行使用您的应用程序。希望这可以帮助到您。

1
你的回答很有帮助,但问题是当我运行“application.App”时,密码没有存储在系统钥匙串中。请指导我,我将非常感激。 - Sawan Cool

0

VPN的用户名和密码当然属于特定用户,您真的是指系统钥匙串而不是用户钥匙串吗?

尝试删除对SecKeychainCopyDomainDefaultSecKeychainUnlock的调用,并将NULL作为第一个参数传递给SecKeychainAddGenericPassword - 这将把该项目添加到默认密钥串。


不幸的是,VPN密码属于系统而非用户钥匙串。如果您通过系统偏好设置手动创建新的PPTP VPN连接并打开钥匙串,您会发现VPN密码被存储在系统钥匙串中。 - Kevin
我目前没有想法,而且我使用的机器不适合测试,但是它是否需要在系统钥匙串中?也就是说,如果将其添加到用户钥匙串中,它会被忽略吗?如果是这样,也许您将不得不让用户始终输入它。 - CRD
为了测试这个,我在网络偏好设置中手动创建了一个新的 VPN 连接。我成功地连接上了它。然后我打开了钥匙串访问并将存储密码的钥匙串项目从系统钥匙串移动到登录钥匙串。当我尝试重新连接时,它提示我输入 VPN 密码。所以它确实需要放在系统钥匙串中。 - Kevin
我已经成功在 Mac 应用程序中安装了 helperTool,并使用 https://github.com/halo/macosvpn 代码,但当我将 Debug 进程设置为 (Me) 时,源代码仍未将密码存储在系统钥匙串中。有人能帮我吗? - Sawan Cool

0

苹果目前推荐使用服务管理API来获取特权访问。他们有一个示例项目:SMJobBless。如果你的目标是Mac App Store,我不确定沙盒是否允许系统钥匙串访问。

你提到的另一个问题似乎推荐使用授权服务API,而服务管理在10.6中替代了它,并明确说明在沙盒中根本不允许使用。


我已经成功在Mac应用程序中安装了helperTool,并使用https://github.com/halo/macosvpn代码,但当我将Debug Process设置为(Me)时,源代码仍未将密码存储在系统钥匙串中。有人能帮帮我吗? - Sawan Cool

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接