From 27c5d7f8c055208d1529bd4824a3b5398a4135f5 Mon Sep 17 00:00:00 2001 From: Miguel Alatzar Date: Fri, 18 Jun 2021 15:42:14 -0700 Subject: [PATCH 1/2] Add getAllInternetPasswordServers method for iOS --- RNKeychainManager/RNKeychainManager.m | 38 +++++++++++++++++++++++++++ index.js | 15 +++++++++++ 2 files changed, 53 insertions(+) diff --git a/RNKeychainManager/RNKeychainManager.m b/RNKeychainManager/RNKeychainManager.m index 900e4f00..b4abd490 100644 --- a/RNKeychainManager/RNKeychainManager.m +++ b/RNKeychainManager/RNKeychainManager.m @@ -301,6 +301,34 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server return services; } +-(NSArray*)getAllServersForInternetPasswords +{ + NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys: + (__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnAttributes, + (__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit, + nil]; + NSMutableArray *servers = [NSMutableArray new]; + + [query setObject:(__bridge id)kSecClassInternetPassword forKey:(__bridge id)kSecClass]; + NSArray *result = nil; + CFTypeRef resultRef = NULL; + OSStatus osStatus = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&resultRef); + if (osStatus != noErr && osStatus != errSecItemNotFound) { + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:osStatus userInfo:nil]; + @throw error; + } else if (osStatus != errSecItemNotFound) { + result = (__bridge NSArray*)(resultRef); + if (result != NULL) { + for (id entry in result) { + NSString *server = [entry objectForKey:(__bridge NSString *)kSecAttrServer]; + [servers addObject:server]; + } + } + } + + return servers; +} + #pragma mark - RNKeychain #if TARGET_OS_IOS @@ -594,4 +622,14 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server } } +RCT_EXPORT_METHOD(getAllInternetPasswordServers:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + @try { + NSArray *servers = [self getAllServersForInternetPasswords]; + return resolve(servers); + } @catch (NSError *nsError) { + return rejectWithError(reject, nsError); + } +} + @end diff --git a/index.js b/index.js index b73cfb25..7ecbe01a 100644 --- a/index.js +++ b/index.js @@ -348,6 +348,21 @@ export function canImplyAuthentication(options?: Options): Promise { return RNKeychainManager.canCheckAuthentication(options); } +/** + * Gets all `kSecAttrServer` values used with internet credentials for iOS. + * @return {Promise} Resolves to an array of strings + */ + export async function getAllInternetPasswordServers(): Promise { + if (Platform.OS !== 'ios') { + return Promise.reject( + new Error( + `getAllInternetPasswordServers() is not supported on ${Platform.OS}` + ) + ); + } + return RNKeychainManager.getAllInternetPasswordServers(); +} + //* ANDROID ONLY */ /** From c966aeee7f4fdf6ca1350f6df8ff9bdb3b28832b Mon Sep 17 00:00:00 2001 From: Miguel Alatzar Date: Fri, 25 Jun 2021 13:17:43 -0700 Subject: [PATCH 2/2] fix: handle NSMutableData --- RNKeychainManager/RNKeychainManager.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/RNKeychainManager/RNKeychainManager.m b/RNKeychainManager/RNKeychainManager.m index b4abd490..ad3fabcf 100644 --- a/RNKeychainManager/RNKeychainManager.m +++ b/RNKeychainManager/RNKeychainManager.m @@ -320,8 +320,11 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server result = (__bridge NSArray*)(resultRef); if (result != NULL) { for (id entry in result) { - NSString *server = [entry objectForKey:(__bridge NSString *)kSecAttrServer]; - [servers addObject:server]; + NSMutableData *serverData = [entry objectForKey:(__bridge NSString *)kSecAttrServer]; + if (serverData != NULL) { + NSString *server = [[NSString alloc] initWithData:serverData encoding:NSUTF8StringEncoding]; + [servers addObject:server]; + } } } }