KDSecItems.m
1 /* 2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25 #import "KDSecItems.h" 26 #include <Security/Security.h> 27 #include <Security/SecItemPriv.h> 28 29 30 NSString *kKDSecItemsUpdated = @"KDSecItemsUpdated"; 31 32 @interface KDSecItems () 33 @property NSMutableArray *items; 34 @end 35 36 @implementation KDSecItems 37 38 -(NSInteger)numberOfRowsInTableView:(NSTableView*)t 39 { 40 return [self.items count]; 41 } 42 43 +(NSString*)nameOfItem:(NSDictionary*)item 44 { 45 id name = item[(id)kSecAttrService]; 46 if (name) { 47 return name; 48 } 49 50 NSString *path = item[(id)kSecAttrPath]; 51 if (!path) { 52 path = @"/"; 53 } 54 NSString *port = item[(id)kSecAttrPort]; 55 if ([@"0" isEqualToString:port] || [@0 isEqual:port]) { 56 port = @""; 57 } else { 58 port = [NSString stringWithFormat:@":%@", port]; 59 } 60 61 return [NSString stringWithFormat:@"%@://%@%@%@", item[(id)kSecAttrProtocol], item[(id)kSecAttrServer], port, path]; 62 } 63 64 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex 65 { 66 NSString *identifier = [aTableColumn identifier]; 67 68 if ([@"account" isEqualToString:identifier]) { 69 return self.items[rowIndex][(id)kSecAttrAccount]; 70 } 71 if ([@"name" isEqualToString:identifier]) { 72 return [KDSecItems nameOfItem:self.items[rowIndex]]; 73 } 74 75 return [NSString stringWithFormat:@"*** c=%@ r%ld", [aTableColumn identifier], (long)rowIndex]; 76 } 77 78 -(NSArray*)fetchItemsMatching:(NSDictionary *)query 79 { 80 CFTypeRef raw_items = NULL; 81 OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)(query), &raw_items); 82 if (result) { 83 // XXX: UI 84 NSLog(@"Error result %d - query: %@", result, query); 85 return nil; 86 } 87 if (CFArrayGetTypeID() == CFGetTypeID(raw_items)) { 88 return (__bridge NSArray*)raw_items; 89 } 90 91 NSLog(@"Unexpected result type from copyMatching: %@ (query=%@)", raw_items, query); 92 CFRelease(raw_items); 93 94 return nil; 95 } 96 97 -(void)loadItems 98 { 99 NSDictionary *query_genp = @{(id)kSecClass: (id)kSecClassGenericPassword, 100 (__bridge id)kSecAttrSynchronizable: @1, 101 (id)kSecMatchLimit: (id)kSecMatchLimitAll, 102 (id)kSecReturnAttributes: (id)kCFBooleanTrue}; 103 NSDictionary *query_inet = @{(id)kSecClass: (id)kSecClassInternetPassword, 104 (__bridge id)kSecAttrSynchronizable: @1, 105 (id)kSecMatchLimit: (id)kSecMatchLimitAll, 106 (id)kSecReturnAttributes: (id)kCFBooleanTrue}; 107 NSArray *nextItems = [[self fetchItemsMatching:query_genp] arrayByAddingObjectsFromArray:[self fetchItemsMatching:query_inet]]; 108 self.items = [[nextItems sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { 109 NSDictionary *da = a, *db = b; 110 return [da[(id)kSecAttrService] caseInsensitiveCompare:db[(id)kSecAttrService]]; 111 }] mutableCopy]; 112 113 dispatch_async(dispatch_get_main_queue(), ^{ 114 [[NSNotificationCenter defaultCenter] postNotificationName:kKDSecItemsUpdated object:self]; 115 }); 116 } 117 118 -(id)init 119 { 120 [self loadItems]; 121 return self; 122 } 123 124 @end