ViewController.m
1 // 2 // ViewController.m 3 // 4 5 #import "ViewController.h" 6 7 #import <GSS/GSS.h> 8 9 10 @interface ViewController () 11 12 @end 13 14 @implementation ViewController 15 16 - (void)didReceiveMemoryWarning 17 { 18 [super didReceiveMemoryWarning]; 19 // Release any cached data, images, etc that aren't in use. 20 } 21 22 #pragma mark - View lifecycle 23 24 - (void)viewDidLoad 25 { 26 [super viewDidLoad]; 27 _queue = dispatch_queue_create("com.apple.GSSSampleIOS.credential.queue", NULL); 28 [self listCredentials:self]; 29 } 30 31 - (NSUInteger)supportedInterfaceOrientations 32 { 33 return UIInterfaceOrientationMaskPortrait; 34 } 35 36 - (void)kdestroyAll 37 { 38 OM_uint32 min_stat; 39 40 gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID oid, gss_cred_id_t gcred) { 41 if (gcred) { 42 NSLog(@"destroy credential: %@", gcred); 43 OM_uint32 foo; 44 gss_destroy_cred(&foo, &gcred); 45 } 46 }); 47 } 48 49 - (gss_cred_id_t)getACred 50 { 51 OM_uint32 min_stat; 52 __block gss_cred_id_t first = NULL; 53 54 gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID oid, gss_cred_id_t gcred) { 55 if (gcred) { 56 CFRetain(gcred); 57 first = gcred; 58 } 59 }); 60 return first; 61 } 62 63 64 - (void)checkNoCredentials 65 { 66 __block unsigned num = 0; 67 OM_uint32 min_stat; 68 69 gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID oid, gss_cred_id_t gcred) { 70 if (gcred != NULL) { 71 NSLog(@"unexpected cred: %@", gcred); 72 num++; 73 } 74 }); 75 if (num) 76 NSLog(@"FAIL too many credential (more then 0)"); 77 } 78 79 - (gss_cred_id_t)acquire_cred:(NSString *)name password:(NSString *)password 80 { 81 OM_uint32 maj_stat, min_stat; 82 gss_name_t gname = GSS_C_NO_NAME; 83 gss_cred_id_t cred = NULL; 84 CFErrorRef error = NULL; 85 gss_buffer_desc buffer; 86 87 NSLog(@"acquire: %@", name); 88 89 const char *str = [name UTF8String]; 90 buffer.value = (void *)str; 91 buffer.length = strlen(str); 92 93 maj_stat = gss_import_name(&min_stat, &buffer, GSS_C_NT_USER_NAME, &gname); 94 if (maj_stat) { 95 NSLog(@"failed to import name: %@", name); 96 return NULL; 97 } 98 99 NSDictionary *attrs = @{ (id)kGSSICPassword : password }; 100 101 maj_stat = gss_aapl_initial_cred(gname, GSS_KRB5_MECHANISM, (__bridge CFDictionaryRef)attrs, &cred, &error); 102 gss_release_name(&min_stat, &gname); 103 if (maj_stat) { 104 NSLog(@"error: %d %@", (int)maj_stat, error); 105 goto out; 106 } 107 108 NSLog(@"acquire: %@ done", name); 109 110 if (cred) { 111 CFUUIDRef uuid = GSSCredentialCopyUUID(cred); 112 if (uuid == NULL) { 113 NSLog(@"GSSCredentialCopyUUID error failed to get credential"); 114 CFRelease(cred); 115 cred = NULL; 116 goto out; 117 } 118 gss_cred_id_t dupCred = GSSCreateCredentialFromUUID(uuid); 119 if (dupCred == GSS_C_NO_CREDENTIAL) { 120 NSLog(@"GSSCreateCredentialFromUUID error failed to get credential"); 121 CFRelease(cred); 122 cred = NULL; 123 goto out; 124 } 125 126 CFRelease(uuid); 127 CFRelease(dupCred); 128 } 129 130 out: 131 return cred; 132 } 133 134 - (BOOL)checkCredentialCacheName 135 { 136 OM_uint32 maj_stat; 137 gss_name_t gname = GSS_C_NO_NAME; 138 gss_cred_id_t cred = NULL; 139 CFErrorRef error = NULL; 140 141 142 gname = GSSCreateName(@"ktestuser@ADS.APPLE.COM", GSS_C_NT_USER_NAME, NULL); 143 if (gname == NULL) 144 return false; 145 146 NSString *password = @"foobar"; 147 148 CFUUIDRef uuid = CFUUIDCreateFromString(NULL, CFSTR("E5ECDD5B-1348-4452-A31A-A0A791F94114")); 149 150 NSDictionary *attrs = @{ 151 (id)kGSSICPassword : password, 152 (id)kGSSICKerberosCacheName : @"XCACHE:E5ECDD5B-1348-4452-A31A-A0A791F94114" 153 }; 154 155 maj_stat = gss_aapl_initial_cred(gname, GSS_KRB5_MECHANISM, (__bridge CFDictionaryRef)attrs, &cred, &error); 156 CFRelease(gname); 157 if (maj_stat) { 158 NSLog(@"error: %d %@", (int)maj_stat, error); 159 return false; 160 } 161 162 CFUUIDRef creduuid = GSSCredentialCopyUUID(cred); 163 164 if (!CFEqual(creduuid, uuid)) 165 return false; 166 167 CFRelease(cred); 168 169 170 return true; 171 } 172 173 - (BOOL)authenticate:(gss_cred_id_t)cred nameType:(gss_OID)nameType toServer:(NSString *)serverName 174 { 175 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 176 gss_name_t server_name = GSS_C_NO_NAME; 177 gss_buffer_desc buffer; 178 OM_uint32 maj_stat, min_stat; 179 BOOL res; 180 181 NSLog(@"acquire: %@ to %@", cred, serverName); 182 183 184 const char *name = [serverName UTF8String]; 185 buffer.value = (void *)name; 186 buffer.length = strlen(name); 187 188 maj_stat = gss_import_name(&min_stat, &buffer, nameType, &server_name); 189 if (maj_stat != GSS_S_COMPLETE) { 190 NSLog(@"import_name maj_stat: %d min_stat: %d", (int)maj_stat, (int)min_stat); 191 return FALSE; 192 } 193 194 maj_stat = gss_init_sec_context(&min_stat, cred, 195 &ctx, server_name, GSS_KRB5_MECHANISM, 196 GSS_C_REPLAY_FLAG|GSS_C_INTEG_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS, 197 NULL, NULL, &buffer, NULL, NULL); 198 if (maj_stat) { 199 NSLog(@"FAIL init_sec_context maj_stat: %d", (int)maj_stat); 200 res = FALSE; 201 } else { 202 NSLog(@"have a buffer of length: %d, success", (int)buffer.length); 203 res = TRUE; 204 } 205 206 gss_delete_sec_context(&min_stat, &ctx, NULL); 207 gss_release_name(&min_stat, &server_name); 208 gss_release_buffer(&min_stat, &buffer); 209 210 return res; 211 } 212 213 214 215 - (Boolean)testCSD11 216 { 217 gss_cred_id_t cred = NULL; 218 OM_uint32 min_stat; 219 220 cred = [self acquire_cred:@"testuser@CSD11.APPLE.COM" password:@"testuser"]; 221 if (cred == NULL) 222 return false; 223 224 [self authenticate:cred nameType:GSS_C_NT_HOSTBASED_SERVICE toServer:@"HTTP@csd11.apple.com"]; 225 226 227 gss_release_cred(&min_stat, &cred); 228 229 return true; 230 } 231 232 - (Boolean)testADS 233 { 234 OM_uint32 maj_stat, min_stat; 235 gss_name_t name = GSS_C_NO_NAME; 236 gss_cred_id_t cred = NULL; 237 238 cred = [self acquire_cred:@"ktestuser@ADS.APPLE.COM" password:@"foobar"]; 239 if (cred == NULL) 240 return false; 241 242 maj_stat = gss_inquire_cred(&min_stat, cred, &name, NULL, NULL, NULL); 243 if (maj_stat != GSS_S_COMPLETE) { 244 NSLog(@"error inquire name: %d", (int)maj_stat); 245 } else { 246 NSLog(@"inquire name: %@", name); 247 } 248 gss_release_name(&min_stat, &name); 249 250 NSLog(@"start list"); 251 maj_stat = gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID mech, gss_cred_id_t gcred) { 252 if (gcred == NULL) 253 return; 254 OM_uint32 major, minor; 255 gss_name_t name2; 256 257 NSLog(@"list cred: %@", gcred); 258 259 major = gss_inquire_cred(&minor, gcred, &name2, NULL, NULL, NULL); 260 if (major != GSS_S_COMPLETE) { 261 NSLog(@"failed to inquire cred: %d/%d", major, minor); 262 return; 263 } 264 265 gss_release_cred(&minor, &gcred); 266 267 NSLog(@"list name: %@", name2); 268 269 }); 270 NSLog(@"end list"); 271 if (maj_stat) 272 NSLog(@"list error: %d", (int)maj_stat); 273 274 NSLog(@"authenticate"); 275 276 [self authenticate:cred nameType:GSS_C_NT_HOSTBASED_SERVICE toServer:@"ldap@dc02.ads.apple.com"]; 277 [self authenticate:cred nameType:GSS_KRB5_NT_PRINCIPAL_NAME toServer:@"ldap/dc02.ads.apple.com@ADS.APPLE.COM"]; 278 279 return true; 280 } 281 282 - (IBAction)listCredentials:(id)sender 283 { 284 __block unsigned ncreds = 0; 285 OM_uint32 min_stat; 286 287 self.ticketView.text = @"<nocred>"; 288 289 290 NSMutableString *str = [NSMutableString string]; 291 292 gss_iter_creds(&min_stat, 0, NULL, ^(gss_OID mech, gss_cred_id_t cred) { 293 CFStringRef displayName = NULL; 294 CFStringRef uuidName = NULL; 295 gss_name_t name = NULL; 296 CFUUIDRef uuid = NULL; 297 298 if (cred == NULL) 299 return; 300 301 ncreds++; 302 303 name = GSSCredentialCopyName(cred); 304 if (name == NULL) 305 goto out; 306 307 displayName = GSSNameCreateDisplayString(name); 308 if (displayName == NULL) 309 goto out; 310 311 [str appendString:(__bridge NSString *)displayName]; 312 313 uuid = GSSCredentialCopyUUID(cred); 314 if (uuid == NULL) 315 goto out; 316 317 uuidName = CFUUIDCreateString(NULL, uuid); 318 319 [str appendString:@" uuid: "]; 320 [str appendString:(__bridge NSString *)uuidName]; 321 322 323 out: 324 [str appendString:@"\n"]; 325 if (displayName) 326 CFRelease(displayName); 327 if (name) 328 CFRelease(name); 329 330 if (uuidName) 331 CFRelease(uuidName); 332 if (uuid) 333 CFRelease(uuid); 334 335 }); 336 NSLog(@"num creds in list: %u", ncreds); 337 self.ticketView.text = str; 338 339 } 340 341 - (IBAction)deleteAllCredentials:(id)sender 342 { 343 self.ticketView.text = @"<nocred>"; 344 [self kdestroyAll]; 345 } 346 347 - (IBAction)authServer:(id)sender 348 { 349 gss_cred_id_t cred = [self getACred]; 350 NSString *res; 351 352 if ([self authenticate:cred nameType:GSS_C_NT_HOSTBASED_SERVICE toServer:[self.authServerName text]]) 353 res = @"pass"; 354 else 355 res = @"fail"; 356 357 self.authServerResult.text = res; 358 359 } 360 361 - (IBAction)nsURLFetch:(id)sender 362 { 363 NSLog(@"nsURLFetch"); 364 365 NSURL *url = [NSURL URLWithString:self.urlTextField.text]; 366 NSError *error = NULL; 367 368 self.urlResultTextView.text = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; 369 if ( self.urlResultTextView.text == NULL) 370 self.urlResultTextView.text = [error localizedDescription]; 371 if ( self.urlResultTextView.text == NULL) 372 self.urlResultTextView.text = @"why what ?, failed"; 373 374 } 375 376 - (IBAction)acquirektestuserAtADS:(id)sender 377 { 378 [self acquire_cred:@"ktestuser@ADS.APPLE.COM" password:@"foobar"]; 379 [self listCredentials:sender]; 380 } 381 382 383 384 - (IBAction)addCredential:(id)sender { 385 static bool running = false; 386 387 NSLog(@"Add credential hit"); 388 389 if (running) 390 return; 391 392 NSLog(@"Add credential"); 393 394 running = true; 395 /* 396 * Run on queue in background since the all operations are blocking 397 */ 398 dispatch_async(_queue, ^{ 399 400 NSLog(@"destroy all"); 401 [self kdestroyAll]; 402 NSLog(@"check none exists"); 403 [self checkNoCredentials]; 404 405 NSLog(@"test ADS"); 406 if (![self testADS]) 407 goto out; 408 409 [self kdestroyAll]; 410 [self checkNoCredentials]; 411 412 NSLog(@"test CSD11"); 413 if (![self testCSD11]) 414 goto out; 415 416 [self kdestroyAll]; 417 [self checkNoCredentials]; 418 419 NSLog(@"test checkCredentialCacheName"); 420 [self checkCredentialCacheName]; 421 422 [self kdestroyAll]; 423 424 NSLog(@"complete"); 425 426 out: 427 running = false; 428 }); 429 430 } 431 432 433 @end