1/*
2 * Copyright (c) 2000-2005, 2009, 2011 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 * May 1, 2003			Allan Nathanson <ajn@apple.com>
28 * - add console [session] information SPIs
29 *
30 * June 1, 2001			Allan Nathanson <ajn@apple.com>
31 * - public API conversion
32 *
33 * January 2, 2001		Allan Nathanson <ajn@apple.com>
34 * - initial revision
35 */
36
37#include <SystemConfiguration/SystemConfiguration.h>
38#include <SystemConfiguration/SCValidation.h>
39#include <SystemConfiguration/SCPrivate.h>
40
41
42#undef	kSCPropUsersConsoleUserName
43#define	kSCPropUsersConsoleUserName	CFSTR("Name")
44
45#undef	kSCPropUsersConsoleUserUID
46#define	kSCPropUsersConsoleUserUID	CFSTR("UID")
47
48#undef	kSCPropUsersConsoleUserGID
49#define	kSCPropUsersConsoleUserGID	CFSTR("GID")
50
51#undef	kSCPropUsersConsoleSessionInfo
52#define	kSCPropUsersConsoleSessionInfo	CFSTR("SessionInfo")
53
54
55// from CoreGraphics (CGSession.h)
56const CFStringRef kSCConsoleSessionUserName		= CFSTR("kCGSSessionUserNameKey");		/* value is CFString */
57const CFStringRef kSCConsoleSessionUID			= CFSTR("kCGSSessionUserIDKey");		/* value is CFNumber (a uid_t) */
58const CFStringRef kSCConsoleSessionConsoleSet		= CFSTR("kCGSSessionConsoleSetKey");		/* value is CFNumber */
59const CFStringRef kSCConsoleSessionOnConsole		= CFSTR("kCGSSessionOnConsoleKey");		/* value is CFBoolean */
60const CFStringRef kSCConsoleSessionLoginDone		= CFSTR("kCGSessionLoginDoneKey");		/* value is CFBoolean */
61
62// from CoreGraphics (CGSSession.h)
63const CFStringRef kSCConsoleSessionID			= CFSTR("kCGSSessionIDKey");			/* value is CFNumber */
64
65// for loginwindow
66const CFStringRef kSCConsoleSessionSystemSafeBoot	= CFSTR("kCGSSessionSystemSafeBoot");		/* value is CFBoolean */
67const CFStringRef kSCConsoleSessionLoginwindowSafeLogin	= CFSTR("kCGSSessionLoginwindowSafeLogin");	/* value is CFBoolean */
68
69
70CFStringRef
71SCDynamicStoreKeyCreateConsoleUser(CFAllocatorRef allocator)
72{
73	return SCDynamicStoreKeyCreate(allocator,
74				       CFSTR("%@/%@/%@"),
75				       kSCDynamicStoreDomainState,
76				       kSCCompUsers,
77				       kSCEntUsersConsoleUser);
78}
79
80
81CFStringRef
82SCDynamicStoreCopyConsoleUser(SCDynamicStoreRef	store,
83			      uid_t		*uid,
84			      gid_t		*gid)
85{
86	CFStringRef		consoleUser	= NULL;
87	CFDictionaryRef		dict		= NULL;
88	CFStringRef		key;
89
90	key  = SCDynamicStoreKeyCreateConsoleUser(NULL);
91	dict = SCDynamicStoreCopyValue(store, key);
92	CFRelease(key);
93	if (!isA_CFDictionary(dict)) {
94		_SCErrorSet(kSCStatusNoKey);
95		goto done;
96	}
97
98	consoleUser = CFDictionaryGetValue(dict, kSCPropUsersConsoleUserName);
99	consoleUser = isA_CFString(consoleUser);
100	if (!consoleUser) {
101		_SCErrorSet(kSCStatusNoKey);
102		goto done;
103	}
104
105	CFRetain(consoleUser);
106
107	if (uid) {
108		CFNumberRef	num;
109		SInt32		val;
110
111		num = CFDictionaryGetValue(dict, kSCPropUsersConsoleUserUID);
112		if (isA_CFNumber(num)) {
113			if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) {
114				*uid = (uid_t)val;
115			}
116		}
117	}
118
119	if (gid) {
120		CFNumberRef	num;
121		SInt32		val;
122
123		num = CFDictionaryGetValue(dict, kSCPropUsersConsoleUserGID);
124		if (isA_CFNumber(num)) {
125			if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) {
126				*gid = (gid_t)val;
127			}
128		}
129	}
130
131    done :
132
133	if (dict)		CFRelease(dict);
134	return consoleUser;
135}
136
137
138CFArrayRef
139SCDynamicStoreCopyConsoleInformation(SCDynamicStoreRef store)
140{
141	CFDictionaryRef		dict		= NULL;
142	CFArrayRef		info		= NULL;
143	CFStringRef		key;
144
145	key  = SCDynamicStoreKeyCreateConsoleUser(NULL);
146	dict = SCDynamicStoreCopyValue(store, key);
147	CFRelease(key);
148	if (!isA_CFDictionary(dict)) {
149		_SCErrorSet(kSCStatusNoKey);
150		goto done;
151	}
152
153	info = CFDictionaryGetValue(dict, kSCPropUsersConsoleSessionInfo);
154	info = isA_CFArray(info);
155	if (!info) {
156		_SCErrorSet(kSCStatusNoKey);
157		goto done;
158	}
159
160	CFRetain(info);
161
162    done :
163
164	if (dict)		CFRelease(dict);
165	return info;
166}
167
168
169Boolean
170SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef	store,
171				    const char		*user,
172				    uid_t		uid,
173				    gid_t		gid,
174				    CFArrayRef		sessions)
175{
176	CFStringRef		consoleUser;
177	CFMutableDictionaryRef	dict		= NULL;
178	CFStringRef		key		= SCDynamicStoreKeyCreateConsoleUser(NULL);
179	Boolean			ok		= FALSE;
180
181	if ((user == NULL) && (sessions == NULL)) {
182		ok = SCDynamicStoreRemoveValue(store, key);
183		goto done;
184	}
185
186	dict = CFDictionaryCreateMutable(NULL,
187					 0,
188					 &kCFTypeDictionaryKeyCallBacks,
189					 &kCFTypeDictionaryValueCallBacks);
190
191	if (user != NULL) {
192		CFNumberRef	num;
193
194		consoleUser = CFStringCreateWithCString(NULL, user, kCFStringEncodingMacRoman);
195		CFDictionarySetValue(dict, kSCPropUsersConsoleUserName, consoleUser);
196		CFRelease(consoleUser);
197
198		num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&uid);
199		CFDictionarySetValue(dict, kSCPropUsersConsoleUserUID, num);
200		CFRelease(num);
201
202		num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&gid);
203		CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num);
204		CFRelease(num);
205	}
206
207	if (sessions != NULL) {
208		CFDictionarySetValue(dict, kSCPropUsersConsoleSessionInfo, sessions);
209	}
210
211	ok = SCDynamicStoreSetValue(store, key, dict);
212
213    done :
214
215	if (dict)		CFRelease(dict);
216	if (key)		CFRelease(key);
217	return ok;
218}
219
220
221Boolean
222SCDynamicStoreSetConsoleUser(SCDynamicStoreRef	store,
223			     const char		*user,
224			     uid_t		uid,
225			     gid_t		gid)
226{
227	CFStringRef		consoleUser;
228	CFMutableDictionaryRef	dict		= NULL;
229	CFStringRef		key		= SCDynamicStoreKeyCreateConsoleUser(NULL);
230	CFNumberRef		num;
231	Boolean			ok		= FALSE;
232
233	if (user == NULL) {
234		ok = SCDynamicStoreRemoveValue(store, key);
235		goto done;
236	}
237
238	dict = CFDictionaryCreateMutable(NULL,
239					 0,
240					 &kCFTypeDictionaryKeyCallBacks,
241					 &kCFTypeDictionaryValueCallBacks);
242
243	consoleUser = CFStringCreateWithCString(NULL, user, kCFStringEncodingMacRoman);
244	CFDictionarySetValue(dict, kSCPropUsersConsoleUserName, consoleUser);
245	CFRelease(consoleUser);
246
247	num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&uid);
248	CFDictionarySetValue(dict, kSCPropUsersConsoleUserUID, num);
249	CFRelease(num);
250
251	num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&gid);
252	CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num);
253	CFRelease(num);
254
255	ok = SCDynamicStoreSetValue(store, key, dict);
256
257    done :
258
259	if (dict)		CFRelease(dict);
260	if (key)		CFRelease(key);
261	return ok;
262}
263