]> git.saurik.com Git - apple/security.git/blobdiff - Keychain/MyKeychain.m
Security-57740.51.3.tar.gz
[apple/security.git] / Keychain / MyKeychain.m
diff --git a/Keychain/MyKeychain.m b/Keychain/MyKeychain.m
deleted file mode 100644 (file)
index 347a2bc..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-//
-//  MyKeychain.m
-//  KCSync
-//
-//  Created by John Hurley on 10/3/12.
-//  Copyright (c) 2012 john. All rights reserved.
-//
-
-#import "MyKeychain.h"
-#import <Security/Security.h>
-#import <Security/SecItemPriv.h>
-#import <utilities/debugging.h>
-
-const NSString *kItemPasswordKey = @"ItemPasswordKey";
-const NSString *kItemAccountKey = @"ItemAccountKey";
-const NSString *kItemNameKey = @"ItemNameKey";
-
-#define KCSCOPE "mykeychain"
-
-// secdebug(KCSCOPE,
-
-@implementation MyKeychain
-
-static MyKeychain *sharedInstance = nil;
-
-+ (MyKeychain *) sharedInstance
-{
-    if (!sharedInstance)
-               sharedInstance = [[self alloc] init];
-
-    return sharedInstance;
-}
-
-// Translate status messages into return strings
-- (NSString *) fetchStatus : (OSStatus) status
-{
-    switch (status)
-    {
-    case 0:
-        return(@"Success!");
-    case errSecNotAvailable:
-        return(@"No trust results are available.!");
-    case errSecItemNotFound:
-        return(@"The item cannot be found.");
-    case errSecParam:
-        return(@"Parameter error.");
-    case errSecAllocate:
-        return(@"Memory allocation error. Failed to allocate memory.");
-    case errSecInteractionNotAllowed:
-        return(@"User interaction is not allowed.");
-    case errSecUnimplemented:
-        return(@"Function is not implemented");
-    case errSecDuplicateItem:
-        return(@"The item already exists.");
-    case errSecDecode:
-        return(@"Unable to decode the provided data.");
-
-    default:
-               return([NSString stringWithFormat:@"Function returned: %ld", (long)status]);
-        break;
-    }
-    return @"can't happen...";
-}
-
-#define        ACCOUNT @"Keychain Sync Test Account"
-#define        SERVICE @"Keychain Sync Test Service"
-#define PWKEY  @"Keychain Sync Test Password Data"
-
-// Return a base dictionary
-- (NSMutableDictionary *) baseDictionary
-{
-       NSMutableDictionary *md = [[NSMutableDictionary alloc] init];
-       
-       // Password identification keys
-       NSData *identifier = [PWKEY dataUsingEncoding:NSUTF8StringEncoding];
-       [md setObject:identifier forKey:(__bridge id)kSecAttrGeneric];
-       [md setObject:ACCOUNT forKey:(__bridge id)kSecAttrAccount];
-    [md setObject:SERVICE forKey:(__bridge id)kSecAttrService];
-       [md setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
-    [md setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable];
-    
-       return md;
-}
-
-// Return a keychain-style dictionary populated with the password
-- (NSMutableDictionary *) buildDictForPassword:(NSString *) password
-{
-       NSMutableDictionary *passwordDict = [self baseDictionary];
-       
-       // Add the password
-       NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
-    [passwordDict setObject:passwordData forKey:(__bridge id)kSecValueData]; // password 
-       
-       return passwordDict;
-}
-
-// Build a search query based
-- (NSMutableDictionary *) buildSearchQuery
-{
-       NSMutableDictionary *genericPasswordQuery = [self baseDictionary];
-       
-       // Add the search constraints
-       [genericPasswordQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
-       [genericPasswordQuery setObject:(__bridge id)kCFBooleanTrue
-                                                        forKey:(__bridge id)kSecReturnAttributes];
-       [genericPasswordQuery setObject:(__bridge id)kCFBooleanTrue
-                                                        forKey:(__bridge id)kSecReturnData];
-       
-       return genericPasswordQuery;
-}
-
-// retrieve data dictionary from the keychain
-- (NSMutableArray *) fetchDictionaryWithQuery:(NSMutableDictionary *)query
-{
-       NSMutableDictionary *genericPasswordQuery = query;
-       
-//  secerror("Query: %@", query);
-    CFTypeRef cfresult = nil;
-       OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, &cfresult);
-
-//  secerror( "FETCH: %s\n", [[self fetchStatus:status] UTF8String]);
-
-       if (status == errSecItemNotFound)
-        return NULL;
-    
-    if (CFGetTypeID(cfresult) == CFArrayGetTypeID())
-    {
-        NSMutableArray *result = [NSMutableArray arrayWithCapacity:0];
-        [result addObjectsFromArray:CFBridgingRelease(cfresult)];
-        return result;
-    }
-    
-    // If it is a single result, embed it in an array because callers expect it
-    if (CFGetTypeID(cfresult) == CFDictionaryGetTypeID())
-        return [NSMutableArray arrayWithObject:CFBridgingRelease(cfresult)];
-
-       return NULL;
-}      
-
-- (NSMutableArray *)fetchDictionary
-{
-       return [self fetchDictionaryWithQuery:[self buildSearchQuery]];
-}      
-
-// create a new keychain entry
-- (BOOL) createKeychainValue:(NSString *) password
-{
-       NSMutableDictionary *md = [self buildDictForPassword:password];
-       OSStatus status = SecItemAdd((__bridge CFDictionaryRef)md, NULL);
-
-    secerror( "CREATE: %s\n", [[self fetchStatus:status] UTF8String]);
-       
-       if (status == errSecSuccess) return YES; else return NO;
-}
-
-// remove a keychain entry
-- (void) clearKeychain
-{
-       NSMutableDictionary *genericPasswordQuery = [self baseDictionary];
-       
-       OSStatus status = SecItemDelete((__bridge CFDictionaryRef) genericPasswordQuery);
-    secerror( "DELETE: %s\n", [[self fetchStatus:status] UTF8String]);
-}
-
-// update a keychain entry
-- (BOOL) updateKeychainValue:(NSString *)password
-{
-       NSMutableDictionary *genericPasswordQuery = [self baseDictionary];
-       
-       NSMutableDictionary *attributesToUpdate = [[NSMutableDictionary alloc] init];
-       NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
-       [attributesToUpdate setObject:passwordData forKey:(__bridge id)kSecValueData];
-       
-       OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)genericPasswordQuery, (__bridge CFDictionaryRef)attributesToUpdate);
-    secerror( "UPDATE: %s\n", [[self fetchStatus:status] UTF8String]);
-       
-       if (status == 0) return YES; else return NO;
-}
-
-// fetch a keychain value
-- (NSString *) fetchPassword
-{
-    NSMutableArray *allItems = [self fetchDictionary];
-    if (!allItems)
-        return NULL;
-    
-    // This is used for a single item, so take first item in array
-    NSData *passData = [allItems[0] objectForKey:(__bridge id)kSecValueData];
-    if (passData)
-        return [[NSString alloc] initWithData:passData encoding:NSUTF8StringEncoding];
-       
-    return NULL;
-}
-
-- (void)setPassword: (NSString *) thePassword
-{
-       if (![self createKeychainValue:thePassword]) 
-               [self updateKeychainValue:thePassword];
-}
-
-- (void)setItem:(NSDictionary *)newItem
-{
-    OSStatus status = errSecSuccess;
-    NSMutableDictionary *passwordDict = [self baseDictionary];
-
-       // Add the password
-       NSData *passwordData = [[newItem objectForKey:kItemPasswordKey] dataUsingEncoding:NSUTF8StringEncoding];
-    [passwordDict setObject:passwordData forKey:(__bridge id)kSecValueData]; // password 
-
-    [passwordDict setObject:[newItem objectForKey:kItemAccountKey] forKey:(__bridge id)kSecAttrAccount];
-    [passwordDict setObject:[newItem objectForKey:kItemNameKey] forKey:(__bridge id)kSecAttrService];
-
-    // Try to add first; if error, then try to update
-       status = SecItemAdd((__bridge CFDictionaryRef)passwordDict, NULL);
-    secerror( "SecItemAdd result: %@ (%ld)", [self fetchStatus:status], (long)status);
-    NSLog(@"SecItemAdd result: %@ (%ld)", [self fetchStatus:status], (long)status);
-
-    if (status)
-    {
-        // Try update
-        // We only want to update the password data, so delete the other keys
-        
-//        NSArray *keysToRemove = [NSArray arrayWithObjects:kItemAccountKey, kItemNameKey, nil];
-        [passwordDict removeObjectsForKeys:@[(__bridge id)kSecValueData]];
-
-        NSDictionary *itemsToUpdate = @{ (__bridge id)kSecValueData : passwordData };
-//        [genericPasswordQuery setObject:[newItem objectForKey:kItemAccountKey] forKey:(__bridge id)kSecAttrAccount];
-//        [genericPasswordQuery setObject:[newItem objectForKey:kItemNameKey] forKey:(__bridge id)kSecAttrService];
-        status = SecItemUpdate((__bridge CFDictionaryRef)passwordDict, (__bridge CFDictionaryRef)(itemsToUpdate));
-        secerror( "SecItemUpdate result: %@ (%ld)", [self fetchStatus:status], (long)status);
-        NSLog(@"SecItemUpdate result: %@ (%ld)", [self fetchStatus:status], (long)status);
-    }
-}
-
-- (NSMutableArray *)fetchDictionaryAll
-{
-       NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
-       [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
-    [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable];
-
-       // Add the search constraints
-       [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
-       [query setObject:(__bridge id)kCFBooleanTrue
-                                                        forKey:(__bridge id)kSecReturnAttributes];
-       [query setObject:(__bridge id)kCFBooleanTrue
-                                                        forKey:(__bridge id)kSecReturnData];
-
-    NSMutableArray *genericItems = [self fetchDictionaryWithQuery:query];
-    
-    // Now look for internet items
-    [query setObject:(__bridge id)kSecClassInternetPassword forKey:(__bridge id)kSecClass];
-    NSMutableArray *internetItems = [self fetchDictionaryWithQuery:query];
-    if (internetItems)
-        [genericItems addObjectsFromArray:internetItems];
-       return genericItems;
-}      
-
-// MARK: ----- Full routines -----
-
-// Return a base dictionary
-- (NSMutableDictionary *) baseDictionaryFull:(NSString *)account service:(NSString *)service
-{
-       NSMutableDictionary *md = [[NSMutableDictionary alloc] init];
-       
-       // Password identification keys
-       NSData *identifier = [PWKEY dataUsingEncoding:NSUTF8StringEncoding];
-       [md setObject:identifier forKey:(__bridge id)kSecAttrGeneric];
-       [md setObject:account forKey:(__bridge id)kSecAttrAccount];
-    [md setObject:service forKey:(__bridge id)kSecAttrService];
-       [md setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
-    [md setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable];
-
-//     return [md autorelease];
-       return md;
-}
-
-- (BOOL) createKeychainValueFull:(NSString *)account service:(NSString *)service password:(NSString *)password
-{
-       NSMutableDictionary *md = [self buildDictForPasswordFull:account service:service password:password];
-       OSStatus status = SecItemAdd((__bridge CFDictionaryRef)md, NULL);
-    secerror( "CREATE: %s\n", [[self fetchStatus:status] UTF8String]);
-       
-       if (status == errSecSuccess) return YES; else return NO;
-}
-
-- (BOOL) updateKeychainValueFull:(NSString *)account service:(NSString *)service password:(NSString *)password
-{
-       NSMutableDictionary *genericPasswordQuery = [self baseDictionaryFull:account service:service];
-       
-       NSMutableDictionary *attributesToUpdate = [[NSMutableDictionary alloc] init];
-       NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
-       [attributesToUpdate setObject:passwordData forKey:(__bridge id)kSecValueData];
-       
-       OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)genericPasswordQuery, (__bridge CFDictionaryRef)attributesToUpdate);
-    secerror( "UPDATE: %s\n", [[self fetchStatus:status] UTF8String]);
-       
-       if (status == 0) return YES; else return NO;
-}
-
-- (void)setPasswordFull:(NSString *)account service:(NSString *)service password:(NSString *) thePassword
-{
-    secerror( "setPasswordFull account: %@, service: %@, password: %@", account, service, thePassword);
-       if (![self createKeychainValueFull:account service:service password:thePassword])
-               [self updateKeychainValueFull:account service:service password:thePassword];
-}
-
-// Return a keychain-style dictionary populated with the password
-- (NSMutableDictionary *) buildDictForPasswordFull:(NSString *)account service:(NSString *)service password:(NSString *)password
-{
-       NSMutableDictionary *passwordDict = [self baseDictionaryFull:account service:service];
-       
-       // Add the password
-       NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
-    [passwordDict setObject:passwordData forKey:(__bridge id)kSecValueData]; // password 
-       
-       return passwordDict;
-}
-
-- (void)clearAllKeychainItems
-{
-    CFIndex ix, top;
-    OSStatus status = errSecSuccess;
-    
-    NSArray *allItems = (NSArray *)[[MyKeychain sharedInstance] fetchDictionaryAll];
-    top = [allItems count];
-    secerror( "Deleting %ld items", (long)top);
-    
-    for (ix=0; ix<top && !status; ix++)
-    {
-        NSDictionary *item = [allItems objectAtIndex:ix];
-        NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
-        
-        NSData *identifier = [PWKEY dataUsingEncoding:NSUTF8StringEncoding];
-        [query setObject:identifier forKey:(__bridge id)kSecAttrGeneric];
-        [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
-        [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable];
-        
-        [query setObject:[item objectForKey:(__bridge id)(kSecAttrAccount)] forKey:(__bridge id)kSecAttrAccount];
-        [query setObject:[item objectForKey:(__bridge id)(kSecAttrService)] forKey:(__bridge id)kSecAttrService];
-        
-        status = SecItemDelete((__bridge CFDictionaryRef) query);
-        secerror( "DELETE: %s\n", [[self fetchStatus:status] UTF8String]);
-    }
-}
-
-
-@end