Revision: 27921
http://sourceforge.net/p/bibdesk/svn/27921
Author: hofman
Date: 2022-09-22 17:03:06 +0000 (Thu, 22 Sep 2022)
Log Message:
-----------
replace old keychain functions by core foundation based functions
Modified Paths:
--------------
trunk/bibdesk/BDSKPasswordController.m
Modified: trunk/bibdesk/BDSKPasswordController.m
===================================================================
--- trunk/bibdesk/BDSKPasswordController.m 2022-09-21 09:11:45 UTC (rev
27920)
+++ trunk/bibdesk/BDSKPasswordController.m 2022-09-22 17:03:06 UTC (rev
27921)
@@ -47,111 +47,95 @@
@synthesize passwordField, statusField;
static inline void logError(NSString *action, OSStatus err) {
- if (err != errSecItemNotFound && err != errSecUserCanceled)
+ if (err != noErr && err != errSecItemNotFound && err != errSecUserCanceled)
NSLog(@"Error %d occurred %@ password: %@", (int)err, action,
[(id)SecCopyErrorMessageString(err, NULL) autorelease]);
}
-static inline SecKeychainAttributeList makeAttributeList(const char
*serviceCString, const char *accountCString, const char *nameCString) {
- // default is to use current user's username
- if (accountCString == NULL)
- accountCString = [NSUserName() UTF8String];
- SecKeychainAttribute attrs[] = {
- {kSecServiceItemAttr, (UInt32)strlen(serviceCString), (void
*)serviceCString},
- {kSecAccountItemAttr, (UInt32)strlen(accountCString), (void
*)accountCString},
- {kSecLabelItemAttr, (UInt32)strlen(nameCString), (void *)nameCString}};
- SecKeychainAttributeList attributes = {3, attrs};
- return attributes;
-}
-
+ (NSString *)passwordForKeychainService:(NSString *)service account:(NSString
*)account name:(NSString *)name {
// use the service name to get password from keychain and hash it with
sha1 for comparison purposes
+ NSString *passwordString = nil;
+ NSData *passwordData = nil;
OSStatus err;
+ NSMutableDictionary *query = [NSMutableDictionary dictionary];
- const char *serviceCString = [service UTF8String];
- const char *accountCString = [account UTF8String];
- const char *nameCString = [name UTF8String];
- void *password = NULL;
- UInt32 passwordLength = 0;
- NSString *passwordString = nil;
+ [query setObject:(NSString *)kSecClassGenericPassword forKey:(NSString
*)kSecClass];
+ [query setObject:(NSString *)kSecMatchLimitOne forKey:(NSString
*)kSecMatchLimit];
+ [query setObject:[NSNumber numberWithBool:YES] forKey:(NSString
*)kSecReturnData];
+ [query setObject:service forKey:(NSString *)kSecAttrService];
+ if (account)
+ [query setObject:account forKey:(NSString *)kSecAttrAccount];
// see if the password exists in the keychain
- err = SecKeychainFindGenericPassword(NULL, strlen(serviceCString),
serviceCString, account ? strlen(accountCString) : 0, accountCString,
&passwordLength, &password, NULL);
+ err = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef
*)&passwordData);
if (err == errSecItemNotFound && name) {
// see if an item in the old format exists
- SecKeychainItemRef itemRef = nil;
- err = SecKeychainFindGenericPassword(NULL, strlen(nameCString),
nameCString, 0, NULL, &passwordLength, &password, &itemRef);
+ [query setObject:name forKey:(NSString *)kSecAttrService];
+ [query removeObjectForKey:(NSString *)kSecAttrAccount];
+ err = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef
*)&passwordData);
if (err == noErr) {
// item in old format exists, update to new format
- SecKeychainAttributeList attributes =
makeAttributeList(serviceCString, accountCString, nameCString);
- SecKeychainItemModifyAttributesAndData(itemRef, &attributes, 0,
NULL);
- CFRelease(itemRef);
+ NSDictionary *attributes = [NSDictionary
dictionaryWithObjectsAndKeys:service, (NSString *)kSecAttrService, account ?:
[NSUserName() dataUsingEncoding:NSUTF8StringEncoding], (NSString
*)kSecAttrAccount, name, (NSString *)kSecAttrLabel, nil];
+ [query removeObjectForKey:(NSString *)kSecReturnData];
+ SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attributes);
}
}
+
if (err == noErr) {
- passwordString = [[[NSString alloc] initWithBytes:password
length:passwordLength encoding:NSUTF8StringEncoding] autorelease];
- SecKeychainItemFreeContent(NULL, password);
+ passwordString = [[[NSString alloc] initWithData:passwordData
encoding:NSUTF8StringEncoding] autorelease];
+ [passwordData release];
} else {
logError(@"getting", err);
}
+
return passwordString;
}
+ (BOOL)addOrModifyPassword:(NSString *)password forKeychainService:(NSString
*)service account:(NSString *)account name:(NSString *)name {
+ NSString *passwordString = nil;
+ NSData *passwordData = nil;
+ OSStatus err;
+ NSMutableDictionary *query = [NSMutableDictionary dictionary];
+ NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
- NSParameterAssert(service != nil);
- NSParameterAssert(password != nil);
- const char *serviceCString = [service UTF8String];
- const char *accountCString = [account UTF8String];
+ // first try to update an existing item
+ [query setObject:(NSString *)kSecClassGenericPassword forKey:(NSString
*)kSecClass];
+ [query setObject:(NSString *)kSecMatchLimitOne forKey:(NSString
*)kSecMatchLimit];
+ [query setObject:service forKey:(NSString *)kSecAttrService];
+ if (account)
+ [query setObject:account forKey:(NSString *)kSecAttrAccount];
- OSStatus err;
- SecKeychainItemRef itemRef = NULL;
- const void *passwordData = [password UTF8String];
- const void *oldPasswordData = NULL;
- UInt32 passwordLength = 0;
+ [attributes setObject:[password dataUsingEncoding:NSUTF8StringEncoding]
forKey:(NSString *)kSecValueData];
- // first see if the password exists in the keychain
- err = SecKeychainFindGenericPassword(NULL, strlen(serviceCString),
serviceCString, account ? strlen(accountCString) : 0, accountCString,
&passwordLength, (void **)&oldPasswordData, &itemRef);
+ err = SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attributes);
- if (err == noErr) {
- // password was on keychain, so flush the buffer and then modify the
keychain if necessary
- if (passwordLength != strlen(passwordData) || strncmp(passwordData,
oldPasswordData, passwordLength) != 0) {
- err = SecKeychainItemModifyAttributesAndData(itemRef, NULL,
strlen(passwordData), passwordData);
- logError(@"modifying", err);
- }
- SecKeychainItemFreeContent(NULL, (void *)oldPasswordData);
- CFRelease(itemRef);
- } else if (err == errSecItemNotFound) {
- // password not on keychain
+ logError(@"updating", err);
+
+ if (err == errSecItemNotFound) {
+ [attributes setObject:service forKey:(NSString *)kSecAttrService];
+ [attributes setObject:account ?: [NSUserName()
dataUsingEncoding:NSUTF8StringEncoding] forKey:(NSString *)kSecAttrAccount];
+
if (name) {
- const char *nameCString = [name UTF8String];
-
// see if an item in the old format exists
- err = SecKeychainFindGenericPassword(NULL, strlen(nameCString),
nameCString, 0, NULL, NULL, NULL, &itemRef);
+ [attributes setObject:name forKey:(NSString *)kSecAttrLabel];
- SecKeychainAttributeList attributes =
makeAttributeList(serviceCString, accountCString, nameCString);
- if (err == noErr) {
- // password in old format was on keychain, modify the keychain
to the new format
- err = SecKeychainItemModifyAttributesAndData(itemRef,
&attributes, strlen(passwordData), passwordData);
- logError(@"modifying", err);
- CFRelease(itemRef);
- } else if (err == errSecItemNotFound) {
- // password not on keychain, so add it
- err =
SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes,
strlen(passwordData), passwordData, NULL, NULL, NULL);
- logError(@"adding", err);
- } else {
- logError(@"getting", err);
- }
- } else {
- // simple password not on keychain, so add it
- // default is to use current user's username
- if (account == nil)
- accountCString = [NSUserName() UTF8String];
- err = SecKeychainAddGenericPassword(NULL, strlen(serviceCString),
serviceCString, strlen(accountCString), accountCString, strlen(passwordData),
passwordData, NULL);
+ [query setObject:name forKey:(NSString *)kSecAttrService];
+ [query removeObjectForKey:(NSString *)kSecAttrAccount];
+
+ err = SecItemUpdate((CFDictionaryRef)query,
(CFDictionaryRef)attributes);
+
+ logError(@"updating", err);
+ }
+
+ if (err == errSecItemNotFound) {
+ // password not yet on keychain, so add it
+ [attributes setObject:(NSString *)kSecClassGenericPassword
forKey:(NSString *)kSecClass];
+
+ err = SecItemAdd((CFDictionaryRef)attributes, NULL);
+
logError(@"adding", err);
}
- } else {
- logError(@"getting", err);
}
+
return (err == noErr);
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit