diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPKeychain.h | 9 | ||||
-rw-r--r-- | Source/SPKeychain.m | 93 |
2 files changed, 33 insertions, 69 deletions
diff --git a/Source/SPKeychain.h b/Source/SPKeychain.h index 7c82cf97..4fa986c9 100644 --- a/Source/SPKeychain.h +++ b/Source/SPKeychain.h @@ -40,9 +40,10 @@ - (BOOL)passwordExistsForName:(NSString *)name account:(NSString *)account; - (void)updateItemWithName:(NSString *)name account:(NSString *)account toPassword:(NSString *)password; - (void)updateItemWithName:(NSString *)name account:(NSString *)account toName:(NSString *)newName account:(NSString *)newAccount password:(NSString *)password; -- (NSString *)nameForFavoriteName:(NSString *)theName id:(NSString *)theID; -- (NSString *)accountForUser:(NSString *)theUser host:(NSString *)theHost database:(NSString *)theDatabase; -- (NSString *)nameForSSHForFavoriteName:(NSString *)theName id:(NSString *)theID; -- (NSString *)accountForSSHUser:(NSString *)theSSHUser sshHost:(NSString *)theSSHHost; + +- (NSString *)nameForFavoriteName:(NSString *)favoriteName id:(NSString *)favoriteId; +- (NSString *)accountForUser:(NSString *)user host:(NSString *)host database:(NSString *)database; +- (NSString *)nameForSSHForFavoriteName:(NSString *)favoriteName id:(NSString *)favoriteId; +- (NSString *)accountForSSHUser:(NSString *)SSHUser sshHost:(NSString *)SSHHost; @end diff --git a/Source/SPKeychain.m b/Source/SPKeychain.m index 03ba464f..c7b3731d 100644 --- a/Source/SPKeychain.m +++ b/Source/SPKeychain.m @@ -59,9 +59,7 @@ SecKeychainAttributeList attList; // If a nil password was supplied, do nothing. - if (!password) { - return; - } + if (!password) return; // Check supplied variables and replaces nils with empty strings if (!name) name = @""; @@ -71,13 +69,16 @@ // Check if password already exists before adding if (![self passwordExistsForName:name account:account]) { - // Create a trusted access list with two items - ourselves and the SSH pass app. + // Create a trusted access list with two items - ourselves and the SSH pass app NSString *helperPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"SequelProTunnelAssistant"]; + if ((SecTrustedApplicationCreateFromPath(NULL, &sequelProRef) == noErr) && (SecTrustedApplicationCreateFromPath([helperPath UTF8String], &sequelProHelperRef) == noErr)) { NSArray *trustedApps = [NSArray arrayWithObjects:(id)sequelProRef, (id)sequelProHelperRef, nil]; + status = SecAccessCreate((CFStringRef)name, (CFArrayRef)trustedApps, &passwordAccessRef); + if (status != noErr) { NSLog(@"Error (%i) while trying to create access list for name: %@ account: %@", (int)status, name, account); passwordAccessRef = NULL; @@ -152,6 +153,7 @@ ); if (status == noErr) { + // Create a \0 terminated cString out of passwordData char passwordBuf[passwordLength + 1]; strncpy(passwordBuf, passwordData, (size_t)passwordLength); @@ -211,37 +213,20 @@ */ - (BOOL)passwordExistsForName:(NSString *)name account:(NSString *)account { - SecKeychainItemRef item; - SecKeychainSearchRef search = NULL; - NSInteger numberOfItemsFound = 0; - SecKeychainAttributeList list; - SecKeychainAttribute attributes[2]; + NSMutableDictionary *query = [NSMutableDictionary dictionary]; - // Check supplied variables and replaces nils with empty strings - if (!name) name = @""; - if (!account) account = @""; + [query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; + [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; + [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; - attributes[0].tag = kSecAccountItemAttr; - attributes[0].data = (void *)[account UTF8String]; // Account name - attributes[0].length = (UInt32)strlen([account UTF8String]); // Length of account name (bytes) - - attributes[1].tag = kSecServiceItemAttr; - attributes[1].data = (void *)[name UTF8String]; // Service name - attributes[1].length = (UInt32)strlen([name UTF8String]); // Length of service name (bytes) - - list.count = 2; - list.attr = attributes; - - if (SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &list, &search) == noErr) { - while (SecKeychainSearchCopyNext(search, &item) == noErr) { - CFRelease(item); - numberOfItemsFound++; - } - } - - if (search) CFRelease(search); - - return (numberOfItemsFound > 0); + [query setObject:account forKey:(id)kSecAttrAccount]; + [query setObject:name forKey:(id)kSecAttrService]; + + CFDictionaryRef result = NULL; + + BOOL found = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&result) == errSecSuccess; + + return found; } /** @@ -275,6 +260,7 @@ if (status != noErr) { NSLog(@"Error (%i) while trying to find keychain item to edit for name: %@ account: %@", (int)status, name, account); + SPBeginAlertSheet(NSLocalizedString(@"Error retrieving Keychain item to edit", @"error finding keychain item to edit message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil, @@ -301,10 +287,12 @@ // this indicates an issue when previously altering keychain items; delete the old item and try again. if ((int)status == -25299) { [self deletePasswordForName:newName account:newAccount]; + return [self updateItemWithName:name account:account toName:newName account:newAccount password:password]; } NSLog(@"Error (%i) while updating keychain item for name: %@ account: %@", (int)status, name, account); + SPBeginAlertSheet(NSLocalizedString(@"Error updating Keychain item", @"error updating keychain item message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil, @@ -315,46 +303,27 @@ /** * Retrieve the keychain item name for a supplied name and id. */ -- (NSString *)nameForFavoriteName:(NSString *)theName id:(NSString *)theID +- (NSString *)nameForFavoriteName:(NSString *)favoriteName id:(NSString *)favoriteId { - NSString *keychainItemName; - // Look up the keychain name using long longs to support 64-bit > 32-bit keychain usage - keychainItemName = [NSString stringWithFormat:@"Sequel Pro : %@ (%lld)", - theName?theName:@"", - [theID longLongValue]]; - - return keychainItemName; + return [NSString stringWithFormat:@"Sequel Pro : %@ (%lld)", favoriteName ? favoriteName: @"", [favoriteId longLongValue]]; } /** * Retrieve the keychain item account for a supplied user, host, and database - which can be nil. */ -- (NSString *)accountForUser:(NSString *)theUser host:(NSString *)theHost database:(NSString *)theDatabase +- (NSString *)accountForUser:(NSString *)user host:(NSString *)host database:(NSString *)database { - NSString *keychainItemAccount; - - keychainItemAccount = [NSString stringWithFormat:@"%@@%@/%@", - theUser?theUser:@"", - theHost?theHost:@"", - theDatabase?theDatabase:@""]; - - return keychainItemAccount; + return [NSString stringWithFormat:@"%@@%@/%@", user ? user : @"", host ? host : @"", database ? database : @""]; } /** * Retrieve the keychain SSH item name for a supplied name and id. */ -- (NSString *)nameForSSHForFavoriteName:(NSString *)theName id:(NSString *)theID +- (NSString *)nameForSSHForFavoriteName:(NSString *)favoriteName id:(NSString *)favoriteId { - NSString *sshKeychainItemName; - // Look up the keychain name using long longs to support 64-bit > 32-bit keychain usage - sshKeychainItemName = [NSString stringWithFormat:@"Sequel Pro SSHTunnel : %@ (%lld)", - theName?theName:@"", - [theID longLongValue]]; - - return sshKeychainItemName; + return [NSString stringWithFormat:@"Sequel Pro SSHTunnel : %@ (%lld)", favoriteName ? favoriteName: @"", [favoriteId longLongValue]]; } /** @@ -362,13 +331,7 @@ */ - (NSString *)accountForSSHUser:(NSString *)theSSHUser sshHost:(NSString *)theSSHHost { - NSString *sshKeychainItemAccount; - - sshKeychainItemAccount = [NSString stringWithFormat:@"%@@%@", - theSSHUser?theSSHUser:@"", - theSSHHost?theSSHHost:@""]; - - return sshKeychainItemAccount; + return [NSString stringWithFormat:@"%@@%@", theSSHUser ? theSSHUser : @"", theSSHHost ? theSSHHost : @""]; } @end |