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
);