ViewController.m   [plain text]

//
// 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: %@", gcred);
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: %@", gcred);
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: %@", name);

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: %@", 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: %d %@", (int)maj_stat, error);
goto out;
}

NSLog(@"acquire: %@ done", name);

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: %d %@", (int)maj_stat, 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: %@ to %@", cred, serverName);

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: %d min_stat: %d", (int)maj_stat, (int)min_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: %d", (int)maj_stat);
res = FALSE;
} else {
NSLog(@"have a buffer of length: %d, success", (int)buffer.length);
res = TRUE;
}

gss_delete_sec_context(&min_stat, &ctx, NULL);
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: %d", (int)maj_stat);
} else {
NSLog(@"inquire name: %@", 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: %@", gcred);

major = gss_inquire_cred(&minor, gcred, &name2, NULL, NULL, NULL);
if (major != GSS_S_COMPLETE) {
NSLog(@"failed to inquire cred: %d/%d", major, minor);
return;
}

gss_release_cred(&minor, &gcred);

NSLog(@"list name: %@", name2);

});
NSLog(@"end list");
if (maj_stat)
NSLog(@"list error: %d", (int)maj_stat);

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: %u", ncreds);
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