]>
Commit | Line | Data |
---|---|---|
5958d7c0 | 1 | /* |
a40a14f8 | 2 | * Copyright (c) 2000-2009 Apple Inc. All rights reserved. |
5958d7c0 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
009ee3c6 | 5 | * |
009ee3c6 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
5958d7c0 A |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
009ee3c6 A |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
5958d7c0 A |
21 | * @APPLE_LICENSE_HEADER_END@ |
22 | */ | |
23 | ||
0fae82ee A |
24 | /* |
25 | * Modification History | |
26 | * | |
27 | * June 1, 2001 Allan Nathanson <ajn@apple.com> | |
28 | * - public API conversion | |
29 | * | |
30 | * March 24, 2000 Allan Nathanson <ajn@apple.com> | |
31 | * - initial revision | |
32 | */ | |
33 | ||
5958d7c0 A |
34 | #include "configd.h" |
35 | #include "configd_server.h" | |
36 | #include "session.h" | |
37 | ||
edebe297 A |
38 | #include <bsm/libbsm.h> |
39 | #include <sys/types.h> | |
40 | #include <unistd.h> | |
41 | ||
009ee3c6 | 42 | __private_extern__ |
0fae82ee A |
43 | int |
44 | __SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name) | |
5958d7c0 | 45 | { |
5958d7c0 A |
46 | /* |
47 | * allocate and initialize a new session | |
48 | */ | |
009ee3c6 | 49 | *store = (SCDynamicStoreRef)__SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL); |
5958d7c0 A |
50 | |
51 | /* | |
0fae82ee | 52 | * If necessary, initialize the store and session data dictionaries |
5958d7c0 | 53 | */ |
0fae82ee | 54 | if (storeData == NULL) { |
009ee3c6 A |
55 | sessionData = CFDictionaryCreateMutable(NULL, |
56 | 0, | |
57 | &kCFTypeDictionaryKeyCallBacks, | |
58 | &kCFTypeDictionaryValueCallBacks); | |
0fae82ee | 59 | storeData = CFDictionaryCreateMutable(NULL, |
5958d7c0 A |
60 | 0, |
61 | &kCFTypeDictionaryKeyCallBacks, | |
62 | &kCFTypeDictionaryValueCallBacks); | |
009ee3c6 | 63 | patternData = CFDictionaryCreateMutable(NULL, |
5958d7c0 A |
64 | 0, |
65 | &kCFTypeDictionaryKeyCallBacks, | |
66 | &kCFTypeDictionaryValueCallBacks); | |
67 | changedKeys = CFSetCreateMutable(NULL, | |
68 | 0, | |
69 | &kCFTypeSetCallBacks); | |
70 | deferredRemovals = CFSetCreateMutable(NULL, | |
71 | 0, | |
72 | &kCFTypeSetCallBacks); | |
73 | removedSessionKeys = CFSetCreateMutable(NULL, | |
74 | 0, | |
75 | &kCFTypeSetCallBacks); | |
76 | } | |
77 | ||
0fae82ee | 78 | return kSCStatusOK; |
5958d7c0 A |
79 | } |
80 | ||
81 | ||
edebe297 A |
82 | static CFStringRef |
83 | openMPCopyDescription(const void *info) | |
84 | { | |
85 | return CFStringCreateWithFormat(NULL, NULL, CFSTR("<SCDynamicStore MP>")); | |
86 | } | |
87 | ||
88 | ||
009ee3c6 | 89 | __private_extern__ |
5958d7c0 A |
90 | kern_return_t |
91 | _configopen(mach_port_t server, | |
92 | xmlData_t nameRef, /* raw XML bytes */ | |
93 | mach_msg_type_number_t nameLen, | |
dbf6a266 A |
94 | xmlData_t optionsRef, /* raw XML bytes */ |
95 | mach_msg_type_number_t optionsLen, | |
5958d7c0 | 96 | mach_port_t *newServer, |
edebe297 A |
97 | int *sc_status, |
98 | audit_token_t audit_token) | |
5958d7c0 | 99 | { |
dbf6a266 | 100 | CFDictionaryRef info; |
dbf6a266 A |
101 | serverSessionRef mySession; |
102 | CFStringRef name = NULL; /* name (un-serialized) */ | |
103 | CFMutableDictionaryRef newInfo; | |
dbf6a266 A |
104 | mach_port_t oldNotify; |
105 | CFDictionaryRef options = NULL; /* options (un-serialized) */ | |
106 | CFStringRef sessionKey; | |
107 | kern_return_t status; | |
108 | SCDynamicStorePrivateRef storePrivate; | |
109 | CFBooleanRef useSessionKeys = NULL; | |
5958d7c0 | 110 | |
edebe297 A |
111 | *sc_status = kSCStatusOK; |
112 | ||
5958d7c0 | 113 | /* un-serialize the name */ |
009ee3c6 | 114 | if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) { |
0fae82ee | 115 | *sc_status = kSCStatusFailed; |
edebe297 A |
116 | } |
117 | ||
118 | if ((optionsRef != NULL) && (optionsLen > 0)) { | |
119 | /* un-serialize the [session] options */ | |
120 | if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) { | |
121 | *sc_status = kSCStatusFailed; | |
122 | } | |
123 | } | |
124 | ||
125 | if (*sc_status != kSCStatusOK) { | |
dbf6a266 | 126 | goto done; |
a5f60add A |
127 | } |
128 | ||
129 | if (!isA_CFString(name)) { | |
0fae82ee | 130 | *sc_status = kSCStatusInvalidArgument; |
dbf6a266 A |
131 | goto done; |
132 | } | |
133 | ||
edebe297 | 134 | if (options != NULL) { |
dbf6a266 A |
135 | if (!isA_CFDictionary(options)) { |
136 | *sc_status = kSCStatusInvalidArgument; | |
137 | goto done; | |
138 | } | |
139 | ||
140 | /* | |
141 | * [pre-]process any provided options | |
142 | */ | |
143 | useSessionKeys = CFDictionaryGetValue(options, kSCDynamicStoreUseSessionKeys); | |
144 | if (useSessionKeys != NULL) { | |
145 | if (!isA_CFBoolean(useSessionKeys)) { | |
146 | *sc_status = kSCStatusInvalidArgument; | |
147 | goto done; | |
148 | } | |
149 | } | |
5958d7c0 A |
150 | } |
151 | ||
152 | mySession = getSession(server); | |
be997540 | 153 | if ((mySession != NULL) && (mySession->store != NULL)) { |
dbf6a266 A |
154 | #ifdef DEBUG |
155 | SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen(): session is already open.")); | |
156 | #endif /* DEBUG */ | |
0fae82ee | 157 | *sc_status = kSCStatusFailed; /* you can't re-open an "open" session */ |
dbf6a266 | 158 | goto done; |
5958d7c0 A |
159 | } |
160 | ||
5958d7c0 A |
161 | /* |
162 | * establish the new session | |
163 | */ | |
be997540 A |
164 | mySession = addSession(MACH_PORT_NULL, openMPCopyDescription); |
165 | *newServer = mySession->key; | |
a40a14f8 | 166 | __MACH_PORT_DEBUG(TRUE, "*** _configopen (after addSession)", *newServer); |
5958d7c0 | 167 | |
a40a14f8 A |
168 | /* save the audit_token in case we need to check the callers credentials */ |
169 | mySession->auditToken = audit_token; | |
edebe297 | 170 | |
5958d7c0 | 171 | /* Create and add a run loop source for the port */ |
be997540 | 172 | mySession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mySession->serverPort, 0); |
5958d7c0 | 173 | CFRunLoopAddSource(CFRunLoopGetCurrent(), |
be997540 | 174 | mySession->serverRunLoopSource, |
5958d7c0 A |
175 | kCFRunLoopDefaultMode); |
176 | ||
009ee3c6 | 177 | if (_configd_trace) { |
edebe297 A |
178 | SCTrace(TRUE, _configd_trace, |
179 | CFSTR("open : %5d : %@\n"), | |
180 | *newServer, | |
181 | name); | |
009ee3c6 A |
182 | } |
183 | ||
be997540 A |
184 | *sc_status = __SCDynamicStoreOpen(&mySession->store, name); |
185 | storePrivate = (SCDynamicStorePrivateRef)mySession->store; | |
5958d7c0 A |
186 | |
187 | /* | |
188 | * Make the server port accessible to the framework routines. | |
a40a14f8 | 189 | * ... and be sure to clear before calling CFRelease(store) |
5958d7c0 | 190 | */ |
dbf6a266 A |
191 | storePrivate->server = *newServer; |
192 | ||
193 | /* | |
194 | * Process any provided [session] options | |
195 | */ | |
196 | if (useSessionKeys != NULL) { | |
197 | storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys); | |
198 | } | |
5958d7c0 A |
199 | |
200 | /* Request a notification when/if the client dies */ | |
201 | status = mach_port_request_notification(mach_task_self(), | |
202 | *newServer, | |
203 | MACH_NOTIFY_NO_SENDERS, | |
204 | 1, | |
205 | *newServer, | |
206 | MACH_MSG_TYPE_MAKE_SEND_ONCE, | |
207 | &oldNotify); | |
208 | if (status != KERN_SUCCESS) { | |
a40a14f8 | 209 | SCLog(TRUE, LOG_ERR, CFSTR("_configopen() mach_port_request_notification() failed: %s"), mach_error_string(status)); |
5958d7c0 A |
210 | cleanupSession(*newServer); |
211 | *newServer = MACH_PORT_NULL; | |
0fae82ee | 212 | *sc_status = kSCStatusFailed; |
dbf6a266 | 213 | goto done; |
0fae82ee | 214 | } |
a40a14f8 | 215 | __MACH_PORT_DEBUG(TRUE, "*** _configopen (after mach_port_request_notification)", *newServer); |
5958d7c0 | 216 | |
5958d7c0 | 217 | if (oldNotify != MACH_PORT_NULL) { |
a40a14f8 | 218 | SCLog(TRUE, LOG_ERR, CFSTR("_configopen(): oldNotify != MACH_PORT_NULL")); |
5958d7c0 | 219 | } |
5958d7c0 A |
220 | |
221 | /* | |
222 | * Save the name of the calling application / plug-in with the session data. | |
223 | */ | |
224 | sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), *newServer); | |
225 | info = CFDictionaryGetValue(sessionData, sessionKey); | |
edebe297 | 226 | if (info != NULL) { |
5958d7c0 A |
227 | newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); |
228 | } else { | |
229 | newInfo = CFDictionaryCreateMutable(NULL, | |
230 | 0, | |
231 | &kCFTypeDictionaryKeyCallBacks, | |
232 | &kCFTypeDictionaryValueCallBacks); | |
233 | } | |
234 | CFDictionarySetValue(newInfo, kSCDName, name); | |
5958d7c0 A |
235 | CFDictionarySetValue(sessionData, sessionKey, newInfo); |
236 | CFRelease(newInfo); | |
237 | CFRelease(sessionKey); | |
238 | ||
a40a14f8 A |
239 | /* |
240 | * Note: at this time we should be holding ONE send right and | |
241 | * ONE receive right to the server. The send right is | |
242 | * moved to the caller. | |
243 | */ | |
244 | ||
dbf6a266 A |
245 | done : |
246 | ||
edebe297 A |
247 | if (name != NULL) CFRelease(name); |
248 | if (options != NULL) CFRelease(options); | |
5958d7c0 A |
249 | return KERN_SUCCESS; |
250 | } |