1/* 2 * Copyright (c) 2010 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <CoreFoundation/CoreFoundation.h> 37 38#include "UserEventAgentInterface.h" 39 40#include <sys/types.h> 41#include <stdio.h> 42#include <stdlib.h> 43#include <asl.h> 44 45#include "kcm.h" 46 47typedef struct { 48 UserEventAgentInterfaceStruct *agentInterface; 49 CFUUIDRef factoryID; 50 UInt32 refCount; 51 52 CFRunLoopRef rl; 53 54 CFNotificationCenterRef darwin; 55 CFNotificationCenterRef distributed; 56 57} GSSNotificationForwarder; 58 59static void 60GSSNotificationForwarderDelete(GSSNotificationForwarder *instance) { 61 62 CFUUIDRef factoryID = instance->factoryID; 63 64 asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "UserEventAgentFactory: %s", __func__); 65 66 /* XXX */ 67 68 if (instance->darwin) 69 CFRelease(instance->darwin); 70 if (instance->distributed) 71 CFRelease(instance->distributed); 72 if (instance->rl) 73 CFRelease(instance->rl); 74 75 if (factoryID) { 76 CFPlugInRemoveInstanceForFactory(factoryID); 77 CFRelease(factoryID); 78 } 79 free(instance); 80} 81 82 83static void 84cc_changed(CFNotificationCenterRef center, 85 void *observer, 86 CFStringRef name, 87 const void *object, 88 CFDictionaryRef userInfo) 89{ 90 GSSNotificationForwarder *instance = observer; 91 92 CFNotificationCenterPostNotification(instance->distributed, 93 CFSTR(kCCAPICacheCollectionChangedNotification), 94 NULL, 95 NULL, 96 false); 97} 98 99static void 100GSSNotificationForwarderInstall(void *pinstance) 101{ 102 GSSNotificationForwarder *instance = pinstance; 103 104 asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "UserEventAgentFactory: %s", __func__); 105 106 instance->darwin = CFNotificationCenterGetDarwinNotifyCenter(); 107 instance->distributed = CFNotificationCenterGetDistributedCenter(); 108 109 CFNotificationCenterAddObserver(instance->darwin, 110 instance, 111 cc_changed, 112 CFSTR(KRB5_KCM_NOTIFY_CACHE_CHANGED), 113 NULL, 114 CFNotificationSuspensionBehaviorHold); 115 116} 117 118 119static HRESULT 120GSSNotificationForwarderQueryInterface(void *pinstance, REFIID iid, LPVOID *ppv) 121{ 122 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(NULL, iid); 123 GSSNotificationForwarder *instance = pinstance; 124 125 asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "UserEventAgentFactory: %s", __func__); 126 127 if (CFEqual(interfaceID, kUserEventAgentInterfaceID) || CFEqual(interfaceID, IUnknownUUID)) { 128 instance->agentInterface->AddRef(instance); 129 *ppv = instance; 130 CFRelease(interfaceID); 131 return S_OK; 132 } 133 134 *ppv = NULL; 135 CFRelease(interfaceID); 136 return E_NOINTERFACE; 137} 138 139static ULONG 140GSSNotificationForwarderAddRef(void *pinstance) 141{ 142 GSSNotificationForwarder *instance = pinstance; 143 return ++instance->refCount; 144} 145 146static ULONG 147GSSNotificationForwarderRelease(void *pinstance) 148{ 149 GSSNotificationForwarder *instance = pinstance; 150 if (instance->refCount == 1) { 151 GSSNotificationForwarderDelete(instance); 152 return 0; 153 } 154 return --instance->refCount; 155} 156 157 158 159static UserEventAgentInterfaceStruct UserEventAgentInterfaceFtbl = { 160 NULL, 161 GSSNotificationForwarderQueryInterface, 162 GSSNotificationForwarderAddRef, 163 GSSNotificationForwarderRelease, 164 GSSNotificationForwarderInstall 165}; 166 167 168static GSSNotificationForwarder * 169GSSNotificationForwarderCreate(CFAllocatorRef allocator, CFUUIDRef factoryID) 170{ 171 GSSNotificationForwarder *instance; 172 173 asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "UserEventAgentFactory: %s", __func__); 174 175 instance = calloc(1, sizeof(*instance)); 176 if (instance == NULL) 177 return NULL; 178 179 instance->agentInterface = &UserEventAgentInterfaceFtbl; 180 if (factoryID) { 181 instance->factoryID = (CFUUIDRef)CFRetain(factoryID); 182 CFPlugInAddInstanceForFactory(factoryID); 183 } 184 185 instance->rl = CFRunLoopGetCurrent(); 186 CFRetain(instance->rl); 187 188 instance->refCount = 1; 189 return instance; 190} 191 192 193void * 194UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID); 195 196 197void * 198UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID) 199{ 200 asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "UserEventAgentFactory: %s", __func__); 201 202 if (CFEqual(typeID, kUserEventAgentTypeID)) 203 return GSSNotificationForwarderCreate(allocator, kUserEventAgentFactoryID); 204 205 return NULL; 206} 207