/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved.
*
* The contents of this file constitute Original Code as defined in and are
* subject to the Apple Public Source License Version 1.2 (the 'License').
Contains: Code that communicates with processes that install a callback
with the Keychain Manager to receive keychain events.
- Written by: Sari Harrison, Craig Mortensen
-
- Copyright: © 1998-2000 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- To Do:
*/
#include "CCallbackMgr.h"
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
#include "Globals.h"
#include <Security/DLDBListCFPref.h>
+#include <Security/SecCFTypes.h>
+//#include <Security/Keychain.h>
-//using namespace std;
using namespace KeychainCore;
using namespace CssmClient;
-static const UInt32 kTicksBetweenIdleEvents = 5L;
-
#pragma mark ÑÑÑÑ CallbackInfo ÑÑÑÑ
CallbackInfo::CallbackInfo() : mCallback(NULL),mEventMask(0),mContext(NULL)
{
}
-CallbackInfo::CallbackInfo(SecKeychainCallbackProcPtr inCallbackFunction,SecKeychainEventMask inEventMask,void *inContext)
- : mCallback(inCallbackFunction),mEventMask(inEventMask),mContext(inContext)
+CallbackInfo::CallbackInfo(SecKeychainCallback inCallbackFunction,
+ SecKeychainEventMask inEventMask, void *inContext)
+ : mCallback(inCallbackFunction), mEventMask(inEventMask), mContext(inContext)
{
}
CCallbackMgr::CCallbackMgr() :
// register for receiving Keychain events via CF
- Observer( kSecEventNotificationName, NULL, CFNotificationSuspensionBehaviorDeliverImmediately )
+ Observer(Listener::databaseNotifications, Listener::allEvents)
{
}
return *mCCallbackMgr;
}
-void CCallbackMgr::AddCallback( SecKeychainCallbackProcPtr inCallbackFunction,
+void CCallbackMgr::AddCallback( SecKeychainCallback inCallbackFunction,
SecKeychainEventMask inEventMask,
void* inContext)
CCallbackMgr::Instance().mEventCallbacks.push_back(info);
}
-#if 0
-void CCallbackMgr::AddCallbackUPP(KCCallbackUPP inCallbackFunction,
- KCEventMask inEventMask,
- void* inContext)
-{
- CallbackInfo info( reinterpret_cast<SecKeychainCallbackProcPtr>(inCallbackFunction), inEventMask, inContext );
- CallbackInfo existingInfo;
-
-#if TARGET_API_MAC_OS8
- OSErr err = noErr;
- err = ::GetCurrentProcess( &info.mProcessID );
- KCThrowIf_( err );
-#endif
-
- CallbackInfoListIterator ix = find( CCallbackMgr::Instance().mEventCallbacks.begin(),
- CCallbackMgr::Instance().mEventCallbacks.end(), info );
-
- // make sure it is not already there
- if ( ix!=CCallbackMgr::Instance().mEventCallbacks.end() )
- {
- // It's already there. This could mean that the old process died unexpectedly,
- // so we need to validate the process ID of the existing callback.
-#if TARGET_API_MAC_OS8
- if (ValidProcess(ix->mProcessID)) // existing callback is OK, so don't add this one.
- MacOSError::throwMe(errKCDuplicateCallback);
-
- // Process is gone, so remove the old entry
- CCallbackMgr::Instance().mEventCallbacks.erase(ix);
-#else
- // On Mac OS X this list is per process so this is always a duplicate
- MacOSError::throwMe(errKCDuplicateCallback);
-#endif
- }
-
- CCallbackMgr::Instance().mEventCallbacks.push_back(info);
-}
-#endif
-
class Predicate
{
- SecKeychainCallbackProcPtr mCallbackFunction;
+ SecKeychainCallback mCallbackFunction;
public:
- Predicate(SecKeychainCallbackProcPtr inCallbackFunction) : mCallbackFunction(inCallbackFunction) {}
+ Predicate(SecKeychainCallback inCallbackFunction) : mCallbackFunction(inCallbackFunction) {}
bool operator()(const CallbackInfo &cbInfo) { return cbInfo.mCallback == mCallbackFunction; }
};
-void CCallbackMgr::RemoveCallback(SecKeychainCallbackProcPtr inCallbackFunction)
+void CCallbackMgr::RemoveCallback(SecKeychainCallback inCallbackFunction)
{
size_t oldSize = CCallbackMgr::Instance().mEventCallbacks.size();
Predicate predicate(inCallbackFunction);
MacOSError::throwMe(errSecInvalidCallback);
}
-#if 0
-void CCallbackMgr::RemoveCallbackUPP(KCCallbackUPP inCallbackFunction)
-{
- size_t oldSize = CCallbackMgr::Instance().mEventCallbacks.size();
- Predicate predicate(reinterpret_cast<SecKeychainCallbackProcPtr>(inCallbackFunction));
- CCallbackMgr::Instance().mEventCallbacks.remove_if(predicate);
-
- if (oldSize == CCallbackMgr::Instance().mEventCallbacks.size())
- MacOSError::throwMe(errKCInvalidCallback);
-}
-#endif
-
-bool CCallbackMgr::ThisProcessUsesSystemEvtCallback()
-{
- const SecKeychainEventMask theMask = 1 << kSecSystemEvent;
-
-
- for ( CallbackInfoListIterator ix = CCallbackMgr::Instance().mEventCallbacks.begin();
- ix!=CCallbackMgr::Instance().mEventCallbacks.end(); ++ix )
- {
- if ( ix->mEventMask & theMask)
- return true;
- }
- return false;
-}
-
-//%%% jch move this function to SecurityHI
-bool CCallbackMgr::ThisProcessCanDisplayUI()
-{
- return true;
-}
-
-#if 0
-void CCallbackMgr::Idle()
-{
- static unsigned long lastTickCount = 0;
- unsigned long tickCount = ::TickCount( );
-
- if (tickCount > lastTickCount+kTicksBetweenIdleEvents)
- {
- lastTickCount = tickCount;
- }
-}
-#endif
-
-void CCallbackMgr::AlertClients(SecKeychainEvent inEvent, bool inOKToAllocateMemory)
-{
- AlertClients(inEvent, Keychain(), Item(), inOKToAllocateMemory);
-}
-
void CCallbackMgr::AlertClients(SecKeychainEvent inEvent,
+ pid_t inPid,
const Keychain &inKeychain,
- const Item &inItem,
- bool inOKToAllocateMemory)
+ const Item &inItem)
{
+ secdebug("kcnotify", "dispatch event %ld pid %d keychain %p item %p",
+ inEvent, inPid, &inKeychain, !!inItem ? &*inItem : NULL);
+
// Deal with events that we care about ourselves first.
- if (inEvent == kSecDefaultChangedEvent)
- globals().defaultKeychain.reload(true);
- else if (inEvent == kSecKeychainListChangedEvent)
- globals().storageManager.reload(true);
+ if (inEvent == kSecDeleteEvent && inKeychain.get() && inItem.get())
+ inKeychain->didDeleteItem(inItem.get());
// Iterate through callbacks, looking for those registered for inEvent
const SecKeychainEventMask theMask = 1U << inEvent;
SecKeychainCallbackInfo cbInfo;
cbInfo.version = 0; // @@@ kKeychainAPIVersion;
- cbInfo.item = inItem ? ItemRef::handle(inItem) : 0;
- cbInfo.keychain = inKeychain ? KeychainRef::handle(inKeychain) : 0;
-
-#if 0
- //%%%cpm- need to change keychaincore.i so we don't to the reinterpret_cast
- // we need a carbon-version of the callbackmgr to register for events
- // and call the "C" real callback mgr (use the ix->mCallback when this is ready)
-
- // until then, we rely on CarbonCore for the UPP stuff
- InvokeKCCallbackUPP(inEvent,reinterpret_cast<KCCallbackInfo*>(&cbInfo),ix->mContext,
- reinterpret_cast<KCCallbackUPP>(ix->mCallback));
-#else
- ix->mCallback(inEvent,&cbInfo,ix->mContext);
-#endif
+ cbInfo.item = inItem ? inItem->handle() : 0;
+ cbInfo.keychain = inKeychain ? inKeychain->handle() : 0;
+ cbInfo.pid = inPid;
+
+ ix->mCallback(inEvent, &cbInfo, ix->mContext);
+ if (cbInfo.item) CFRelease(cbInfo.item);
+ if (cbInfo.keychain) CFRelease(cbInfo.keychain);
}
}
* If it wasn't 'us', we should remove our cached reference to the item that was deleted.
*
***********************************************************************************/
-void CCallbackMgr::Event(CFNotificationCenterRef center,
- CFStringRef name,
- const void *object,
- CFDictionaryRef userInfo)
+void CCallbackMgr::Event (Listener::Domain domain, Listener::Event whichEvent, NameValueDictionary &dictionary)
{
// Decode from userInfo the event type, 'keychain' CFDict, and 'item' CFDict
- CCFValue event(CFDictionaryGetValue( userInfo, kSecEventTypeKey ));
- SecKeychainEvent thisEvent = 0;
- if (!event.hasValue())
- return;
+ SecKeychainEvent thisEvent = whichEvent;
- thisEvent = sint32( event );
-
- CFDictionaryRef kc = reinterpret_cast<CFDictionaryRef>
- (CFDictionaryGetValue(userInfo, kSecEventKeychainKey));
- Keychain thisKeychain;
- if (kc)
- {
- thisKeychain = globals().storageManager.keychain
- (DLDbListCFPref::cfDictionaryRefToDLDbIdentifier(kc));
- }
+ pid_t thisPid;
+ const NameValuePair* pidRef = dictionary.FindByName (PID_KEY);
+ if (pidRef == 0)
+ {
+ thisPid = 0;
+ }
+ else
+ {
+ thisPid = *reinterpret_cast<pid_t*>(pidRef->Value ().data ());
+ }
- CFDataRef item = reinterpret_cast<CFDataRef>
- (CFDictionaryGetValue(userInfo, kSecEventItemKey));
+ Keychain thisKeychain = 0;
+
+ // make sure we have a database identifier
+ if (dictionary.FindByName (SSUID_KEY) != 0)
+ {
+ DLDbIdentifier dbid = NameValueDictionary::MakeDLDbIdentifierFromNameValueDictionary (dictionary);
+ thisKeychain = globals().storageManager.keychain (dbid);
+ }
+
+ const NameValuePair* item = dictionary.FindByName (ITEM_KEY);
Item thisItem;
+
if (item && thisKeychain)
{
- const CssmData pkData(const_cast<UInt8*>(CFDataGetBytePtr(item)), CFDataGetLength(item));
- PrimaryKey pk(pkData);
+ PrimaryKey pk(item->Value ());
thisItem = thisKeychain->item(pk);
}
// Notify our process of this event.
- CCallbackMgr::AlertClients(thisEvent, thisKeychain, thisItem);
+ CCallbackMgr::AlertClients(thisEvent, thisPid, thisKeychain, thisItem);
}