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/debugging.h>
24 #include <CoreFoundation/CoreFoundation.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 keychainKey CFSTR("keychain")
35 #define itekey CFSTR("item")
36 #define keyGUID CFSTR("GUID")
37 #define keySubserviceId CFSTR("SubserviceId")
38 #define keySubserviceType CFSTR("SubserviceType")
39 #define keyDbName CFSTR("DbName")
40 #define keyDbLocation CFSTR("DbLocation")
41 #define keyActive CFSTR("Active")
42 #define keyMajorVersion CFSTR("MajorVersion")
43 #define keyMinorVersion CFSTR("MinorVersion")
44 #define defaultDLDbListKey CFSTR("DLDBSearchList")
45 #define defaultDomain CFSTR("com.apple.securitycore")
52 lockedEvent
= 1, /* a keychain was locked */
53 unlockedEvent
= 2, /* a keychain was unlocked */
54 passphraseChangedEvent
= 6 /* a keychain password was (possibly) changed */
61 static CFDictionaryRef
makeDictionary(const DLDbIdentifier
&db
);
67 void KeychainNotifier::lock(const DLDbIdentifier
&db
)
68 { notify(db
, lockedEvent
); }
70 void KeychainNotifier::unlock(const DLDbIdentifier
&db
)
71 { notify(db
, unlockedEvent
); }
73 void KeychainNotifier::passphraseChanged(const DLDbIdentifier
&db
)
74 { notify(db
, passphraseChangedEvent
); }
78 // Lock and unlock notifications
80 void KeychainNotifier::notify(const DLDbIdentifier
&db
, int event
)
82 CFRef
<CFMutableDictionaryRef
> mutableDict(::CFDictionaryCreateMutable(
83 kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
,
84 &kCFTypeDictionaryValueCallBacks
));
86 throw std::bad_alloc();
88 SInt32 theEvent
= event
;
89 CFRef
<CFNumberRef
> theEventData(::CFNumberCreate( kCFAllocatorDefault
,
90 kCFNumberSInt32Type
, &theEvent
));
92 throw std::bad_alloc();
93 ::CFDictionarySetValue( mutableDict
, eventTypeKey
, theEventData
);
95 CFRef
<CFDictionaryRef
> dict
= makeDictionary(db
);
97 throw std::bad_alloc();
98 ::CFDictionarySetValue(mutableDict
, keychainKey
, dict
);
100 for (Session::Iterator it
= Session::begin(); it
!= Session::end(); it
++) {
101 StBootstrap
bootSwitch(it
->second
->bootstrapPort());
102 IFDEBUG(debug("cfnotify", "send event %d for database %s to session %p",
103 event
, db
.dbName(), it
->second
));
104 ::CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(),
105 notificationName
, NULL
, mutableDict
, false);
109 static CFDictionaryRef
makeDictionary(const DLDbIdentifier
&db
)
111 CFRef
<CFMutableDictionaryRef
> aDict(CFDictionaryCreateMutable(kCFAllocatorDefault
,0,
112 &kCFTypeDictionaryKeyCallBacks
,&kCFTypeDictionaryValueCallBacks
));
114 throw std::bad_alloc();
116 // Put SUBSERVICE_UID in dictionary
117 char buffer
[Guid::stringRepLength
+1];
118 const CssmSubserviceUid
& ssuid
=db
.ssuid();
119 const Guid
&theGuid
= Guid::overlay(ssuid
.Guid
);
120 CFRef
<CFStringRef
> stringGuid(::CFStringCreateWithCString(kCFAllocatorDefault
,
121 theGuid
.toString(buffer
),kCFStringEncodingMacRoman
));
123 ::CFDictionarySetValue(aDict
,keyGUID
,stringGuid
);
125 if (ssuid
.SubserviceId
!=0)
127 CFRef
<CFNumberRef
> subserviceId(::CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.SubserviceId
));
129 ::CFDictionarySetValue(aDict
,keySubserviceId
,subserviceId
);
131 if (ssuid
.SubserviceType
!=0)
133 CFRef
<CFNumberRef
> subserviceType(CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.SubserviceType
));
135 ::CFDictionarySetValue(aDict
,keySubserviceType
,subserviceType
);
137 if (ssuid
.Version
.Major
!=0 && ssuid
.Version
.Minor
!=0)
139 CFRef
<CFNumberRef
> majorVersion(::CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.Version
.Major
));
141 ::CFDictionarySetValue(aDict
,keyMajorVersion
,majorVersion
);
142 CFRef
<CFNumberRef
> minorVersion(::CFNumberCreate(kCFAllocatorDefault
,kCFNumberSInt32Type
,&ssuid
.Version
.Minor
));
144 ::CFDictionarySetValue(aDict
,keyMinorVersion
,minorVersion
);
147 // Put DbName in dictionary
148 const char *dbName
=db
.dbName();
151 CFRef
<CFStringRef
> theDbName(::CFStringCreateWithCString(kCFAllocatorDefault
,dbName
,kCFStringEncodingMacRoman
));
152 ::CFDictionarySetValue(aDict
,keyDbName
,theDbName
);
154 // Put DbLocation in dictionary
155 const CSSM_NET_ADDRESS
*dbLocation
=db
.dbLocation();
156 if (dbLocation
!=NULL
&& dbLocation
->AddressType
!=CSSM_ADDR_NONE
)
158 CFRef
<CFDataRef
> theData(::CFDataCreate(kCFAllocatorDefault
,dbLocation
->Address
.Data
,dbLocation
->Address
.Length
));
160 ::CFDictionarySetValue(aDict
,keyDbLocation
,theData
);