CredentialTableController.m [plain text]
//
// CredentialTableController.m
// GSSTestApp
//
// Created by Love Hörnquist Åstrand on 2014-08-16.
// Copyright (c) 2014 Apple, Inc. All rights reserved.
//
#import "CredentialTableController.h"
#import <GSS/GSS.h>
#import <notify.h>
@interface CredentialTableController ()
@property (assign) CFMutableArrayRef array;
@property (assign) CFMutableDictionaryRef credentials;
@property (assign) int token;
@property (strong) NSMutableSet *notificationObjects;
@end
@implementation CredentialTableController
+ (CredentialTableController *)getGlobalController {
static dispatch_once_t onceToken;
static CredentialTableController *controller = NULL;
dispatch_once(&onceToken, ^{
controller = [[CredentialTableController alloc] init];
});
return controller;
}
- (CredentialTableController *)init {
if ((self = [super init]) == nil)
return nil;
self.array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
self.credentials = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
[self updateCredentials];
self.notificationObjects = [NSMutableSet set];
self.token = NOTIFY_TOKEN_INVALID;
notify_register_dispatch("com.apple.Kerberos.cache.changed", &_token, dispatch_get_main_queue(), ^(int token) {
[self updateCredentials];
});
return self;
}
- (void)dealloc {
notify_cancel(self.token);
CFRelease(_array);
CFRelease(_credentials);
}
- (void)addNotification:(id<GSSCredentialsChangeNotification>)object
{
[self.notificationObjects addObject:object];
}
- (void)removeNotification:(id<GSSCredentialsChangeNotification>)object
{
[self.notificationObjects removeObject:object];
}
- (void)updateCredentials {
OM_uint32 min_stat;
__block bool changeHappned = false;
CFMutableDictionaryRef removedItems = CFDictionaryCreateMutableCopy(NULL, 0, self.credentials);
gss_iter_creds(&min_stat, 0, GSS_KRB5_MECHANISM, ^(gss_OID mechOID, gss_cred_id_t cred) {
CFStringRef nameString = NULL;
gss_name_t name = NULL;
CFUUIDRef uuid;
if (cred == NULL)
return;
uuid = GSSCredentialCopyUUID(cred);
if (uuid == NULL) {
CFRelease(cred);
return;
}
if (CFDictionaryGetValue(self.credentials, uuid)) {
CFDictionaryRemoveValue(removedItems, uuid);
CFRelease(uuid);
CFRelease(cred);
return;
}
name = GSSCredentialCopyName(cred);
if (name) {
nameString = GSSNameCreateDisplayString(name);
CFRelease(name);
}
if (nameString) {
CFDictionarySetValue(self.credentials, uuid, nameString);
CFArrayAppendValue(self.array, uuid);
NSLog(@"adding: CFRelease(nameString);
changeHappned = true;
}
CFRelease(uuid);
CFRelease(cred);
});
[(__bridge NSDictionary *)removedItems enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
CFIndex n = CFArrayGetFirstIndexOfValue(self.array, CFRangeMake(0, CFArrayGetCount(self.array)), (__bridge CFUUIDRef)key);
if (n > 0) {
CFArrayRemoveValueAtIndex(self.array, n);
changeHappned = true;
}
}];
CFRelease(removedItems);
if (changeHappned) {
for (id<GSSCredentialsChangeNotification> object in self.notificationObjects) {
[object GSSCredentialChangeNotifification];
}
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return CFArrayGetCount(self.array);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"CredentialTableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
CFUUIDRef uuid = (CFUUIDRef)CFArrayGetValueAtIndex(self.array, indexPath.row);
NSString *name = NULL;
if (uuid)
name = CFDictionaryGetValue(self.credentials, uuid);
cell.textLabel.text = name ? name : @"???";
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
CFUUIDRef uuid = (CFUUIDRef)CFArrayGetValueAtIndex(self.array, indexPath.row);
OM_uint32 min_stat;
gss_cred_id_t cred = GSSCreateCredentialFromUUID(uuid);
if (cred)
gss_destroy_cred(&min_stat, &cred);
CFDictionaryRemoveValue(self.credentials, uuid);
CFArrayRemoveValueAtIndex(self.array, indexPath.row);
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
@end