2  * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 
   4  * The contents of this file constitute Original Code as defined in and are 
   5  * subject to the Apple Public Source License Version 1.2 (the 'License'). 
   6  * You may not use this file except in compliance with the License. Please obtain 
   7  * a copy of the License at http://www.apple.com/publicsource and read it before 
  10  * This Original Code and all software distributed under the License are 
  11  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 
  12  * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 
  13  * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
  14  * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 
  15  * specific language governing rights and limitations under the License. 
  20 // cfnotifier - quick & dirty code to send keychain lock notification 
  22 #include "cfnotifier.h" 
  23 #include <Security/cfutilities.h> 
  24 #include <Security/debugging.h> 
  28 using namespace Security
; 
  29 using namespace Security::MachPlusPlus
; 
  32 #define notificationName        CFSTR("com.apple.securitycore.kcevent") 
  33 #define eventTypeKey            CFSTR("type") 
  34 #define pidKey                          CFSTR("pid") 
  35 #define keychainKey             CFSTR("keychain") 
  36 #define itekey                  CFSTR("item") 
  37 #define keyGUID                 CFSTR("GUID") 
  38 #define keySubserviceId CFSTR("SubserviceId") 
  39 #define keySubserviceType       CFSTR("SubserviceType") 
  40 #define keyDbName               CFSTR("DbName") 
  41 #define keyDbLocation           CFSTR("DbLocation") 
  42 #define keyActive                       CFSTR("Active") 
  43 #define keyMajorVersion CFSTR("MajorVersion") 
  44 #define keyMinorVersion CFSTR("MinorVersion") 
  45 #define defaultDLDbListKey       CFSTR("DLDBSearchList") 
  46 #define defaultDomain           CFSTR("com.apple.securitycore") 
  53     lockedEvent                
= 1,     /* a keychain was locked */ 
  54     unlockedEvent              
= 2,     /* a keychain was unlocked */ 
  55         passphraseChangedEvent     
= 6  /* a keychain password was (possibly) changed */ 
  62 static CFDictionaryRef 
makeDictionary(const DLDbIdentifier 
&db
); 
  68 void KeychainNotifier::lock(const DLDbIdentifier 
&db
) 
  69 { notify(db
, lockedEvent
); } 
  71 void KeychainNotifier::unlock(const DLDbIdentifier 
&db
) 
  72 { notify(db
, unlockedEvent
); } 
  74 void KeychainNotifier::passphraseChanged(const DLDbIdentifier 
&db
) 
  75 { notify(db
, passphraseChangedEvent
); } 
  79 // Lock and unlock notifications 
  81 void KeychainNotifier::notify(const DLDbIdentifier 
&db
, int event
) 
  83     CFRef
<CFMutableDictionaryRef
> mutableDict(::CFDictionaryCreateMutable( 
  84         kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, 
  85         &kCFTypeDictionaryValueCallBacks
)); 
  87         throw std::bad_alloc(); 
  89     SInt32 theEvent 
= event
; 
  90     CFRef
<CFNumberRef
> theEventData(::CFNumberCreate( kCFAllocatorDefault
, 
  91         kCFNumberSInt32Type
, &theEvent
)); 
  93         throw std::bad_alloc(); 
  94     ::CFDictionarySetValue( mutableDict
, eventTypeKey
, theEventData 
); 
  96     CFRef
<CFDictionaryRef
> dict 
= makeDictionary(db
); 
  98         throw std::bad_alloc(); 
  99     ::CFDictionarySetValue(mutableDict
, keychainKey
, dict
); 
 101     for (Session::Iterator it 
= Session::begin(); it 
!= Session::end(); it
++) { 
 102         StBootstrap 
bootSwitch(it
->second
->bootstrapPort()); 
 103         IFDEBUG(debug("cfnotify", "send event %d for database %s to session %p", 
 104             event
, db
.dbName(), it
->second
)); 
 105         ::CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), 
 106             notificationName
, NULL
, mutableDict
, false); 
 110 static CFDictionaryRef 
makeDictionary(const DLDbIdentifier 
&db
) 
 112         CFRef
<CFMutableDictionaryRef
> aDict(CFDictionaryCreateMutable(kCFAllocatorDefault
,0, 
 113                 &kCFTypeDictionaryKeyCallBacks
,&kCFTypeDictionaryValueCallBacks
)); 
 115         throw std::bad_alloc(); 
 117     // Put SUBSERVICE_UID in dictionary 
 118     char buffer
[Guid::stringRepLength
+1]; 
 119     const CssmSubserviceUid
& ssuid
=db
.ssuid(); 
 120     const Guid 
&theGuid 
= Guid::overlay(ssuid
.Guid
); 
 121     CFRef
<CFStringRef
> stringGuid(::CFStringCreateWithCString(kCFAllocatorDefault
, 
 122             theGuid
.toString(buffer
),kCFStringEncodingMacRoman
)); 
 124         ::CFDictionarySetValue(aDict
,keyGUID
,stringGuid
); 
 126     if (ssuid
.SubserviceId
!=0) 
 128         CFRef
<CFNumberRef
> subserviceId(::CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.SubserviceId
)); 
 130             ::CFDictionarySetValue(aDict
,keySubserviceId
,subserviceId
); 
 132     if (ssuid
.SubserviceType
!=0) 
 134         CFRef
<CFNumberRef
> subserviceType(CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.SubserviceType
)); 
 136             ::CFDictionarySetValue(aDict
,keySubserviceType
,subserviceType
); 
 138     if (ssuid
.Version
.Major
!=0 && ssuid
.Version
.Minor
!=0) 
 140         CFRef
<CFNumberRef
> majorVersion(::CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.Version
.Major
)); 
 142             ::CFDictionarySetValue(aDict
,keyMajorVersion
,majorVersion
); 
 143         CFRef
<CFNumberRef
> minorVersion(::CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.Version
.Minor
)); 
 145             ::CFDictionarySetValue(aDict
,keyMinorVersion
,minorVersion
); 
 148     // Put DbName in dictionary 
 149         const char *dbName
=db
.dbName(); 
 152         CFRef
<CFStringRef
> theDbName(::CFStringCreateWithCString(kCFAllocatorDefault
,dbName
,kCFStringEncodingMacRoman
)); 
 153         ::CFDictionarySetValue(aDict
,keyDbName
,theDbName
); 
 155     // Put DbLocation in dictionary 
 156         const CSSM_NET_ADDRESS 
*dbLocation
=db
.dbLocation(); 
 157     if (dbLocation
!=NULL 
&& dbLocation
->AddressType
!=CSSM_ADDR_NONE
) 
 159         CFRef
<CFDataRef
> theData(::CFDataCreate(kCFAllocatorDefault
,dbLocation
->Address
.Data
,dbLocation
->Address
.Length
)); 
 161             ::CFDictionarySetValue(aDict
,keyDbLocation
,theData
);