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