* We now store passwords for network servers securely instead of storing them in plain text in the Growl preferences. Heh.
* Remove unneeded code related to resolving Bonjour clients immediately, since we want to resolve them as-needed rather than storing a static IP/port.
5 // Created by Ingmar Stein on 16.04.05.
6 // Copyright 2005-2006 The Growl Project. All rights reserved.
9 #import "GrowlBrowserEntry.h"
10 #import "GrowlPreferencePane.h"
11 #include "CFDictionaryAdditions.h"
12 #include "CFMutableDictionaryAdditions.h"
13 #include <Security/SecKeychain.h>
14 #include <Security/SecKeychainItem.h>
16 #define GrowlBrowserEntryKeychainServiceName "GrowlOutgoingNetworkConnection"
18 @implementation GrowlBrowserEntry
20 - (id) initWithDictionary:(NSDictionary *)dict {
21 if ((self = [self init])) {
22 properties = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, (CFDictionaryRef)dict);
28 - (id) initWithComputerName:(NSString *)name {
29 if ((self = [self init])) {
30 properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
31 CFDictionarySetValue(properties, CFSTR("computer"), name);
32 CFDictionarySetValue(properties, CFSTR("use"), kCFBooleanFalse);
33 CFDictionarySetValue(properties, CFSTR("active"), kCFBooleanTrue);
40 return getBooleanForKey((NSDictionary *)properties, @"use");
43 - (void) setUse:(BOOL)flag {
44 setBooleanForKey((NSMutableDictionary *)properties, @"use", flag);
45 [owner writeForwardDestinations];
49 return getBooleanForKey((NSDictionary *)properties, @"active");
52 - (void) setActive:(BOOL)flag {
53 setBooleanForKey((NSMutableDictionary *)properties, @"active", flag);
54 [owner writeForwardDestinations];
57 - (NSString *) computerName {
58 return (NSString *)CFDictionaryGetValue(properties, CFSTR("computer"));
61 - (void) setComputerName:(NSString *)name {
62 CFDictionarySetValue(properties, CFSTR("computer"), name);
63 [owner writeForwardDestinations];
66 - (NSString *) password {
67 if (!didPasswordLookup) {
68 unsigned char *passwordChars;
69 UInt32 passwordLength;
71 const char *computerNameChars = [[self computerName] UTF8String];
72 status = SecKeychainFindGenericPassword(NULL,
73 strlen(GrowlBrowserEntryKeychainServiceName), GrowlBrowserEntryKeychainServiceName,
74 strlen(computerNameChars), computerNameChars,
75 &passwordLength, (void **)&passwordChars, NULL);
76 if (status == noErr) {
77 password = [[NSString alloc] initWithBytes:passwordChars
79 encoding:NSUTF8StringEncoding];
80 SecKeychainItemFreeContent(NULL, password);
82 if (status != errSecItemNotFound)
83 NSLog(@"Failed to retrieve password for %@ from keychain. Error: %d", status);
87 didPasswordLookup = YES;
94 - (void) setPassword:(NSString *)inPassword {
95 if (password != inPassword) {
97 password = [inPassword copy];
100 // Store the password to the keychain
101 // XXX TODO Use AIKeychain
102 const char *passwordChars = password ? [password UTF8String] : "";
104 SecKeychainItemRef itemRef = nil;
105 const char *computerNameChars = [[self computerName] UTF8String];
106 status = SecKeychainFindGenericPassword(NULL,
107 strlen(GrowlBrowserEntryKeychainServiceName), GrowlBrowserEntryKeychainServiceName,
108 strlen(computerNameChars), computerNameChars,
109 NULL, NULL, &itemRef);
110 if (status == errSecItemNotFound) {
112 status = SecKeychainAddGenericPassword(NULL,
113 strlen(GrowlBrowserEntryKeychainServiceName), GrowlBrowserEntryKeychainServiceName,
114 strlen(computerNameChars), computerNameChars,
115 strlen(passwordChars), passwordChars, NULL);
117 NSLog(@"Failed to add password to keychain.");
119 // change existing password
120 SecKeychainAttribute attrs[] = {
121 { kSecAccountItemAttr, strlen(computerNameChars), (char *)computerNameChars },
122 { kSecServiceItemAttr, strlen(GrowlBrowserEntryKeychainServiceName), (char *)GrowlBrowserEntryKeychainServiceName }
124 const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
125 status = SecKeychainItemModifyAttributesAndData(itemRef, // the item reference
126 &attributes, // no change to attributes
127 strlen(passwordChars), // length of password
128 passwordChars // pointer to password data
133 NSLog(@"Failed to change password in keychain.");
136 [owner writeForwardDestinations];
139 - (void) setOwner:(GrowlPreferencePane *)pref {
143 - (NSDictionary *) properties {
144 return (NSDictionary *)properties;
150 CFRelease(properties);