1/* 2 * Copyright (c) 2013 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 * EAPOLControlPrefs.c 26 * - definitions for accessing EAPOL preferences 27 */ 28 29/* 30 * Modification History 31 * 32 * January 9, 2013 Dieter Siegmund (dieter@apple) 33 * - created 34 */ 35 36#include <SystemConfiguration/SCPreferences.h> 37#include <SystemConfiguration/SCPrivate.h> 38#include <SystemConfiguration/scprefs_observer.h> 39#include <TargetConditionals.h> 40#include "EAPOLControlPrefs.h" 41#include "symbol_scope.h" 42#include "myCFUtil.h" 43 44/* 45 * kEAPOLClientPrefsID 46 * - identifies the eapolclient preferences file that contains 47 * LogFlags and other control variables 48 */ 49#define kEAPOLClientPrefsID CFSTR("com.apple.eapolclient.plist") 50 51 52/* 53 * kEAPOLControlPrefsID, kEAPOLControlPrefsIDStr 54 * - identifies the managed preferences ID used to apply control 55 * settings on iOS via configuration profile 56 */ 57 58#define kEAPOLControlPrefsIDStr "com.apple.eapol.control.plist" 59#define kEAPOLControlPrefsID CFSTR(kEAPOLControlPrefsIDStr) 60 61/* 62 * kLogFlags 63 * - indicates how verbose the eapolclient logging will be 64 */ 65#define kLogFlags CFSTR("LogFlags") 66 67STATIC SCPreferencesRef S_prefs; 68STATIC EAPOLControlPrefsCallBack S_callback; 69 70STATIC SCPreferencesRef 71EAPOLControlPrefsGet(void) 72{ 73 if (S_prefs == NULL) { 74 EAPOLControlPrefsInit(NULL, NULL); 75 } 76 return (S_prefs); 77} 78 79STATIC void 80prefs_changed(__unused void * arg) 81{ 82 if (S_callback != NULL) { 83 (*S_callback)(S_prefs); 84 } 85 return; 86} 87 88#if TARGET_OS_EMBEDDED 89/* 90 * kEAPOLControlManangedPrefsID 91 * - identifies the location of the managed preferences file 92 */ 93#define kManagedPrefsDirStr "/Library/Managed Preferences/mobile/" 94#define kEAPOLControlManagedPrefsID CFSTR(kManagedPrefsDirStr \ 95 kEAPOLControlPrefsIDStr) 96STATIC SCPreferencesRef S_managed_prefs; 97 98STATIC SCPreferencesRef 99EAPOLControlManagedPrefsGet(void) 100{ 101 if (S_managed_prefs == NULL) { 102 S_managed_prefs 103 = SCPreferencesCreate(NULL, CFSTR("EAPOLControlPrefs"), 104 kEAPOLControlManagedPrefsID); 105 } 106 return (S_managed_prefs); 107} 108 109STATIC void 110enable_prefs_observer(CFRunLoopRef runloop) 111{ 112 CFRunLoopSourceContext context; 113 dispatch_block_t handler; 114 CFRunLoopSourceRef source; 115 dispatch_queue_t queue; 116 117 bzero(&context, sizeof(context)); 118 context.perform = prefs_changed; 119 source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); 120 CFRunLoopAddSource(runloop, source, kCFRunLoopCommonModes); 121 queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 122 handler = ^{ 123 if (source != NULL) { 124 CFRunLoopSourceSignal(source); 125 if (runloop != NULL) { 126 CFRunLoopWakeUp(runloop); 127 } 128 }; 129 }; 130 (void)_scprefs_observer_watch(scprefs_observer_type_global, 131 kEAPOLControlPrefsIDStr, 132 queue, handler); 133 return; 134} 135 136#else /* TARGET_OS_EMBEDDED */ 137 138STATIC void 139enable_prefs_observer(CFRunLoopRef runloop) 140{ 141 return; 142} 143 144#endif /* TARGET_OS_EMBEDDED */ 145 146EXTERN void 147EAPOLControlPrefsSynchronize(void) 148{ 149 if (S_prefs != NULL) { 150 SCPreferencesSynchronize(S_prefs); 151 } 152#if TARGET_OS_EMBEDDED 153 if (S_managed_prefs != NULL) { 154 SCPreferencesSynchronize(S_managed_prefs); 155 } 156#endif /* TARGET_OS_EMBEDDED */ 157 return; 158} 159 160STATIC void 161EAPOLControlPrefsChanged(SCPreferencesRef prefs, SCPreferencesNotification type, 162 void * info) 163{ 164 prefs_changed(NULL); 165 return; 166} 167 168EXTERN SCPreferencesRef 169EAPOLControlPrefsInit(CFRunLoopRef runloop, EAPOLControlPrefsCallBack callback) 170{ 171 S_prefs = SCPreferencesCreate(NULL, CFSTR("EAPOLControlPrefs"), 172 kEAPOLClientPrefsID); 173 if (runloop != NULL && callback != NULL) { 174 S_callback = callback; 175 SCPreferencesSetCallback(S_prefs, EAPOLControlPrefsChanged, NULL); 176 SCPreferencesScheduleWithRunLoop(S_prefs, runloop, 177 kCFRunLoopCommonModes); 178 enable_prefs_observer(runloop); 179 } 180 return (S_prefs); 181} 182 183STATIC Boolean 184EAPOLControlPrefsSave(void) 185{ 186 Boolean saved = FALSE; 187 188 if (S_prefs != NULL) { 189 saved = SCPreferencesCommitChanges(S_prefs); 190 SCPreferencesSynchronize(S_prefs); 191 } 192 return (saved); 193} 194 195STATIC CFNumberRef 196prefs_get_number(CFStringRef key) 197{ 198 CFNumberRef num = NULL; 199 200#if TARGET_OS_EMBEDDED 201 num = SCPreferencesGetValue(EAPOLControlManagedPrefsGet(), key); 202 num = isA_CFNumber(num); 203#endif /* TARGET_OS_EMBEDDED */ 204 if (num == NULL) { 205 num = SCPreferencesGetValue(EAPOLControlPrefsGet(), key); 206 num = isA_CFNumber(num); 207 } 208 return (num); 209} 210 211STATIC void 212prefs_set_number(CFStringRef key, CFNumberRef num) 213{ 214 SCPreferencesRef prefs = EAPOLControlPrefsGet(); 215 216 if (prefs != NULL) { 217 if (isA_CFNumber(num) == NULL) { 218 SCPreferencesRemoveValue(prefs, key); 219 } 220 else { 221 SCPreferencesSetValue(prefs, key, num); 222 } 223 } 224 return; 225} 226 227/** 228 ** Get 229 **/ 230EXTERN uint32_t 231EAPOLControlPrefsGetLogFlags(void) 232{ 233 CFNumberRef num; 234 uint32_t ret_value = 0; 235 236 num = prefs_get_number(kLogFlags); 237 if (num != NULL) { 238 CFNumberGetValue(num, kCFNumberSInt32Type, &ret_value); 239 } 240 return (ret_value); 241} 242 243/** 244 ** Set 245 **/ 246EXTERN Boolean 247EAPOLControlPrefsSetLogFlags(uint32_t flags) 248{ 249 if (flags == 0) { 250 prefs_set_number(kLogFlags, NULL); 251 } 252 else { 253 CFNumberRef num; 254 255 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &flags); 256 prefs_set_number(kLogFlags, num); 257 my_CFRelease(&num); 258 } 259 return (EAPOLControlPrefsSave()); 260} 261