]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCP.c
15d39f3d6140fc6e3fab14e2129333191a20e61a
[apple/configd.git] / SystemConfiguration.fproj / SCP.c
1 /*
2 * Copyright(c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1(the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 #include <SystemConfiguration/SystemConfiguration.h>
24 #include "SCPPrivate.h"
25
26 #include <fcntl.h>
27 #include <pwd.h>
28 #include <unistd.h>
29 #include <sys/errno.h>
30 #include <sys/param.h>
31
32
33 static const struct scp_errmsg {
34 SCPStatus status;
35 char *message;
36 } scp_errmsgs[] = {
37 { SCP_OK, "Success!" },
38 { SCP_BUSY, "Configuration daemon busy" },
39 { SCP_NEEDLOCK, "Lock required for this operation" },
40 { SCP_EACCESS, "Permission denied (must be root to obtain lock)" },
41 { SCP_ENOENT, "Configuration file not found" },
42 { SCP_BADCF, "Configuration file corrupt" },
43 { SCP_NOKEY, "No such key" },
44 { SCP_NOLINK, "No such link" },
45 { SCP_EXISTS, "Key already defined" },
46 { SCP_STALE, "Write attempted on stale version of object" },
47 { SCP_INVALIDARGUMENT, "Invalid argument" },
48 { SCP_FAILED, "Failed!" }
49 };
50 #define nSCP_ERRMSGS (sizeof(scp_errmsgs)/sizeof(struct scp_errmsg))
51
52
53 __private_extern__ CFDataRef
54 _SCPSignatureFromStatbuf(const struct stat *statBuf)
55 {
56 CFMutableDataRef signature;
57 SCPSignatureDataRef sig;
58
59 signature = CFDataCreateMutable(NULL, sizeof(SCPSignatureData));
60 CFDataSetLength(signature, sizeof(SCPSignatureData));
61 sig = (SCPSignatureDataRef)CFDataGetBytePtr(signature);
62 sig->st_dev = statBuf->st_dev;
63 sig->st_ino = statBuf->st_ino;
64 sig->st_mtimespec = statBuf->st_mtimespec;
65 sig->st_size = statBuf->st_size;
66 return signature;
67 }
68
69
70 __private_extern__ char *
71 _SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user)
72 {
73 CFStringRef path = NULL;
74 int pathLen;
75 char *pathStr;
76
77 if (perUser) {
78 if (prefsID == NULL) {
79 /* no user prefsID specified */
80 return NULL;
81 } else if (CFStringHasPrefix(prefsID, CFSTR("/"))) {
82 /* if absolute path */
83 path = CFRetain(prefsID);
84 } else {
85 /*
86 * relative (to the user's preferences) path
87 */
88 char login[MAXLOGNAME+1];
89 struct passwd *pwd;
90
91 bzero(&login, sizeof(login));
92 if (user == NULL) {
93 /* get current console user */
94 if (SCDConsoleUserGet(login,
95 MAXLOGNAME,
96 NULL,
97 NULL) != SCD_OK) {
98 /* if could not get console user */
99 return NULL;
100 }
101 } else {
102 /* use specified user */
103 (void)CFStringGetBytes(user,
104 CFRangeMake(0, CFStringGetLength(user)),
105 kCFStringEncodingMacRoman,
106 0,
107 FALSE,
108 login,
109 MAXLOGNAME,
110 NULL);
111 }
112
113 /* get password entry for user */
114 pwd = getpwnam(login);
115 if (pwd == NULL) {
116 /* if no home directory */
117 return NULL;
118 }
119
120 /* create prefs ID */
121 path = CFStringCreateWithFormat(NULL,
122 NULL,
123 CFSTR("%s/%@/%@"),
124 pwd->pw_dir,
125 PREFS_DEFAULT_USER_DIR,
126 prefsID);
127 }
128 } else {
129 if (prefsID == NULL) {
130 /* default preference ID */
131 path = CFStringCreateWithFormat(NULL,
132 NULL,
133 CFSTR("%@/%@"),
134 PREFS_DEFAULT_DIR,
135 PREFS_DEFAULT_CONFIG);
136 } else if (CFStringHasPrefix(prefsID, CFSTR("/"))) {
137 /* if absolute path */
138 path = CFRetain(prefsID);
139 } else {
140 /* relative path */
141 path = CFStringCreateWithFormat(NULL,
142 NULL,
143 CFSTR("%@/%@"),
144 PREFS_DEFAULT_DIR,
145 prefsID);
146 }
147 }
148
149 /*
150 * convert CFStringRef path to C-string path
151 */
152 pathLen = CFStringGetLength(path) + 1;
153 pathStr = CFAllocatorAllocate(NULL, pathLen, 0);
154 if (!CFStringGetCString(path,
155 pathStr,
156 pathLen,
157 kCFStringEncodingMacRoman)) {
158 SCDLog(LOG_DEBUG, CFSTR("could not convert path to C string"));
159 CFAllocatorDeallocate(NULL, pathStr);
160 pathStr = NULL;
161 }
162
163 CFRelease(path);
164 return pathStr;
165 }
166
167
168 SCPStatus
169 SCPGetSignature(SCPSessionRef session, CFDataRef *signature)
170 {
171 SCPSessionPrivateRef sessionPrivate;
172
173 if (session == NULL) {
174 return SCP_FAILED; /* you can't do anything with a closed session */
175 }
176 sessionPrivate = (SCPSessionPrivateRef)session;
177
178 *signature = sessionPrivate->signature;
179 return SCP_OK;
180 }
181
182
183 __private_extern__ CFStringRef
184 _SCPNotificationKey(CFStringRef prefsID,
185 boolean_t perUser,
186 CFStringRef user,
187 int keyType)
188 {
189 CFStringRef key = NULL;
190 char *pathStr;
191 char *typeStr;
192
193 pathStr = _SCPPrefsPath(prefsID, perUser, user);
194 if (pathStr == NULL) {
195 return NULL;
196 }
197
198 /* create notification key */
199 switch (keyType) {
200 case kSCPKeyLock :
201 typeStr = "lock";
202 break;
203 case kSCPKeyCommit :
204 typeStr = "commit";
205 break;
206 case kSCPKeyApply :
207 typeStr = "apply";
208 break;
209 default :
210 typeStr = "?";
211 }
212
213 key = CFStringCreateWithFormat(NULL,
214 NULL,
215 CFSTR("%@%s:%s"),
216 kSCCacheDomainPrefs,
217 typeStr,
218 pathStr);
219
220 CFAllocatorDeallocate(NULL, pathStr);
221 return key;
222 }
223
224
225 CFStringRef
226 SCPNotificationKeyCreate(CFStringRef prefsID, int keyType)
227 {
228 return _SCPNotificationKey(prefsID, FALSE, NULL, keyType);
229 }
230
231
232 CFStringRef
233 SCPUserNotificationKeyCreate(CFStringRef prefsID, CFStringRef user, int keyType)
234 {
235 return _SCPNotificationKey(prefsID, TRUE, user, keyType);
236 }
237
238
239 const char *
240 SCPError(SCPStatus status)
241 {
242 int i;
243
244 for (i = 0; i < nSCP_ERRMSGS; i++) {
245 if (scp_errmsgs[i].status == status) {
246 return scp_errmsgs[i].message;
247 }
248 }
249 return "(unknown error)";
250 }