views:

38

answers:

0

I'm writing a preferences panel and I need to either update or store a password in the System.keychain for others to find. Here's the code I have so far:

Boolean addOrUpdateKey(NSString *service, NSString *key)
{
  OSStatus retVal;
  SecKeychainRef systemKeychainRef;
  SecKeychainItemRef kcItem;
  UInt32 pwSize = 0;
  char *password = NULL;
  AuthorizationRef authRef;
  AuthorizationItem right = { "system.keychain.modify", 0, NULL, 0 };
  AuthorizationRights rightSet = { 1, &right };


  retVal = AuthorizationCreate(&rightSet, kAuthorizationEmptyEnvironment, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, &authRef);
  if (retVal != errSecSuccess) {
    NSLog(@"Failed to get right to modify system keychain %@", SecCopyErrorMessageString(retVal, NULL));
    return FALSE;
  }
  SecKeychainSetUserInteractionAllowed(TRUE);
  retVal = SecKeychainOpen("/Library/Keychains/System.keychain", &systemKeychainRef);
  if (retVal != errSecSuccess) {
    NSLog(@"Failed to open System keychain %@", SecCopyErrorMessageString(retVal, NULL));
    return FALSE;
  }
  retVal = SecKeychainUnlock(systemKeychainRef, 0, NULL, FALSE);
  retVal = SecKeychainFindGenericPassword(NULL, 
                                          [service length], 
                                          [service cString], 
                                          0, 
                                          NULL, 
                                          &pwSize, 
                                          (void**)&password, 
                                          &kcItem);
  if (retVal == errSecItemNotFound) {
    retVal = SecKeychainAddGenericPassword(systemKeychainRef, 
                                           [service length], 
                                           [service cString], 
                                           0, 
                                           NULL, 
                                           [key length], 
                                           [key cString], 
                                            &kcItem);
    if (retVal != errSecSuccess) {
      NSLog(@"Failed to add new key to keychain %@", SecCopyErrorMessageString(retVal, NULL));
      return FALSE;
    }
  }

  retVal = SecKeychainItemModifyAttributesAndData(kcItem, NULL, [key length], [key cString]);
  if (retVal != errSecSuccess) {
    NSLog(@"Failed to update password for key %@", SecCopyErrorMessageString(retVal, NULL));
    return FALSE;
  }

  return TRUE;
}

With or without the Authorization routines and whether the key exists or not the call to SecKeychainItemModifyAttributesAndData always returns -61 (write permission error). The question is, how do I get the correct permissions to write to the system keychain?