]> git.saurik.com Git - apple/security.git/blobdiff - Keychain/CCallbackMgr.cp
Security-163.tar.gz
[apple/security.git] / Keychain / CCallbackMgr.cp
index 4ff7ab72e1d180684f4211f37c4cb1713c698e98..5fc770bdd7b792f0668f5766ae680e41187edbff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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)
 {
 }
 
@@ -78,7 +71,7 @@ CCallbackMgr *CCallbackMgr::mCCallbackMgr;
 
 CCallbackMgr::CCallbackMgr() :
     // register for receiving Keychain events via CF
-    Observer( kSecEventNotificationName, NULL, CFNotificationSuspensionBehaviorDeliverImmediately )
+    Observer(Listener::databaseNotifications, Listener::allEvents)
 {
 }
 
@@ -94,7 +87,7 @@ CCallbackMgr& CCallbackMgr::Instance()
        return *mCCallbackMgr;
 }
 
-void CCallbackMgr::AddCallback( SecKeychainCallbackProcPtr inCallbackFunction, 
+void CCallbackMgr::AddCallback( SecKeychainCallback inCallbackFunction, 
                              SecKeychainEventMask      inEventMask,
                              void*                     inContext)
 
@@ -118,54 +111,16 @@ void CCallbackMgr::AddCallback( SecKeychainCallbackProcPtr inCallbackFunction,
        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);
@@ -175,66 +130,17 @@ void CCallbackMgr::RemoveCallback(SecKeychainCallbackProcPtr 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;
@@ -247,20 +153,13 @@ void CCallbackMgr::AlertClients(SecKeychainEvent 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);
        }
 }
 
@@ -276,38 +175,40 @@ void CCallbackMgr::AlertClients(SecKeychainEvent inEvent,
 *                      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);
 }