Core/Source/GrowlBrowserEntry.m
changeset 4153 899d3019a60a
parent 3510 1cb27a4b0a9a
child 4154 a2dbe798edf8
     1.1 --- a/Core/Source/GrowlBrowserEntry.m	Wed May 09 02:33:04 2007 +0000
     1.2 +++ b/Core/Source/GrowlBrowserEntry.m	Mon Jul 28 21:53:02 2008 +0000
     1.3 @@ -10,6 +10,10 @@
     1.4  #import "GrowlPreferencePane.h"
     1.5  #include "CFDictionaryAdditions.h"
     1.6  #include "CFMutableDictionaryAdditions.h"
     1.7 +#include <Security/SecKeychain.h>
     1.8 +#include <Security/SecKeychainItem.h>
     1.9 +
    1.10 +#define GrowlBrowserEntryKeychainServiceName "GrowlOutgoingNetworkConnection"
    1.11  
    1.12  @implementation GrowlBrowserEntry
    1.13  
    1.14 @@ -21,11 +25,10 @@
    1.15  	return self;
    1.16  }
    1.17  
    1.18 -- (id) initWithComputerName:(NSString *)name netService:(NSNetService *)service {
    1.19 +- (id) initWithComputerName:(NSString *)name {
    1.20  	if ((self = [self init])) {
    1.21  		properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    1.22  		CFDictionarySetValue(properties, CFSTR("computer"), name);
    1.23 -		CFDictionarySetValue(properties, CFSTR("netservice"), service);
    1.24  		CFDictionarySetValue(properties, CFSTR("use"), kCFBooleanFalse);
    1.25  		CFDictionarySetValue(properties, CFSTR("active"), kCFBooleanTrue);
    1.26  	}
    1.27 @@ -60,29 +63,76 @@
    1.28  	[owner writeForwardDestinations];
    1.29  }
    1.30  
    1.31 -- (NSNetService *) netService {
    1.32 -	return (NSNetService *)CFDictionaryGetValue(properties, CFSTR("netservice"));
    1.33 +- (NSString *) password {
    1.34 +	if (!didPasswordLookup) {
    1.35 +		unsigned char *passwordChars;
    1.36 +		UInt32 passwordLength;
    1.37 +		OSStatus status;
    1.38 +		const char *computerNameChars = [[self computerName] UTF8String];
    1.39 +		status = SecKeychainFindGenericPassword(NULL,
    1.40 +												strlen(GrowlBrowserEntryKeychainServiceName), GrowlBrowserEntryKeychainServiceName,
    1.41 +												strlen(computerNameChars), computerNameChars,
    1.42 +												&passwordLength, (void **)&passwordChars, NULL);		
    1.43 +		if (status == noErr) {
    1.44 +			password = [[NSString alloc] initWithBytes:passwordChars
    1.45 +												length:passwordLength
    1.46 +											  encoding:NSUTF8StringEncoding];
    1.47 +			SecKeychainItemFreeContent(NULL, password);
    1.48 +		} else {
    1.49 +			if (status != errSecItemNotFound)
    1.50 +				NSLog(@"Failed to retrieve password for %@ from keychain. Error: %d", status);
    1.51 +			password = nil;
    1.52 +		}
    1.53 +		
    1.54 +		didPasswordLookup = YES;
    1.55 +	}
    1.56 +
    1.57 +	
    1.58 +	return password;
    1.59  }
    1.60  
    1.61 -- (void) setNetService:(NSNetService *)service {
    1.62 -	CFDictionarySetValue(properties, CFSTR("netservice"), service);
    1.63 -}
    1.64 +- (void) setPassword:(NSString *)inPassword {
    1.65 +	if (password != inPassword) {
    1.66 +		[password release];
    1.67 +		password = [inPassword copy];
    1.68 +	}
    1.69  
    1.70 -- (NSString *) password {
    1.71 -	return (NSString *)CFDictionaryGetValue(properties, CFSTR("password"));
    1.72 -}
    1.73 -
    1.74 -- (void) setPassword:(NSString *)password {
    1.75 -	if (password)
    1.76 -		CFDictionarySetValue(properties, CFSTR("password"), password);
    1.77 -	else
    1.78 -		CFDictionaryRemoveValue(properties, CFSTR("password"));
    1.79 -	[owner writeForwardDestinations];
    1.80 -}
    1.81 -
    1.82 -- (void) setAddress:(NSData *)address {
    1.83 -	CFDictionarySetValue(properties, CFSTR("address"), address);
    1.84 -	CFDictionaryRemoveValue(properties, CFSTR("netservice"));
    1.85 +	// Store the password to the keychain
    1.86 +	// XXX TODO Use AIKeychain
    1.87 +	const char *passwordChars = password ? [password UTF8String] : "";
    1.88 +	OSStatus status;
    1.89 +	SecKeychainItemRef itemRef = nil;
    1.90 +	const char *computerNameChars = [[self computerName] UTF8String];
    1.91 +	status = SecKeychainFindGenericPassword(NULL,
    1.92 +											strlen(GrowlBrowserEntryKeychainServiceName), GrowlBrowserEntryKeychainServiceName,
    1.93 +											strlen(computerNameChars), computerNameChars,
    1.94 +											NULL, NULL, &itemRef);
    1.95 +	if (status == errSecItemNotFound) {
    1.96 +		// add new item
    1.97 +		status = SecKeychainAddGenericPassword(NULL,
    1.98 +											   strlen(GrowlBrowserEntryKeychainServiceName), GrowlBrowserEntryKeychainServiceName,
    1.99 +											   strlen(computerNameChars), computerNameChars,
   1.100 +											   strlen(passwordChars), passwordChars, NULL);
   1.101 +		if (status)
   1.102 +			NSLog(@"Failed to add password to keychain.");
   1.103 +	} else {
   1.104 +		// change existing password
   1.105 +		SecKeychainAttribute attrs[] = {
   1.106 +			{ kSecAccountItemAttr, strlen(computerNameChars), (char *)computerNameChars },
   1.107 +			{ kSecServiceItemAttr, strlen(GrowlBrowserEntryKeychainServiceName), (char *)GrowlBrowserEntryKeychainServiceName }
   1.108 +		};
   1.109 +		const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
   1.110 +		status = SecKeychainItemModifyAttributesAndData(itemRef,		// the item reference
   1.111 +														&attributes,	// no change to attributes
   1.112 +														strlen(passwordChars),			// length of password
   1.113 +														passwordChars		// pointer to password data
   1.114 +														);
   1.115 +		if (itemRef)
   1.116 +			CFRelease(itemRef);
   1.117 +		if (status)
   1.118 +			NSLog(@"Failed to change password in keychain.");
   1.119 +	}
   1.120 +	
   1.121  	[owner writeForwardDestinations];
   1.122  }
   1.123  
   1.124 @@ -95,6 +145,8 @@
   1.125  }
   1.126  
   1.127  - (void) dealloc {
   1.128 +	[password release];
   1.129 +
   1.130  	CFRelease(properties);
   1.131  	[super dealloc];
   1.132  }