1/*
2 * Copyright (c) 2000, 2001, 2003-2005, 2007-2009, 2011, 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 * November 9, 2000		Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34#include <SystemConfiguration/SystemConfiguration.h>
35#include <SystemConfiguration/SCPrivate.h>
36#include "SCPreferencesInternal.h"
37#include "SCNetworkConfigurationInternal.h"
38
39#include <fcntl.h>
40#include <pwd.h>
41#include <unistd.h>
42#include <sys/errno.h>
43#include <sys/param.h>
44
45__private_extern__ CF_RETURNS_RETAINED CFDataRef
46__SCPSignatureFromStatbuf(const struct stat *statBuf)
47{
48	CFMutableDataRef	signature;
49	SCPSignatureDataRef	sig;
50
51	signature = CFDataCreateMutable(NULL, sizeof(SCPSignatureData));
52	CFDataSetLength(signature, sizeof(SCPSignatureData));
53
54	/* ALIGN: CFDataGetBytePtr aligns to at least 8 bytes */
55	sig = (SCPSignatureDataRef)(void *)CFDataGetBytePtr(signature);
56
57	sig->st_dev       = statBuf->st_dev;
58	sig->st_ino       = statBuf->st_ino;
59	sig->tv_sec       = statBuf->st_mtimespec.tv_sec;
60	sig->tv_nsec      = statBuf->st_mtimespec.tv_nsec;
61	sig->st_size      = statBuf->st_size;
62	return signature;
63}
64
65
66__private_extern__ char *
67__SCPreferencesPath(CFAllocatorRef	allocator,
68		    CFStringRef		prefsID,
69		    Boolean		useNewPrefs)
70{
71	CFStringRef	path		= NULL;
72	char		*pathStr;
73
74	if (prefsID == NULL) {
75		/* default preference ID */
76		path = CFStringCreateWithFormat(allocator,
77						NULL,
78						CFSTR("%@/%@"),
79						useNewPrefs ? PREFS_DEFAULT_DIR    : PREFS_DEFAULT_DIR_OLD,
80						useNewPrefs ? PREFS_DEFAULT_CONFIG : PREFS_DEFAULT_CONFIG_OLD);
81	} else if (CFStringHasPrefix(prefsID, CFSTR("/"))) {
82		/* if absolute path */
83		path = CFStringCreateCopy(allocator, prefsID);
84	} else {
85		/* relative path */
86		path = CFStringCreateWithFormat(allocator,
87						NULL,
88						CFSTR("%@/%@"),
89						useNewPrefs ? PREFS_DEFAULT_DIR : PREFS_DEFAULT_DIR_OLD,
90						prefsID);
91		if (useNewPrefs && CFStringHasSuffix(path, CFSTR(".xml"))) {
92			CFMutableStringRef	newPath;
93
94			newPath = CFStringCreateMutableCopy(allocator, 0, path);
95			CFStringReplace(newPath,
96					CFRangeMake(CFStringGetLength(newPath)-4, 4),
97					CFSTR(".plist"));
98			CFRelease(path);
99			path = newPath;
100		}
101	}
102
103	/*
104	 * convert CFStringRef path to C-string path
105	 */
106	pathStr = _SC_cfstring_to_cstring(path, NULL, 0, kCFStringEncodingASCII);
107	if (pathStr == NULL) {
108		CFIndex pathLen;
109
110		pathLen = CFStringGetMaximumSizeOfFileSystemRepresentation(path);
111		pathStr = CFAllocatorAllocate(NULL, pathLen, 0);
112		if (CFStringGetFileSystemRepresentation(path, pathStr, pathLen) == FALSE) {
113			SCLog(_sc_verbose, LOG_DEBUG, CFSTR("could not convert path to C string"));
114			CFAllocatorDeallocate(NULL, pathStr);
115			pathStr = NULL;
116		}
117	}
118
119	CFRelease(path);
120	return pathStr;
121}
122
123
124__private_extern__
125Boolean
126__SCPreferencesGetLimitSCNetworkConfiguration(SCPreferencesRef prefs)
127{
128	SCPreferencesPrivateRef	prefsPrivate	= (SCPreferencesPrivateRef)prefs;
129
130	if (prefs == NULL) {
131		return FALSE;
132	}
133	return prefsPrivate->limit_SCNetworkConfiguration;
134}
135
136
137__private_extern__
138Boolean
139__SCPreferencesUsingDefaultPrefs(SCPreferencesRef prefs)
140{
141	char			*curPath;
142	Boolean			isDefault = FALSE;
143	SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
144
145	curPath = prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path;
146	if (curPath != NULL) {
147		char*	defPath;
148
149		defPath = __SCPreferencesPath(NULL,
150					      NULL,
151					      (prefsPrivate->newPath == NULL));
152		if (defPath != NULL) {
153			if (strcmp(curPath, defPath) == 0) {
154				isDefault = TRUE;
155			}
156			CFAllocatorDeallocate(NULL, defPath);
157		}
158	}
159	return isDefault;
160}
161
162__private_extern__
163SCPreferencesRef
164__SCPreferencesCreateNIPrefsFromPrefs(SCPreferencesRef prefs)
165{
166	CFMutableStringRef newPath = NULL;
167	CFURLRef newURL = NULL;
168	SCPreferencesRef ni_prefs = NULL;
169	SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
170	char * prefsPath = __SCPreferencesPath(NULL, prefsPrivate->prefsID, FALSE);
171
172
173	newPath = CFStringCreateMutable(NULL, 0);
174	CFStringAppendFormat(newPath, NULL, CFSTR("%s"), prefsPath);
175
176	CFStringFindAndReplace(newPath, PREFS_DEFAULT_CONFIG,
177			       NETWORK_INTERFACES_PREFS,
178			       CFRangeMake(0, CFStringGetLength(newPath)),
179			       kCFCompareBackwards);
180
181	newURL = CFURLCreateWithFileSystemPath(NULL, newPath, kCFURLPOSIXPathStyle, FALSE);
182	if (CFURLResourceIsReachable(newURL, NULL) == FALSE) {
183		ni_prefs = __SCNetworkCreateDefaultNIPrefs(newPath);
184	}
185	else {
186		ni_prefs = SCPreferencesCreate(NULL, prefsPrivate->name, newPath);
187	}
188	CFAllocatorDeallocate(NULL, prefsPath);
189	CFRelease(newPath);
190	CFRelease(newURL);
191
192	return ni_prefs;
193}
194
195CFDataRef
196SCPreferencesGetSignature(SCPreferencesRef prefs)
197{
198	SCPreferencesPrivateRef	prefsPrivate	= (SCPreferencesPrivateRef)prefs;
199
200	if (prefs == NULL) {
201		/* sorry, you must provide a session */
202		_SCErrorSet(kSCStatusNoPrefsSession);
203		return NULL;
204	}
205
206	__SCPreferencesAccess(prefs);
207
208	return prefsPrivate->signature;
209}
210
211
212__private_extern__ CF_RETURNS_RETAINED CFStringRef
213_SCPNotificationKey(CFAllocatorRef	allocator,
214		    CFStringRef		prefsID,
215		    int			keyType)
216{
217	CFStringRef	keyStr;
218	char		*path;
219	CFStringRef	pathStr;
220	CFStringRef	storeKey;
221
222	switch (keyType) {
223		case kSCPreferencesKeyLock :
224			keyStr = CFSTR("lock");
225			break;
226		case kSCPreferencesKeyCommit :
227			keyStr = CFSTR("commit");
228			break;
229		case kSCPreferencesKeyApply :
230			keyStr = CFSTR("apply");
231			break;
232		default :
233			return NULL;
234	}
235
236	path = __SCPreferencesPath(allocator, prefsID, TRUE);
237	if (path == NULL) {
238		return NULL;
239	}
240
241	pathStr = CFStringCreateWithCStringNoCopy(allocator,
242						  path,
243						  kCFStringEncodingASCII,
244						  kCFAllocatorNull);
245
246	storeKey = CFStringCreateWithFormat(allocator,
247					    NULL,
248					    CFSTR("%@%@:%@"),
249					    kSCDynamicStoreDomainPrefs,
250					    keyStr,
251					    pathStr);
252
253	CFRelease(pathStr);
254	CFAllocatorDeallocate(NULL, path);
255	return storeKey;
256}
257
258
259CFStringRef
260SCDynamicStoreKeyCreatePreferences(CFAllocatorRef	allocator,
261				   CFStringRef		prefsID,
262				   SCPreferencesKeyType	keyType)
263{
264	return _SCPNotificationKey(allocator, prefsID, keyType);
265}
266
267
268__private_extern__ void
269__SCPreferencesSetLimitSCNetworkConfiguration(SCPreferencesRef	prefs,
270					      Boolean		limit_SCNetworkConfiguration)
271{
272	SCPreferencesPrivateRef	prefsPrivate	= (SCPreferencesPrivateRef)prefs;
273
274	if (prefs == NULL) {
275		return;
276	}
277	prefsPrivate->limit_SCNetworkConfiguration = limit_SCNetworkConfiguration;
278}
279