/* * Credentials.m * * $Header$ * * Copyright 2004 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #import "Credentials.h" #import "Utilities.h" @implementation Credentials // --------------------------------------------------------------------------- - (id) initWithCCache: (cc_ccache_t) ccache version: (cc_int32) credsVersion { if ((self = [super init])) { dprintf ("Entering initWithCCache:version: ..."); principal = NULL; credentialsArray = NULL; tgtIndex = -1; version = kerberosVersion_Any; if ([self synchronizeWithCCache: ccache version: credsVersion] != ccNoError) { [self release]; self = NULL; } } return self; } // --------------------------------------------------------------------------- - (void) dealloc { if (principal != NULL) { [principal release]; } if (credentialsArray != NULL) { [credentialsArray release]; } [super dealloc]; } // --------------------------------------------------------------------------- - (int) synchronizeWithCCache: (cc_ccache_t) ccache version: (cc_int32) credsVersion { dprintf ("Entering synchronizeWithCCache:version: ..."); cc_int32 err = ccNoError; cc_string_t credsPrincipal = NULL; Principal *newPrincipal = NULL; cc_credentials_iterator_t iterator = NULL; int newTGTIndex = -1; NSMutableArray *newCredentialsArray = NULL; if (err == ccNoError) { err = cc_ccache_get_principal (ccache, credsVersion, &credsPrincipal); } if (err == ccNoError) { NSString *credsPrincipalString = [NSString stringWithUTF8String: credsPrincipal->data]; KLKerberosVersion klCredsVersion = (credsVersion == cc_credentials_v4) ? kerberosVersion_V4 : kerberosVersion_V5; newPrincipal = [[Principal alloc] initWithString: credsPrincipalString klVersion: klCredsVersion]; if (newPrincipal == NULL) { err = ccErrNoMem; } } if (err == ccNoError) { newCredentialsArray = [[NSMutableArray alloc] init]; if (newCredentialsArray == NULL) { err = ccErrNoMem; } } if (err == ccNoError) { err = cc_ccache_new_credentials_iterator (ccache, &iterator); } while (err == ccNoError) { cc_credentials_t creds = NULL; Credential *credential = NULL; if (err == ccNoError) { err = cc_credentials_iterator_next (iterator, &creds); } if (err == ccNoError) { if (creds->data->version == credsVersion) { credential = [self findCredentialForCredentials: creds]; if (credential != NULL) { err = [credential synchronizeWithCredentials: creds]; } else { credential = [[[Credential alloc] initWithCredentials: creds] autorelease]; if (credential == NULL) { err = ccErrNoMem; } } if (err == ccNoError) { if (newTGTIndex < 0 && [credential isTGT]) { newTGTIndex = [newCredentialsArray count]; // Remember first TGT of this version dprintf ("TGT index for version %s is %d", [[Utilities stringForCCVersion: credsVersion] UTF8String], newTGTIndex); } [newCredentialsArray addObject: credential]; credential = NULL; // don't free creds = NULL; // credential takes ownership of this } } } if (credential != NULL) { [credential release]; } if (creds != NULL) { cc_credentials_release (creds); } } if (err == ccIteratorEnd) { err = ccNoError; } if (err == ccNoError) { if (credentialsArray != NULL) { [credentialsArray release]; } credentialsArray = newCredentialsArray; if (principal != NULL) { [principal release]; } principal = newPrincipal; newPrincipal = NULL; tgtIndex = newTGTIndex; version = credsVersion; } else { dprintf ("synchronizeWithCCache:version: returning error %d (%s)", err, error_message (err)); } if (iterator != NULL) { cc_credentials_iterator_release (iterator); } if (newPrincipal != NULL) { [newPrincipal release]; } if (credsPrincipal != NULL) { cc_string_release (credsPrincipal); } return err; } // --------------------------------------------------------------------------- - (Credential *) findCredentialForCredentials: (cc_credentials_t) creds { unsigned int i = 0; for (i = 0; i < [credentialsArray count]; i++) { Credential *credential = [credentialsArray objectAtIndex: i]; if ([credential isEqualToCredentials: creds]) { return credential; } } return NULL; } // --------------------------------------------------------------------------- - (BOOL) needsValidation { BOOL needsValidation = NO; if (tgtIndex >= 0) { return [[credentialsArray objectAtIndex: tgtIndex] needsValidation]; } else { if ([credentialsArray count] > 0) { unsigned int i; // return union of bad states on service ticket if there is no tgt for (i = 0; i < [credentialsArray count]; i++) { if ([[credentialsArray objectAtIndex: i] needsValidation]) { needsValidation = YES; break; } } } } return needsValidation; } // --------------------------------------------------------------------------- - (int) stateAtTime: (time_t) atTime { int state = CredentialValid; if (tgtIndex >= 0) { // prefer tgt time state = [[credentialsArray objectAtIndex: tgtIndex] stateAtTime: atTime]; } else { if ([credentialsArray count] > 0) { unsigned int i; // return union of bad states on service ticket if there is no tgt for (i = 0; i < [credentialsArray count]; i++) { state |= [[credentialsArray objectAtIndex: i] timeRemainingAtTime: atTime]; } } else { state = CredentialInvalid; // no tickets at all } } return state; } // --------------------------------------------------------------------------- - (cc_time_t) timeRemainingAtTime: (time_t) atTime { cc_time_t timeRemaining = 0; // default if there are no tickets at all if (tgtIndex >= 0) { // prefer tgt time timeRemaining = [[credentialsArray objectAtIndex: tgtIndex] timeRemainingAtTime: atTime]; } else { if ([credentialsArray count] > 0) { // return smallest time of service tickets if there is no tgt timeRemaining = [[credentialsArray objectAtIndex: 0] timeRemainingAtTime: atTime]; unsigned int i; for (i = 1; i < [credentialsArray count]; i++) { cc_time_t temp = [[credentialsArray objectAtIndex: 0] timeRemainingAtTime: atTime]; if (temp < timeRemaining) { timeRemaining = temp; } } } } return timeRemaining; } // --------------------------------------------------------------------------- - (Principal *) principal { return principal; } // --------------------------------------------------------------------------- - (NSString *) principalString { return [principal displayStringForCCVersion: version]; } // --------------------------------------------------------------------------- - (NSAttributedString *) stringValueForTicketColumn { NSString *string = [NSString stringWithFormat: @"(%@) %@", [Utilities stringForCCVersion: version], [self principalString]]; NSDictionary *attributes = [Utilities attributesForTicketColumnCellOfControlSize: NSSmallControlSize bold: YES italic: ([self stateAtTime: time (NULL)] != CredentialValid)]; return [[[NSAttributedString alloc] initWithString: string attributes: attributes] autorelease]; } // --------------------------------------------------------------------------- - (NSAttributedString *) stringValueForLifetimeColumn { time_t now = time (NULL); int state = [self stateAtTime: now]; cc_time_t timeRemaining = [self timeRemainingAtTime: now]; NSString *string = [Utilities stringForTimeRemaining: timeRemaining state: state format: kShortFormat]; NSDictionary *attributes = [Utilities attributesForLifetimeColumnCellOfControlSize: NSSmallControlSize bold: YES state: state timeRemaining: timeRemaining]; return [[NSAttributedString alloc] initWithString: string attributes: attributes]; } // --------------------------------------------------------------------------- - (int) numberOfChildren { return [credentialsArray count]; } // --------------------------------------------------------------------------- - (id) childAtIndex: (int) rowIndex { return [credentialsArray objectAtIndex: rowIndex]; } @end