/*
* KerberosCache.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 "KerberosCache.h"
#import "KerberosCredential.h"
@implementation KerberosCache
// ---------------------------------------------------------------------------
- (id) initWithCCache: (cc_ccache_t) newCCache defaultCCache: (cc_ccache_t) defaultCCache
{
if ((self = [super init])) {
dprintf ("Entering initWithCCache:defaultCCache: ...");
ccache = NULL;
principal = NULL;
credentialsArray = NULL;
tgtIndex = -1;
lastChangeTime = 0;
lastDefaultTime = 0;
isDefault = NO;
if ([self synchronizeWithCCache: newCCache defaultCCache: defaultCCache] != ccNoError) {
[self release];
self = NULL;
}
}
return self;
}
// ---------------------------------------------------------------------------
- (void) dealloc
{
if (ccache ) { cc_ccache_release (ccache); }
if (principal ) { [principal release]; }
if (credentialsArray) { [credentialsArray release]; }
[super dealloc];
}
// ---------------------------------------------------------------------------
- (int) synchronizeWithCCache: (cc_ccache_t) newCCache defaultCCache: (cc_ccache_t) defaultCCache
{
cc_int32 err = ccNoError;
cc_time_t newLastChangeTime = 0;
cc_time_t newLastDefaultTime = 0;
cc_string_t credsPrincipal = NULL;
KerberosPrincipal *newPrincipal = NULL;
cc_credentials_iterator_t iterator = NULL;
int newTGTIndex = -1;
NSMutableArray *newCredentialsArray = NULL;
dprintf ("Entering synchronizeWithCCache:defaultCCache: ...");
if (!err) {
err = cc_ccache_get_change_time (newCCache, &newLastChangeTime);
}
if (!err) {
// When this changes, the ccache change time does not necessarily change
err = cc_ccache_get_last_default_time (newCCache, &newLastDefaultTime);
if (err == ccErrNeverDefault) {
err = ccNoError;
newLastDefaultTime = 0;
}
}
if (!err && newLastChangeTime > lastChangeTime) {
dprintf ("synchronizeWithCCache cache got new change time
if (!err) {
err = cc_ccache_get_principal (newCCache, cc_credentials_v5, &credsPrincipal);
}
if (!err) {
newPrincipal = [[KerberosPrincipal alloc] initWithString: [NSString stringWithUTF8String: credsPrincipal->data]];
if (!newPrincipal) { err = ccErrNoMem; }
}
if (!err) {
newCredentialsArray = [[NSMutableArray alloc] init];
if (!newCredentialsArray) { err = ccErrNoMem; }
}
if (!err) {
err = cc_ccache_new_credentials_iterator (newCCache, &iterator);
}
while (!err) {
cc_credentials_t creds = NULL;
KerberosCredential *credential = NULL;
if (!err) {
err = cc_credentials_iterator_next (iterator, &creds);
}
if (!err) {
if (creds->data->version == cc_credentials_v5) {
credential = [self findCredentialForCredentials: creds];
if (credential) {
err = [credential synchronizeWithCredentials: creds];
} else {
credential = [[[KerberosCredential alloc] initWithCredentials: creds] autorelease];
if (!credential) { err = ccErrNoMem; }
}
if (!err) {
if (newTGTIndex < 0 && [credential isTGT]) {
newTGTIndex = [newCredentialsArray count]; // Remember first TGT of this version
dprintf ("TGT index is }
[newCredentialsArray addObject: credential];
credential = NULL; // don't free
creds = NULL; // credential takes ownership of this
}
}
}
if (credential) { [credential release]; }
if (creds ) { cc_credentials_release (creds); }
}
if (err == ccIteratorEnd) {
err = ccNoError;
}
if (!err) {
if (ccache) { cc_ccache_release (ccache); }
ccache = newCCache;
if (credentialsArray) { [credentialsArray release]; }
credentialsArray = newCredentialsArray;
newCredentialsArray = NULL;
if (!principal) { [principal release]; }
principal = newPrincipal;
newPrincipal = NULL;
tgtIndex = newTGTIndex;
lastChangeTime = newLastChangeTime;
}
}
if (!err) {
// For some reason cache default changes don't always update the cache change time.
// Do this after everything else is set up
isDefault = [self isEqualToCCache: defaultCCache];
lastDefaultTime = newLastDefaultTime;
} else {
dprintf ("synchronizeWithCCache:defaultCCache: returning error }
if (iterator ) { cc_credentials_iterator_release (iterator); }
if (newCredentialsArray) { [newCredentialsArray release]; }
if (newPrincipal ) { [newPrincipal release]; }
if (credsPrincipal ) { cc_string_release (credsPrincipal); }
return err;
}
// ---------------------------------------------------------------------------
- (KerberosCredential *) findCredentialForCredentials: (cc_credentials_t) creds
{
unsigned int i = 0;
for (i = 0; i < [credentialsArray count]; i++) {
KerberosCredential *credential = [credentialsArray objectAtIndex: i];
if ([credential isEqualToCredentials: creds]) {
return credential;
}
}
return NULL;
}
// ---------------------------------------------------------------------------
- (BOOL) isEqualToCCache: (cc_ccache_t) compareCCache
{
cc_uint32 equal = NO;
cc_int32 err = ccNoError;
if (!ccache ) { err = ccErrInvalidCCache; }
if (!compareCCache) { err = ccErrInvalidCCache; }
if (!err) {
err = cc_ccache_compare (ccache, compareCCache, &equal);
}
if (!err) {
return equal;
} else {
// errors such as ccErrInvalidCCache mean they are not equal!
return NO;
}
}
// ---------------------------------------------------------------------------
- (cc_int32) lastDefaultTime
{
return lastDefaultTime;
}
// ---------------------------------------------------------------------------
- (BOOL) isDefault
{
return isDefault;
}
// ---------------------------------------------------------------------------
- (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) state
{
int state = CredentialValid;
if (tgtIndex >= 0) {
// prefer tgt time
state = [[credentialsArray objectAtIndex: tgtIndex] state];
} 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] state];
}
} else {
state = CredentialInvalid; // no tickets at all
}
}
return state;
}
// ---------------------------------------------------------------------------
- (cc_time_t) timeRemaining
{
cc_time_t timeRemaining = 0; // default if there are no tickets at all
if (tgtIndex >= 0) {
// prefer tgt time
timeRemaining = [[credentialsArray objectAtIndex: tgtIndex] timeRemaining];
} else {
if ([credentialsArray count] > 0) {
// return smallest time of service tickets if there is no tgt
timeRemaining = [[credentialsArray objectAtIndex: 0] timeRemaining];
unsigned int i;
for (i = 1; i < [credentialsArray count]; i++) {
cc_time_t temp = [[credentialsArray objectAtIndex: i] timeRemaining];
if (temp < timeRemaining) {
timeRemaining = temp;
}
}
}
}
return timeRemaining;
}
// ---------------------------------------------------------------------------
- (NSString *) shortTimeRemainingString
{
return [KerberosCredential stringForTimeRemaining: [self timeRemaining]
state: [self state]
shortFormat: YES];
}
// ---------------------------------------------------------------------------
- (NSString *) longTimeRemainingString
{
return [KerberosCredential stringForTimeRemaining: [self timeRemaining]
state: [self state]
shortFormat: NO];
}
// ---------------------------------------------------------------------------
- (NSString *) ccacheName
{
NSString *string = NULL;
cc_string_t name = NULL;
if (cc_ccache_get_name (ccache, &name) == ccNoError) {
string = [NSString stringWithCString: name->data];
}
if (name) { cc_string_release (name); }
return string;
}
// ---------------------------------------------------------------------------
- (KerberosPrincipal *) principal
{
return principal;
}
// ---------------------------------------------------------------------------
- (NSString *) principalString
{
return [principal displayString];
}
// ---------------------------------------------------------------------------
- (int) numberOfCredentials
{
return [credentialsArray count];
}
// ---------------------------------------------------------------------------
- (id) credentialAtIndex: (int) rowIndex
{
return [credentialsArray objectAtIndex: rowIndex];
}
@end