]> git.saurik.com Git - apple/security.git/blob - SecurityServer/cfnotifier.cpp
Security-54.tar.gz
[apple/security.git] / SecurityServer / cfnotifier.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // cfnotifier - quick & dirty code to send keychain lock notification
21 //
22 #include "cfnotifier.h"
23 #include <Security/cfutilities.h>
24 #include <Security/debugging.h>
25
26 #include "session.h"
27
28 using namespace Security;
29 using namespace Security::MachPlusPlus;
30
31
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")
47
48
49 //
50 // Event codes
51 //
52 enum {
53 lockedEvent = 1, /* a keychain was locked */
54 unlockedEvent = 2, /* a keychain was unlocked */
55 passphraseChangedEvent = 6 /* a keychain password was (possibly) changed */
56 };
57
58
59 //
60 // Local functions
61 //
62 static CFDictionaryRef makeDictionary(const DLDbIdentifier &db);
63
64
65 //
66 // Main methods
67 //
68 void KeychainNotifier::lock(const DLDbIdentifier &db)
69 { notify(db, lockedEvent); }
70
71 void KeychainNotifier::unlock(const DLDbIdentifier &db)
72 { notify(db, unlockedEvent); }
73
74 void KeychainNotifier::passphraseChanged(const DLDbIdentifier &db)
75 { notify(db, passphraseChangedEvent); }
76
77
78 //
79 // Lock and unlock notifications
80 //
81 void KeychainNotifier::notify(const DLDbIdentifier &db, int event)
82 {
83 CFRef<CFMutableDictionaryRef> mutableDict(::CFDictionaryCreateMutable(
84 kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
85 &kCFTypeDictionaryValueCallBacks));
86 if (!mutableDict)
87 throw std::bad_alloc();
88
89 SInt32 theEvent = event;
90 CFRef<CFNumberRef> theEventData(::CFNumberCreate( kCFAllocatorDefault,
91 kCFNumberSInt32Type, &theEvent));
92 if (!theEventData)
93 throw std::bad_alloc();
94 ::CFDictionarySetValue( mutableDict, eventTypeKey, theEventData );
95
96 CFRef<CFDictionaryRef> dict = makeDictionary(db);
97 if (!dict)
98 throw std::bad_alloc();
99 ::CFDictionarySetValue(mutableDict, keychainKey, dict);
100
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);
107 }
108 }
109
110 static CFDictionaryRef makeDictionary(const DLDbIdentifier &db)
111 {
112 CFRef<CFMutableDictionaryRef> aDict(CFDictionaryCreateMutable(kCFAllocatorDefault,0,
113 &kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks));
114 if (!aDict)
115 throw std::bad_alloc();
116
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));
123 if (stringGuid)
124 ::CFDictionarySetValue(aDict,keyGUID,stringGuid);
125
126 if (ssuid.SubserviceId!=0)
127 {
128 CFRef<CFNumberRef> subserviceId(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.SubserviceId));
129 if (subserviceId)
130 ::CFDictionarySetValue(aDict,keySubserviceId,subserviceId);
131 }
132 if (ssuid.SubserviceType!=0)
133 {
134 CFRef<CFNumberRef> subserviceType(CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.SubserviceType));
135 if (subserviceType)
136 ::CFDictionarySetValue(aDict,keySubserviceType,subserviceType);
137 }
138 if (ssuid.Version.Major!=0 && ssuid.Version.Minor!=0)
139 {
140 CFRef<CFNumberRef> majorVersion(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.Version.Major));
141 if (majorVersion)
142 ::CFDictionarySetValue(aDict,keyMajorVersion,majorVersion);
143 CFRef<CFNumberRef> minorVersion(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.Version.Minor));
144 if (minorVersion)
145 ::CFDictionarySetValue(aDict,keyMinorVersion,minorVersion);
146 }
147
148 // Put DbName in dictionary
149 const char *dbName=db.dbName();
150 if (dbName)
151 {
152 CFRef<CFStringRef> theDbName(::CFStringCreateWithCString(kCFAllocatorDefault,dbName,kCFStringEncodingMacRoman));
153 ::CFDictionarySetValue(aDict,keyDbName,theDbName);
154 }
155 // Put DbLocation in dictionary
156 const CSSM_NET_ADDRESS *dbLocation=db.dbLocation();
157 if (dbLocation!=NULL && dbLocation->AddressType!=CSSM_ADDR_NONE)
158 {
159 CFRef<CFDataRef> theData(::CFDataCreate(kCFAllocatorDefault,dbLocation->Address.Data,dbLocation->Address.Length));
160 if (theData)
161 ::CFDictionarySetValue(aDict,keyDbLocation,theData);
162 }
163
164 ::CFRetain(aDict);
165 return aDict;
166 }
167