/ Sample / GSSSampleIOS / ViewController.m
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