X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/b04fe171f0375ecd5d8a24747ca1dff85720a0ca..6b200bc335dc93c5516ccb52f14bd896d8c7fad7:/Keychain/KCATableViewController.m?ds=inline diff --git a/Keychain/KCATableViewController.m b/Keychain/KCATableViewController.m deleted file mode 100644 index ded63880..00000000 --- a/Keychain/KCATableViewController.m +++ /dev/null @@ -1,312 +0,0 @@ -// -// KCATableViewController.m -// Security -// -// Created by John Hurley on 10/22/12. -// -// - -/* - Sample: - - (lldb) po allItems - (NSMutableDictionary *) $3 = 0x0855f200 <__NSCFArray 0x855f200>( - { - acct = "Keychain Sync Test Account"; - agrp = test; - cdat = "2012-10-04 21:59:46 +0000"; - gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; - mdat = "2012-10-08 21:02:39 +0000"; - pdmn = ak; - svce = "Keychain Sync Test Service"; - }, - { - acct = ""; - agrp = test; - cdat = "2012-10-22 21:08:14 +0000"; - gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; - mdat = "2012-10-22 21:08:14 +0000"; - pdmn = ak; - svce = ""; - }, - { - acct = iacct; - agrp = test; - cdat = "2012-10-22 21:08:29 +0000"; - gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; - mdat = "2012-10-22 21:08:29 +0000"; - pdmn = ak; - svce = iname; - }, - { - acct = bar; - agrp = test; - cdat = "2012-10-23 16:57:03 +0000"; - gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; - mdat = "2012-10-23 16:57:03 +0000"; - pdmn = ak; - svce = baz; - }, - { - acct = foo9; - agrp = test; - cdat = "2012-10-24 22:11:54 +0000"; - gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; - mdat = "2012-10-24 22:11:54 +0000"; - pdmn = ak; - svce = passfoo9; - } - ) -*/ - -#import "KCATableViewController.h" -#import "KeychainItemCell.h" -#import "MyKeychain.h" -#import "KCAItemDetailViewController.h" -#import -#import -#import -#import -#if TARGET_OS_EMBEDDED -#import -#endif - - -@interface KCATableViewController () -@end - -@implementation KCATableViewController - -- (void)viewDidLoad -{ - NSLog(@"KCATableViewController: viewDidLoad"); - [super viewDidLoad]; - - _lockTimer = [NSTimer timerWithTimeInterval:15.0 target:self selector:@selector(stopLockTimer:) userInfo:nil repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer: _lockTimer forMode: NSDefaultRunLoopMode]; - - notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, dispatch_get_main_queue(), - ^ (int token __unused) - { - NSLog(@"Received %s", kSecServerKeychainChangedNotification); - [self.tableView reloadData]; - }); -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender -{ - // Invoked immediately prior to initiating a segue. Return NO to prevent the segue from firing. The default implementation returns YES. - if (hasUnlockedRecently) - return YES; - if ([identifier isEqualToString:@"ItemDetail"]) - return [self askForPassword]; - return YES; -} - -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender -{ - if ([[segue identifier] isEqualToString:@"ItemDetail"]) - { - KCAItemDetailViewController *detailViewController = [segue destinationViewController]; - NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow]; - CFIndex row = [myIndexPath row]; - //TODO - horribly inefficient ! - NSArray *items = [self getItems]; - detailViewController.itemDetailModel = [items objectAtIndex: row]; - } -} - -// MARK: - Table view data source - -- (NSArray *)getItems -{ - // Each array element is a dictionary. If svce is present, compare - NSArray *allItems = (NSArray *)[[MyKeychain sharedInstance] fetchDictionaryAll]; - - return [allItems sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { - NSString *service1 = obj1[(__bridge id)(kSecAttrService)]; - NSString *service2 = obj2[(__bridge id)(kSecAttrService)]; - return [service1 compare:service2]; - }]; - - return allItems; -} - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ - // Return the number of sections. - return 1; //TODO -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - // Return the number of rows in the section. - NSInteger count = [[self getItems] count]; -// NSLog(@"numberOfRowsInSection: %d", count); - self.navigationController.navigationBar.topItem.title = [NSString stringWithFormat:@"All Items (%ld)", (long)count]; - -// NSLog(@"Items: %@", [self getItems]); - return count; -} - -- (BOOL)itemUpdatedRecently:(NSDictionary *)item -{ - const NSTimeInterval recent = 15.0; // within the last 15 seconds - NSDate *modDate = [item[(__bridge id)kSecAttrModificationDate] dateByAddingTimeInterval:recent]; - NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0]; - -// NSLog(@"Mod date: %@, now: %@", modDate, now); - return [modDate compare:now] == NSOrderedDescending; // i.e. modDate+15s > now -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - KeychainItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"kcTableCell" forIndexPath:(NSIndexPath *)indexPath]; - if (cell == nil) - { - NSLog(@"cellForRowAtIndexPath : cell was nil"); - cell = [[KeychainItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"kcTableCell"]; - } - - // Configure the cell... - - NSUInteger row = [indexPath row]; - - NSArray *items = [self getItems]; - NSDictionary *theItem = [items objectAtIndex: row]; - - NSString *svce = [theItem objectForKey: (__bridge id)(kSecAttrService)]; - NSString *acct = [theItem objectForKey: (__bridge id)(kSecAttrAccount)]; - - - if ([self itemUpdatedRecently:theItem]) - [cell startCellFlasher]; -/* else - cell.itemStatus.text = @""; -*/ - cell.itemName.text = (svce && [svce length]) ? svce : @"<>"; - cell.itemAccount.text = (acct && [acct length])? acct : @"<>"; - - [cell.itemAccount setTextColor:[UIColor grayColor]]; - - return cell; -} - -- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath -{ - OSStatus status; - NSUInteger row = [indexPath row]; - - NSArray *items = [self getItems]; - NSDictionary *item = [items objectAtIndex: row]; - NSMutableDictionary *query = [NSMutableDictionary dictionaryWithDictionary:item]; - - [query removeObjectForKey:(__bridge id)kSecValueData]; - [query removeObjectForKey:(__bridge id)kSecAttrCreationDate]; - [query removeObjectForKey:(__bridge id)kSecAttrModificationDate]; - [query removeObjectForKey:(__bridge id)kSecAttrGeneric]; - [query removeObjectForKey:@"tomb"]; - query[(__bridge id)(kSecClass)] = (__bridge id)(kSecClassGenericPassword); - -// NSLog(@"Item: %@", item); -// NSLog(@"Query: %@", query); - status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status) - NSLog(@"Error from SecItemDelete: %d", (int)status); - else - [self.tableView reloadData]; -} - -// MARK: Ask for PIN - -- (void)startLockTimer -{ - NSLog(@"startLockTimer"); - hasUnlockedRecently = true; - [_lockTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:60.0]]; -} - -- (void)stopLockTimer:(NSTimer *)timer -{ -// NSLog(@"stopLockTimer"); - // Call when we hit home button -// [_lockTimer invalidate]; - hasUnlockedRecently = false; -} - -- (BOOL)unlockDeviceWithPasscode:(NSString *)passcode -{ -#if TARGET_OS_EMBEDDED - int status = kMobileKeyBagError; - NSData *passcodeData = [passcode dataUsingEncoding:NSUTF8StringEncoding]; - if (MKBGetDeviceLockState(NULL) != kMobileKeyBagDisabled) - status = MKBUnlockDevice((__bridge CFDataRef)passcodeData, NULL); - else - status = kMobileKeyBagSuccess; - - // #define kMobileKeyBagDeviceLockedError (-2) - - if (status != kMobileKeyBagSuccess) - { - NSLog(@"Could not unlock device. Error: %d", status); - return NO; - } -#endif - [self startLockTimer]; - return YES; -} - -#define NO_AUTOCAPITALIZATION 0 -#define NO_AUTOCORRECTION 1 - -- (BOOL)askForPassword -{ - // Return YES if authenticated - CFUserNotificationRef dialog_alert = 0; - SInt32 err; - NSMutableDictionary *nd = [NSMutableDictionary dictionaryWithCapacity:0]; - CFOptionFlags flags = kCFUserNotificationCautionAlertLevel | kCFUserNotificationNoDefaultButtonFlag; - NSString *passcode; - - // Header and buttons - nd[(NSString *)kCFUserNotificationAlertHeaderKey] = @"Unlock"; - nd[(NSString *)kCFUserNotificationAlertMessageKey] = @"To view details"; - nd[(NSString *)kCFUserNotificationDefaultButtonTitleKey] = @"OK"; - nd[(NSString *)kCFUserNotificationAlternateButtonTitleKey] = @"Cancel"; - nd[(NSString *)kCFUserNotificationTextFieldTitlesKey] = @[@"Passcode"]; - nd[(__bridge NSString *)SBUserNotificationTextAutocapitalizationType] = @[ @(NO_AUTOCAPITALIZATION) ]; - nd[(__bridge NSString *)SBUserNotificationTextAutocapitalizationType] = @[ @(NO_AUTOCORRECTION) ]; - - flags = kCFUserNotificationPlainAlertLevel | CFUserNotificationSecureTextField(0); - - dialog_alert = CFUserNotificationCreate(NULL, 0, flags, &err, (__bridge CFMutableDictionaryRef)nd); - if (!dialog_alert) - return NO; - - CFUserNotificationReceiveResponse(dialog_alert, 0, &flags); - // the 2 lower bits of the response flags will give the button pressed - // 0 --> default - // 1 --> alternate - if (flags & kCFUserNotificationCancelResponse) { // user cancelled - if (dialog_alert) - CFRelease(dialog_alert); - return NO; - } - - // user clicked OK - passcode = CFBridgingRelease(CFUserNotificationGetResponseValue(dialog_alert, kCFUserNotificationTextFieldValuesKey, 0)); - // test using MKBUnlockDevice -// NSLog(@"PIN: %@", passcode); // TODO: REMOVE THIS!!!! - - if (dialog_alert) - CFRelease(dialog_alert); - return [self unlockDeviceWithPasscode:passcode]; -} - -@end