//
// ViewController.m
//
#import "ViewController.h"
#import <GSS/GSS.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
_queue = dispatch_queue_create("com.apple.GSSSampleIOS.credential.queue", NULL);
[self listCredentials:self];
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (void)kdestroyAll
{
OM_uint32 min_stat;
gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID oid, gss_cred_id_t gcred) {
if (gcred) {
NSLog(@"destroy credential: OM_uint32 foo;
gss_destroy_cred(&foo, &gcred);
}
});
}
- (gss_cred_id_t)getACred
{
OM_uint32 min_stat;
__block gss_cred_id_t first = NULL;
gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID oid, gss_cred_id_t gcred) {
if (gcred) {
CFRetain(gcred);
first = gcred;
}
});
return first;
}
- (void)checkNoCredentials
{
__block unsigned num = 0;
OM_uint32 min_stat;
gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID oid, gss_cred_id_t gcred) {
if (gcred != NULL) {
NSLog(@"unexpected cred: num++;
}
});
if (num)
NSLog(@"FAIL too many credential (more then 0)");
}
- (gss_cred_id_t)acquire_cred:(NSString *)name password:(NSString *)password
{
OM_uint32 maj_stat, min_stat;
gss_name_t gname = GSS_C_NO_NAME;
gss_cred_id_t cred = NULL;
CFErrorRef error = NULL;
gss_buffer_desc buffer;
NSLog(@"acquire:
const char *str = [name UTF8String];
buffer.value = (void *)str;
buffer.length = strlen(str);
maj_stat = gss_import_name(&min_stat, &buffer, GSS_C_NT_USER_NAME, &gname);
if (maj_stat) {
NSLog(@"failed to import name: return NULL;
}
NSDictionary *attrs = @{ (id)kGSSICPassword : password };
maj_stat = gss_aapl_initial_cred(gname, GSS_KRB5_MECHANISM, (__bridge CFDictionaryRef)attrs, &cred, &error);
gss_release_name(&min_stat, &gname);
if (maj_stat) {
NSLog(@"error: goto out;
}
NSLog(@"acquire:
if (cred) {
CFUUIDRef uuid = GSSCredentialCopyUUID(cred);
if (uuid == NULL) {
NSLog(@"GSSCredentialCopyUUID error failed to get credential");
CFRelease(cred);
cred = NULL;
goto out;
}
gss_cred_id_t dupCred = GSSCreateCredentialFromUUID(uuid);
if (dupCred == GSS_C_NO_CREDENTIAL) {
NSLog(@"GSSCreateCredentialFromUUID error failed to get credential");
CFRelease(cred);
cred = NULL;
goto out;
}
CFRelease(uuid);
CFRelease(dupCred);
}
out:
return cred;
}
- (BOOL)checkCredentialCacheName
{
OM_uint32 maj_stat;
gss_name_t gname = GSS_C_NO_NAME;
gss_cred_id_t cred = NULL;
CFErrorRef error = NULL;
gname = GSSCreateName(@"ktestuser@ADS.APPLE.COM", GSS_C_NT_USER_NAME, NULL);
if (gname == NULL)
return false;
NSString *password = @"foobar";
CFUUIDRef uuid = CFUUIDCreateFromString(NULL, CFSTR("E5ECDD5B-1348-4452-A31A-A0A791F94114"));
NSDictionary *attrs = @{
(id)kGSSICPassword : password,
(id)kGSSICKerberosCacheName : @"XCACHE:E5ECDD5B-1348-4452-A31A-A0A791F94114"
};
maj_stat = gss_aapl_initial_cred(gname, GSS_KRB5_MECHANISM, (__bridge CFDictionaryRef)attrs, &cred, &error);
CFRelease(gname);
if (maj_stat) {
NSLog(@"error: return false;
}
CFUUIDRef creduuid = GSSCredentialCopyUUID(cred);
if (!CFEqual(creduuid, uuid))
return false;
CFRelease(cred);
return true;
}
- (BOOL)authenticate:(gss_cred_id_t)cred nameType:(gss_OID)nameType toServer:(NSString *)serverName
{
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
gss_name_t server_name = GSS_C_NO_NAME;
gss_buffer_desc buffer;
OM_uint32 maj_stat, min_stat;
BOOL res;
NSLog(@"acquire:
const char *name = [serverName UTF8String];
buffer.value = (void *)name;
buffer.length = strlen(name);
maj_stat = gss_import_name(&min_stat, &buffer, nameType, &server_name);
if (maj_stat != GSS_S_COMPLETE) {
NSLog(@"import_name maj_stat: return FALSE;
}
maj_stat = gss_init_sec_context(&min_stat, cred,
&ctx, server_name, GSS_KRB5_MECHANISM,
GSS_C_REPLAY_FLAG|GSS_C_INTEG_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS,
NULL, NULL, &buffer, NULL, NULL);
if (maj_stat) {
NSLog(@"FAIL init_sec_context maj_stat: res = FALSE;
} else {
NSLog(@"have a buffer of length: res = TRUE;
}
gss_release_name(&min_stat, &server_name);
gss_release_buffer(&min_stat, &buffer);
return res;
}
- (Boolean)testCSD11
{
gss_cred_id_t cred = NULL;
OM_uint32 min_stat;
cred = [self acquire_cred:@"testuser@CSD11.APPLE.COM" password:@"testuser"];
if (cred == NULL)
return false;
[self authenticate:cred nameType:GSS_C_NT_HOSTBASED_SERVICE toServer:@"HTTP@csd11.apple.com"];
gss_release_cred(&min_stat, &cred);
return true;
}
- (Boolean)testADS
{
OM_uint32 maj_stat, min_stat;
gss_name_t name = GSS_C_NO_NAME;
gss_cred_id_t cred = NULL;
cred = [self acquire_cred:@"ktestuser@ADS.APPLE.COM" password:@"foobar"];
if (cred == NULL)
return false;
maj_stat = gss_inquire_cred(&min_stat, cred, &name, NULL, NULL, NULL);
if (maj_stat != GSS_S_COMPLETE) {
NSLog(@"error inquire name: } else {
NSLog(@"inquire name: }
gss_release_name(&min_stat, &name);
NSLog(@"start list");
maj_stat = gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID mech, gss_cred_id_t gcred) {
if (gcred == NULL)
return;
OM_uint32 major, minor;
gss_name_t name2;
NSLog(@"list cred:
major = gss_inquire_cred(&minor, gcred, &name2, NULL, NULL, NULL);
if (major != GSS_S_COMPLETE) {
NSLog(@"failed to inquire cred: return;
}
gss_release_cred(&minor, &gcred);
NSLog(@"list name:
});
NSLog(@"end list");
if (maj_stat)
NSLog(@"list error:
NSLog(@"authenticate");
[self authenticate:cred nameType:GSS_C_NT_HOSTBASED_SERVICE toServer:@"ldap@dc02.ads.apple.com"];
[self authenticate:cred nameType:GSS_KRB5_NT_PRINCIPAL_NAME toServer:@"ldap/dc02.ads.apple.com@ADS.APPLE.COM"];
return true;
}
- (IBAction)listCredentials:(id)sender
{
__block unsigned ncreds = 0;
OM_uint32 min_stat;
self.ticketView.text = @"<nocred>";
NSMutableString *str = [NSMutableString string];
gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID mech, gss_cred_id_t cred) {
CFStringRef displayName = NULL;
CFStringRef uuidName = NULL;
gss_name_t name = NULL;
CFUUIDRef uuid = NULL;
if (cred == NULL)
return;
ncreds++;
name = GSSCredentialCopyName(cred);
if (name == NULL)
goto out;
displayName = GSSNameCreateDisplayString(name);
if (displayName == NULL)
goto out;
[str appendString:(__bridge NSString *)displayName];
uuid = GSSCredentialCopyUUID(cred);
if (uuid == NULL)
goto out;
uuidName = CFUUIDCreateString(NULL, uuid);
[str appendString:@" uuid: "];
[str appendString:(__bridge NSString *)uuidName];
out:
[str appendString:@"\n"];
if (displayName)
CFRelease(displayName);
if (name)
CFRelease(name);
if (uuidName)
CFRelease(uuidName);
if (uuid)
CFRelease(uuid);
});
NSLog(@"num creds in list: self.ticketView.text = str;
}
- (IBAction)deleteAllCredentials:(id)sender
{
self.ticketView.text = @"<nocred>";
[self kdestroyAll];
}
- (IBAction)authServer:(id)sender
{
gss_cred_id_t cred = [self getACred];
NSString *res;
if ([self authenticate:cred nameType:GSS_C_NT_HOSTBASED_SERVICE toServer:[self.authServerName text]])
res = @"pass";
else
res = @"fail";
self.authServerResult.text = res;
}
- (IBAction)nsURLFetch:(id)sender
{
NSLog(@"nsURLFetch");
NSURL *url = [NSURL URLWithString:self.urlTextField.text];
NSError *error = NULL;
self.urlResultTextView.text = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if ( self.urlResultTextView.text == NULL)
self.urlResultTextView.text = [error localizedDescription];
if ( self.urlResultTextView.text == NULL)
self.urlResultTextView.text = @"why what ?, failed";
}
- (IBAction)acquirektestuserAtADS:(id)sender
{
[self acquire_cred:@"ktestuser@ADS.APPLE.COM" password:@"foobar"];
[self listCredentials:sender];
}
- (IBAction)addCredential:(id)sender {
static bool running = false;
NSLog(@"Add credential hit");
if (running)
return;
NSLog(@"Add credential");
running = true;
/*
* Run on queue in background since the all operations are blocking
*/
dispatch_async(_queue, ^{
NSLog(@"destroy all");
[self kdestroyAll];
NSLog(@"check none exists");
[self checkNoCredentials];
NSLog(@"test ADS");
if (![self testADS])
goto out;
[self kdestroyAll];
[self checkNoCredentials];
NSLog(@"test CSD11");
if (![self testCSD11])
goto out;
[self kdestroyAll];
[self checkNoCredentials];
NSLog(@"test checkCredentialCacheName");
[self checkCredentialCacheName];
[self kdestroyAll];
NSLog(@"complete");
out:
running = false;
});
}
@end