Objective c 钥匙链错误:如何使用Objective C在MAC应用程序的系统钥匙链中存储密码

Objective c 钥匙链错误:如何使用Objective C在MAC应用程序的系统钥匙链中存储密码,objective-c,macos,cocoa,vpn,keychain,Objective C,Macos,Cocoa,Vpn,Keychain,我正在尝试从我的MAC应用程序创建VPN连接,为此,我需要在系统密钥链中存储VPN共享机密和VPN密码 我试图从使用Keychain类,但返回一个错误,代码为-61,表示您没有写入权限 这是我的密码。如果我有什么地方出错,请纠正我 // A generic method to create Keychain Items holding Network service passwords + (int) createItem:(NSString*)label withService:(NSStri

我正在尝试从我的MAC应用程序创建VPN连接,为此,我需要在系统密钥链中存储VPN共享机密和VPN密码


我试图从使用Keychain类,但返回一个错误,代码为-61,表示您没有写入权限

这是我的密码。如果我有什么地方出错,请纠正我

// A generic method to create Keychain Items holding Network service passwords
+ (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);

  if(status == noErr) {
    NSLog(@"Successfully created Keychain Item");
  } else {
    //----------- ERROR ---------//
    // Here i got error with error code -61 Saying You do not have write access 
    //---------------------------//
    NSLog(@"Creating Keychain item failed: %@", SecCopyErrorMessageString(status, NULL));
    return 63;
  }
  return 0;
}

+ (NSArray*) trustedApps {
  NSMutableArray *apps = [NSMutableArray array];
  SecTrustedApplicationRef app;
  OSStatus err;

  for (int i = 0; i < (sizeof(trustedAppPaths) / sizeof(*trustedAppPaths)); i++) {
    err = SecTrustedApplicationCreateFromPath(trustedAppPaths[i], &app);
    if (err == errSecSuccess) {
      //NSLog(@"SecTrustedApplicationCreateFromPath succeeded: %@", SecCopyErrorMessageString(err, NULL));
    } else {
      NSLog(@"SecTrustedApplicationCreateFromPath failed: %@", SecCopyErrorMessageString(err, NULL));
    }

    [apps addObject:(__bridge id)app];
  }

  return apps;
}
//创建包含网络服务密码的密钥链项的通用方法
+(int)createItem:(NSString*)带有服务的标签:(NSString*)服务帐户:(NSString*)帐户说明:(NSString*)说明和密码:(NSString*)密码{
//此变量将保存各种操作状态响应
骨状态;
//将NSString转换为我们稍后需要的char*变量
const char*labeloutf8=[label UTF8String];
常量字符*serviceUTF8=[ServiceUTF8String];
const char*accountUTF8=[account UTF8String];
常量字符*DescriptionOutf8=[description UTF8String];
常量字符*密码UTF8=[密码UTF8String];
//这个变量很快就会保存系统钥匙链
SecKeychainRef keychain=NULL;
状态=SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem,&keychain);
如果(状态==errSecSuccess){
NSLog(@“成功打开系统钥匙链”);
}否则{
NSLog(@“无法获取系统密钥链:%@”,SecCopyErrorMessageString(状态,NULL));
返回60;
}
NSLog(“解锁系统钥匙链”);
状态=SecKeychainUnlock(keychain,0,NULL,FALSE);
如果(状态==errSecSuccess){
NSLog(@“成功解锁系统钥匙链”);
}否则{
NSLog(@“无法解锁系统密钥链:%@”,SecCopyErrorMessageString(状态,NULL));
返回61;
}
//这个变量将保存新的Keychain项
SecKeychainItemRef item=nil;
SecAccessRef-access=nil;
status=SecAccessCreate(CFSTR(“一些VPN测试”)、(u桥CFArrayRef)(self.trustedApps)和access);
如果(状态==noErr){
NSLog(@“创建的空密钥链访问对象”);
}否则{
NSLog(@“无法解锁系统密钥链:%@”,SecCopyErrorMessageString(状态,NULL));
返回62;
}
//将配置选项放在一起
SecKeychainAttribute属性属性[]={
{kSecLabelItemAttr,(int)strlen(labelatef8),(char*)labelatef8},
{kSecAccountItemAttr,(int)strlen(accountUTF8),(char*)accountUTF8},
{kSecServiceItemAttr,(int)strlen(serviceUTF8),(char*)serviceUTF8},
{ksecdescriptionontimattr,(int)strlen(descriptionontf8),(char*)descriptionontf8},
};
SecKeychainAttributeList attributes={sizeof(attrs)/sizeof(attrs[0]),attrs};
状态=SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass和属性,(int)strlen(passwordUTF8)、passwordUTF8、keychain、access和item);
如果(状态==noErr){
NSLog(@“已成功创建密钥链项”);
}否则{
//-----------错误---------//
//这里我得到了一个错误,错误代码是-61,表示您没有写权限
//---------------------------//
NSLog(@“创建密钥链项目失败:%@”,SecCopyErrorMessageString(状态,NULL));
返回63;
}
返回0;
}
+(NSArray*)受信任的应用程序{
NSMutableArray*应用程序=[NSMutableArray];
SecTrustedApplicationRef应用程序;
骨性关节炎;
对于(int i=0;i<(sizeof(trustedapppath)/sizeof(*trustedapppath));i++){
err=SecTrustedApplicationCreateFromPath(trustedapppath[i],&app);
if(err==errSecSuccess){
//NSLog(@“SecTrustedApplicationCreateFromPath成功:%@”,SecCopyErrorMessageString(err,NULL));
}否则{
NSLog(@“SecTrustedApplicationCreateFromPath失败:%@”,SecCopyErrorMessageString(err,NULL));
}
[应用程序添加对象:(_桥id)应用程序];
}
返回应用程序;
}

“您没有写入权限”似乎相当明确……您需要管理员(/root)权限来修改系统密钥链。我知道这种方式:“EditScheme”(通过“产品->EditScheme…->运行->信息->调试过程->根目录”菜单)。但是,如果我想在没有任何根访问的情况下执行此操作,那么我该如何执行此操作?因为我不能告诉用户去编辑方案,然后运行应用程序。你能在这方面指导我吗?@MalavSoni你找到解决办法了吗?你能给我指引一下吗?我因为这个问题被卡住了。如果你想储存密码。您必须使用from helper tool调用上述代码,因为我们需要管理员权限才能在keychain中存储密码,并且helper tool正在以管理员权限运行。如果我们使用以管理员权限运行的helper tool,是否有机会通过App store审批流程?