1/*
2 * Copyright (c) 2000-2006, 2008, 2011, 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
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
34#include "configd.h"
35#include "session.h"
36
37__private_extern__
38int
39__SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef *value, Boolean internal)
40{
41	SCDynamicStorePrivateRef	storePrivate = (SCDynamicStorePrivateRef)store;
42	CFDictionaryRef			dict;
43
44	if (_configd_trace) {
45		SCTrace(TRUE, _configd_trace,
46			CFSTR("%s : %5d : %@\n"),
47			internal ? "*copy  " : "copy   ",
48			storePrivate->server,
49			key);
50	}
51
52	dict = CFDictionaryGetValue(storeData, key);
53	if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDData) == FALSE)) {
54		/* key doesn't exist (or data never defined) */
55		return kSCStatusNoKey;
56	}
57
58	/* Return the data associated with the key */
59	*value = CFRetain(CFDictionaryGetValue(dict, kSCDData));
60
61	return kSCStatusOK;
62}
63
64__private_extern__
65kern_return_t
66_configget(mach_port_t			server,
67	   xmlData_t			keyRef,		/* raw XML bytes */
68	   mach_msg_type_number_t	keyLen,
69	   xmlDataOut_t			*dataRef,	/* raw XML bytes */
70	   mach_msg_type_number_t	*dataLen,
71	   int				*newInstance,
72	   int				*sc_status,
73	   audit_token_t		audit_token)
74{
75	CFStringRef		key		= NULL;		/* key  (un-serialized) */
76	CFIndex			len;
77	serverSessionRef	mySession;
78	Boolean			ok;
79	CFDataRef		value;
80
81	*dataRef = NULL;
82	*dataLen = 0;
83
84	/* un-serialize the key */
85	if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
86		*sc_status = kSCStatusFailed;
87		goto done;
88	}
89
90	if (!isA_CFString(key)) {
91		*sc_status = kSCStatusInvalidArgument;
92		goto done;
93	}
94
95	mySession = getSession(server);
96	if (mySession == NULL) {
97		mySession = tempSession(server, CFSTR("SCDynamicStoreCopyValue"), audit_token);
98		if (mySession == NULL) {
99			/* you must have an open session to play */
100			*sc_status = kSCStatusNoStoreSession;
101			goto done;
102		}
103	}
104
105	*sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value, FALSE);
106	if (*sc_status != kSCStatusOK) {
107		goto done;
108	}
109
110	/* serialize the data */
111	ok = _SCSerializeData(value, (void **)dataRef, &len);
112	*dataLen = (mach_msg_type_number_t)len;
113	CFRelease(value);
114	if (!ok) {
115		*sc_status = kSCStatusFailed;
116		goto done;
117	}
118
119	/*
120	 * return the instance number associated with the returned data.
121	 */
122	*newInstance = 1;
123
124    done :
125
126	if (key != NULL)	CFRelease(key);
127	return KERN_SUCCESS;
128}
129
130/*
131 * "context" argument for addSpecificKey() and addSpecificPattern()
132 */
133typedef struct {
134	SCDynamicStoreRef	store;
135	CFMutableDictionaryRef	dict;
136} addSpecific, *addSpecificRef;
137
138static void
139addSpecificKey(const void *value, void *context)
140{
141	CFDataRef		data;
142	CFStringRef		key		= (CFStringRef)value;
143	addSpecificRef		myContextRef	= (addSpecificRef)context;
144	int			sc_status;
145
146	if (!isA_CFString(key)) {
147		return;
148	}
149
150	sc_status = __SCDynamicStoreCopyValue(myContextRef->store, key, &data, TRUE);
151	if (sc_status == kSCStatusOK) {
152		CFDictionaryAddValue(myContextRef->dict, key, data);
153		CFRelease(data);
154	}
155
156	return;
157}
158
159static void
160addSpecificPattern(const void *value, void *context)
161{
162	CFStringRef		pattern		= (CFStringRef)value;
163	addSpecificRef		myContextRef	= (addSpecificRef)context;
164	int			sc_status;
165	CFArrayRef		keys;
166
167	if (!isA_CFString(pattern)) {
168		return;
169	}
170
171	sc_status = __SCDynamicStoreCopyKeyList(myContextRef->store, pattern, TRUE, &keys);
172	if (sc_status == kSCStatusOK) {
173		CFArrayApplyFunction(keys,
174				     CFRangeMake(0, CFArrayGetCount(keys)),
175				     addSpecificKey,
176				     context);
177		CFRelease(keys);
178	}
179
180	return;
181}
182
183__private_extern__
184int
185__SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRef patterns, CFDictionaryRef *values)
186{
187	SCDynamicStorePrivateRef	storePrivate = (SCDynamicStorePrivateRef)store;
188	addSpecific			myContext;
189
190	if (_configd_trace) {
191		SCTrace(TRUE, _configd_trace,
192			CFSTR("copy m  : %5d : %ld keys, %ld patterns\n"),
193			storePrivate->server,
194			keys     ? CFArrayGetCount(keys)     : 0,
195			patterns ? CFArrayGetCount(patterns) : 0);
196	}
197
198	myContext.store = store;
199	myContext.dict  = CFDictionaryCreateMutable(NULL,
200						    0,
201						    &kCFTypeDictionaryKeyCallBacks,
202						    &kCFTypeDictionaryValueCallBacks);
203
204	if (keys) {
205		CFArrayApplyFunction(keys,
206				     CFRangeMake(0, CFArrayGetCount(keys)),
207				     addSpecificKey,
208				     &myContext);
209	}
210
211	if (patterns) {
212		CFArrayApplyFunction(patterns,
213				     CFRangeMake(0, CFArrayGetCount(patterns)),
214				     addSpecificPattern,
215				     &myContext);
216	}
217
218	/* Return the keys/values associated with the key */
219	*values = myContext.dict;
220
221	return kSCStatusOK;
222}
223
224__private_extern__
225kern_return_t
226_configget_m(mach_port_t		server,
227	     xmlData_t			keysRef,
228	     mach_msg_type_number_t	keysLen,
229	     xmlData_t			patternsRef,
230	     mach_msg_type_number_t	patternsLen,
231	     xmlDataOut_t		*dataRef,
232	     mach_msg_type_number_t	*dataLen,
233	     int			*sc_status,
234	     audit_token_t		audit_token)
235{
236	CFDictionaryRef		dict		= NULL;	/* keys/values (un-serialized) */
237	CFArrayRef		keys		= NULL;	/* keys (un-serialized) */
238	CFIndex			len;
239	serverSessionRef	mySession;
240	Boolean			ok;
241	CFArrayRef		patterns	= NULL;	/* patterns (un-serialized) */
242
243	*dataRef = NULL;
244	*dataLen = 0;
245
246	*sc_status = kSCStatusOK;
247
248	if (keysRef && (keysLen > 0)) {
249		/* un-serialize the keys */
250		if (!_SCUnserialize((CFPropertyListRef *)&keys, NULL, (void *)keysRef, keysLen)) {
251			*sc_status = kSCStatusFailed;
252		}
253	}
254
255	if (patternsRef && (patternsLen > 0)) {
256		/* un-serialize the patterns */
257		if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) {
258			*sc_status = kSCStatusFailed;
259		}
260	}
261
262	if (*sc_status != kSCStatusOK) {
263		goto done;
264	}
265
266	if ((keys != NULL) && !isA_CFArray(keys)) {
267		*sc_status = kSCStatusInvalidArgument;
268		goto done;
269	}
270
271	if ((patterns != NULL) && !isA_CFArray(patterns)) {
272		*sc_status = kSCStatusInvalidArgument;
273		goto done;
274	}
275
276	mySession = getSession(server);
277	if (mySession == NULL) {
278		mySession = tempSession(server, CFSTR("SCDynamicStoreCopyMultiple"), audit_token);
279		if (mySession == NULL) {
280			/* you must have an open session to play */
281			*sc_status = kSCStatusNoStoreSession;
282			goto done;
283		}
284	}
285
286	/* fetch the requested information */
287	*sc_status = __SCDynamicStoreCopyMultiple(mySession->store, keys, patterns, &dict);
288
289	/* serialize the dictionary of matching keys/patterns */
290	ok = _SCSerialize(dict, NULL, (void **)dataRef, &len);
291	*dataLen = (mach_msg_type_number_t)len;
292	CFRelease(dict);
293	if (!ok) {
294		*sc_status = kSCStatusFailed;
295	}
296
297    done :
298
299	if (keys)	CFRelease(keys);
300	if (patterns)	CFRelease(patterns);
301	return KERN_SUCCESS;
302}
303