]> git.saurik.com Git - apple/configd.git/blame - configd.tproj/session.c
configd-802.40.13.tar.gz
[apple/configd.git] / configd.tproj / session.c
CommitLineData
5958d7c0 1/*
9de8ab86 2 * Copyright (c) 2000, 2001, 2003-2005, 2007-2015 Apple Inc. All rights reserved.
5958d7c0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
9de8ab86 5 *
009ee3c6
A
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.
9de8ab86 12 *
009ee3c6
A
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
5958d7c0
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
009ee3c6
A
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.
9de8ab86 20 *
5958d7c0
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
0fae82ee
A
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
5e9ce69e 34#include <SystemConfiguration/SystemConfiguration.h>
5958d7c0
A
35#include "configd.h"
36#include "configd_server.h"
5e9ce69e 37#include "pattern.h"
5958d7c0
A
38#include "session.h"
39
a40a14f8
A
40#include <unistd.h>
41#include <bsm/libbsm.h>
6bb65964
A
42#include <sandbox.h>
43
6f870c06
A
44#if !TARGET_IPHONE_SIMULATOR || (defined(IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED) && (IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED >= 1090))
45#define HAVE_MACHPORT_GUARDS
46#endif
47
a40a14f8 48
5958d7c0 49/* information maintained for each active session */
17d3ee29
A
50static serverSessionRef *sessions = NULL;
51static int nSessions = 0; /* # of allocated sessions */
52static int lastSession = -1; /* # of last used session */
5958d7c0 53
6bb65964
A
54/* CFMachPortInvalidation runloop */
55static CFRunLoopRef sessionRunLoop = NULL;
56
17d3ee29
A
57/* temp session */
58static serverSessionRef temp_session = NULL;
59
6bb65964 60
009ee3c6 61__private_extern__
5958d7c0
A
62serverSessionRef
63getSession(mach_port_t server)
64{
65 int i;
66
67 if (server == MACH_PORT_NULL) {
9de8ab86 68 SC_log(LOG_NOTICE, "Excuse me, why is getSession() being called with an invalid port?");
5958d7c0
A
69 return NULL;
70 }
71
17d3ee29
A
72 /* look for matching session (note: slot 0 is the "server" port) */
73 for (i = 1; i <= lastSession; i++) {
009ee3c6
A
74 serverSessionRef thisSession = sessions[i];
75
76 if (thisSession == NULL) {
77 /* found an empty slot, skip it */
78 continue;
17d3ee29
A
79 }
80
81 if (thisSession->key == server) {
82 /* we've seen this server before */
83 return thisSession;
84 }
85
86 if ((thisSession->store != NULL) &&
87 (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) {
88 /* we've seen this task port before */
009ee3c6 89 return thisSession;
5958d7c0
A
90 }
91 }
92
93 /* no sessions available */
94 return NULL;
95}
96
97
17d3ee29
A
98__private_extern__
99serverSessionRef
100tempSession(mach_port_t server, CFStringRef name, audit_token_t auditToken)
101{
102 static dispatch_once_t once;
103 SCDynamicStorePrivateRef storePrivate;
104
105 if (sessions[0]->key != server) {
106 // if not SCDynamicStore "server" port
107 return NULL;
108 }
109
110 dispatch_once(&once, ^{
111 temp_session = sessions[0]; /* use "server" session */
112 (void) __SCDynamicStoreOpen(&temp_session->store, NULL);
113 });
114
5e9ce69e
A
115 /* save audit token, caller entitlements */
116 temp_session->auditToken = auditToken;
117 temp_session->callerEUID = 1; /* not "root" */
118 temp_session->callerRootAccess = UNKNOWN;
5e9ce69e
A
119 if ((temp_session->callerWriteEntitlement != NULL) &&
120 (temp_session->callerWriteEntitlement != kCFNull)) {
121 CFRelease(temp_session->callerWriteEntitlement);
122 }
123 temp_session->callerWriteEntitlement = kCFNull; /* UNKNOWN */
17d3ee29
A
124
125 /* save name */
126 storePrivate = (SCDynamicStorePrivateRef)temp_session->store;
127 if (storePrivate->name != NULL) CFRelease(storePrivate->name);
128 storePrivate->name = CFRetain(name);
129
130 return temp_session;
131}
132
133
009ee3c6 134__private_extern__
5958d7c0 135serverSessionRef
be997540 136addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info))
5958d7c0 137{
6f870c06
A
138 CFMachPortContext context = { 0, NULL, NULL, NULL, NULL };
139 kern_return_t kr;
140 mach_port_t mp = server;
141 int n = -1;
142 serverSessionRef newSession = NULL;
6bb65964
A
143
144 /* save current (SCDynamicStore) runloop */
145 if (sessionRunLoop == NULL) {
146 sessionRunLoop = CFRunLoopGetCurrent();
147 }
5958d7c0
A
148
149 if (nSessions <= 0) {
17d3ee29
A
150 /* if first session (the "server" port) */
151 n = 0; /* use slot "0" */
152 lastSession = 0; /* last used slot */
153
154 nSessions = 64;
155 sessions = malloc(nSessions * sizeof(serverSessionRef));
6f870c06
A
156
157 // allocate a new session for "the" server
158 newSession = calloc(1, sizeof(serverSession));
5958d7c0 159 } else {
6f870c06
A
160 int i;
161#ifdef HAVE_MACHPORT_GUARDS
162 mach_port_options_t opts;
163#endif // HAVE_MACHPORT_GUARDS
be997540 164
17d3ee29
A
165 /* check to see if we already have an open session (note: slot 0 is the "server" port) */
166 for (i = 1; i <= lastSession; i++) {
6f870c06 167 serverSessionRef thisSession = sessions[i];
17d3ee29
A
168
169 if (thisSession == NULL) {
170 /* found an empty slot */
171 if (n < 0) {
172 /* keep track of the first [empty] slot */
173 n = i;
174 }
175
176 /* and keep looking for a matching session */
177 continue;
178 }
179
180 if (thisSession->key == server) {
181 /* we've seen this server before */
182 return NULL;
183 }
184
185 if ((thisSession->store != NULL) &&
186 (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) {
187 /* we've seen this task port before */
188 return NULL;
5958d7c0
A
189 }
190 }
17d3ee29
A
191
192 /* add a new session */
5958d7c0 193 if (n < 0) {
17d3ee29
A
194 /* if no empty slots */
195 n = ++lastSession;
196 if (lastSession >= nSessions) {
197 /* expand the session list */
198 nSessions *= 2;
199 sessions = reallocf(sessions, (nSessions * sizeof(serverSessionRef)));
200 }
5958d7c0 201 }
17d3ee29 202
6f870c06
A
203 // allocate a session for this client
204 newSession = calloc(1, sizeof(serverSession));
205
17d3ee29
A
206 // create mach port for SCDynamicStore client
207 mp = MACH_PORT_NULL;
5958d7c0 208
6f870c06
A
209 retry_allocate :
210
211#ifdef HAVE_MACHPORT_GUARDS
212 bzero(&opts, sizeof(opts));
213 opts.flags = MPO_CONTEXT_AS_GUARD;
214
215 kr = mach_port_construct(mach_task_self(), &opts, newSession, &mp);
216#else // HAVE_MACHPORT_GUARDS
217 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp);
218#endif // HAVE_MACHPORT_GUARDS
219
220 if (kr != KERN_SUCCESS) {
221 char *err = NULL;
222
9de8ab86 223 SC_log(LOG_NOTICE, "could not allocate mach port: %s", mach_error_string(kr));
6f870c06
A
224 if ((kr == KERN_NO_SPACE) || (kr == KERN_RESOURCE_SHORTAGE)) {
225 sleep(1);
226 goto retry_allocate;
227 }
228
9de8ab86
A
229 (void) asprintf(&err, "Could not allocate mach port: %s", mach_error_string(kr));
230 _SC_crash(err != NULL ? err : "Could not allocate new session (mach) port",
6f870c06
A
231 NULL,
232 NULL);
233 if (err != NULL) free(err);
234
235 free(newSession);
236 return NULL;
237 }
238 }
be997540
A
239
240 // create server port
6f870c06 241 context.info = newSession;
17d3ee29 242 context.copyDescription = copyDescription;
a40a14f8
A
243
244 //
245 // Note: we create the CFMachPort *before* we insert a send
246 // right present to ensure that CF does not establish
247 // its dead name notification.
248 //
6f870c06
A
249 newSession->serverPort = _SC_CFMachPortCreateWithPort("SCDynamicStore/session",
250 mp,
251 configdCallback,
252 &context);
6bb65964 253
17d3ee29 254 if (n > 0) {
a40a14f8 255 // insert send right that will be moved to the client
6f870c06
A
256 kr = mach_port_insert_right(mach_task_self(),
257 mp,
258 mp,
259 MACH_MSG_TYPE_MAKE_SEND);
260 if (kr != KERN_SUCCESS) {
261 /*
262 * We can't insert a send right into our own port! This should
263 * only happen if someone stomped on OUR port (so let's leave
264 * the port alone).
265 */
9de8ab86 266 SC_log(LOG_NOTICE, "mach_port_insert_right() failed: %s", mach_error_string(kr));
6f870c06
A
267
268 free(newSession);
269 return NULL;
270 }
be997540 271 }
a40a14f8 272
6f870c06 273 sessions[n] = newSession;
5e9ce69e
A
274 sessions[n]->key = mp;
275// sessions[n]->serverRunLoopSource = NULL;
276// sessions[n]->store = NULL;
277 sessions[n]->callerEUID = 1; /* not "root" */
278 sessions[n]->callerRootAccess = UNKNOWN;
5e9ce69e 279 sessions[n]->callerWriteEntitlement = kCFNull; /* UNKNOWN */
5958d7c0 280
6f870c06 281 return newSession;
5958d7c0
A
282}
283
284
009ee3c6 285__private_extern__
5958d7c0 286void
17d3ee29 287cleanupSession(mach_port_t server)
5958d7c0 288{
17d3ee29 289 int i;
5958d7c0 290
17d3ee29
A
291 for (i = 1; i <= lastSession; i++) {
292 CFStringRef sessionKey;
293 serverSessionRef thisSession = sessions[i];
5958d7c0
A
294
295 if (thisSession == NULL) {
296 /* found an empty slot, skip it */
297 continue;
5958d7c0 298 }
5958d7c0 299
17d3ee29 300 if (thisSession->key == server) {
5958d7c0
A
301 /*
302 * session entry still exists.
303 */
304
9de8ab86 305 SC_trace(_configd_trace, "cleanup : %5d\n", server);
009ee3c6 306
5958d7c0
A
307 /*
308 * Close any open connections including cancelling any outstanding
309 * notification requests and releasing any locks.
310 */
a40a14f8 311 __MACH_PORT_DEBUG(TRUE, "*** cleanupSession", server);
17d3ee29 312 (void) __SCDynamicStoreClose(&thisSession->store);
a40a14f8 313 __MACH_PORT_DEBUG(TRUE, "*** cleanupSession (after __SCDynamicStoreClose)", server);
5958d7c0 314
be997540 315 /*
a40a14f8 316 * Our send right has already been removed. Remove our receive right.
be997540 317 */
6f870c06
A
318#ifdef HAVE_MACHPORT_GUARDS
319 (void) mach_port_destruct(mach_task_self(), server, 0, thisSession);
320#else // HAVE_MACHPORT_GUARDS
a40a14f8 321 (void) mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_RECEIVE, -1);
6f870c06 322#endif // HAVE_MACHPORT_GUARDS
a40a14f8 323
5e9ce69e
A
324 /*
325 * release any entitlement info
326 */
327 if ((thisSession->callerWriteEntitlement != NULL) &&
328 (thisSession->callerWriteEntitlement != kCFNull)) {
329 CFRelease(thisSession->callerWriteEntitlement);
330 }
5e9ce69e 331
5958d7c0 332 /*
17d3ee29
A
333 * We don't need any remaining information in the
334 * sessionData dictionary, remove it.
335 */
336 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), server);
337 CFDictionaryRemoveValue(sessionData, sessionKey);
338 CFRelease(sessionKey);
339
340 /*
341 * get rid of the per-session structure.
5958d7c0 342 */
17d3ee29
A
343 free(thisSession);
344 sessions[i] = NULL;
345
346 if (i == lastSession) {
347 /* we are removing the last session, update last used slot */
348 while (--lastSession > 0) {
349 if (sessions[lastSession] != NULL) {
350 break;
351 }
352 }
353 }
5958d7c0
A
354
355 return;
356 }
357 }
a40a14f8 358
9de8ab86 359 SC_log(LOG_NOTICE, "MACH_NOTIFY_NO_SENDERS w/no session, port = %d", server);
a40a14f8 360 __MACH_PORT_DEBUG(TRUE, "*** cleanupSession w/no session", server);
5958d7c0
A
361 return;
362}
363
364
009ee3c6 365__private_extern__
5958d7c0 366void
a40a14f8 367listSessions(FILE *f)
5958d7c0
A
368{
369 int i;
370
a40a14f8 371 SCPrint(TRUE, f, CFSTR("Current sessions :\n"));
17d3ee29 372 for (i = 0; i <= lastSession; i++) {
5958d7c0
A
373 serverSessionRef thisSession = sessions[i];
374
375 if (thisSession == NULL) {
376 continue;
377 }
378
a40a14f8
A
379 SCPrint(TRUE, f, CFSTR("\t%d : port = 0x%x"), i, thisSession->key);
380
381 if (thisSession->store != NULL) {
382 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)thisSession->store;
383
384 if (storePrivate->notifySignalTask != TASK_NULL) {
385 SCPrint(TRUE, f, CFSTR(", task = %d"), storePrivate->notifySignalTask);
386 }
387 }
388
389 if (sessionData != NULL) {
390 CFDictionaryRef info;
391 CFStringRef key;
392
393 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), thisSession->key);
394 info = CFDictionaryGetValue(sessionData, key);
395 CFRelease(key);
396 if (info != NULL) {
397 CFStringRef name;
398
399 name = CFDictionaryGetValue(info, kSCDName);
400 if (name != NULL) {
401 SCPrint(TRUE, f, CFSTR(", name = %@"), name);
402 }
403 }
404 }
405
406 if (thisSession->serverPort != NULL) {
407 SCPrint(TRUE, f, CFSTR("\n\t\t%@"), thisSession->serverPort);
408 }
409
410 if (thisSession->serverRunLoopSource != NULL) {
411 SCPrint(TRUE, f, CFSTR("\n\t\t%@"), thisSession->serverRunLoopSource);
412 }
413
414 SCPrint(TRUE, f, CFSTR("\n"));
415 }
416
417 SCPrint(TRUE, f, CFSTR("\n"));
418 return;
419}
420
421
a40a14f8
A
422#include <Security/Security.h>
423#include <Security/SecTask.h>
5958d7c0 424
a40a14f8
A
425static CFStringRef
426sessionName(serverSessionRef session)
427{
428 CFDictionaryRef info;
429 CFStringRef name = NULL;
430 CFStringRef sessionKey;
431
432 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), session->key);
433 info = CFDictionaryGetValue(sessionData, sessionKey);
434 CFRelease(sessionKey);
435
436 if (info != NULL) {
437 name = CFDictionaryGetValue(info, kSCDName);
438 }
5958d7c0 439
a40a14f8
A
440 return (name != NULL) ? name : CFSTR("???");
441}
442
5e9ce69e
A
443static CFTypeRef
444copyEntitlement(serverSessionRef session, CFStringRef entitlement)
a40a14f8 445{
a40a14f8 446 SecTaskRef task;
5e9ce69e 447 CFTypeRef value = NULL;
a40a14f8 448
5e9ce69e 449 // Create the security task from the audit token
a40a14f8
A
450 task = SecTaskCreateWithAuditToken(NULL, session->auditToken);
451 if (task != NULL) {
452 CFErrorRef error = NULL;
a40a14f8 453
5e9ce69e 454 // Get the value for the entitlement
6bb65964 455 value = SecTaskCopyValueForEntitlement(task, entitlement, &error);
5e9ce69e
A
456 if ((value == NULL) && (error != NULL)) {
457 CFIndex code = CFErrorGetCode(error);
458 CFStringRef domain = CFErrorGetDomain(error);
459
460 if (!CFEqual(domain, kCFErrorDomainMach) ||
461 ((code != kIOReturnInvalid) && (code != kIOReturnNotFound))) {
462 // if unexpected error
9de8ab86
A
463 SC_log(LOG_NOTICE, "SecTaskCopyValueForEntitlement(,\"%@\",) failed, error = %@ : %@",
464 entitlement,
465 error,
466 sessionName(session));
5958d7c0 467 }
a40a14f8 468 CFRelease(error);
5958d7c0 469 }
a40a14f8
A
470
471 CFRelease(task);
472 } else {
9de8ab86
A
473 SC_log(LOG_NOTICE, "SecTaskCreateWithAuditToken() failed: %@",
474 sessionName(session));
5958d7c0 475 }
a40a14f8 476
5e9ce69e 477 return value;
5958d7c0
A
478}
479
5e9ce69e
A
480
481static pid_t
482sessionPid(serverSessionRef session)
483{
484 pid_t caller_pid;
485
486#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
487 caller_pid = audit_token_to_pid(session->auditToken);
488#else // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
489 audit_token_to_au32(session->auditToken,
490 NULL, // auidp
491 NULL, // euid
492 NULL, // egid
493 NULL, // ruid
494 NULL, // rgid
495 &caller_pid, // pid
496 NULL, // asid
497 NULL); // tid
498#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
499
500 return caller_pid;
501}
a40a14f8
A
502
503
504__private_extern__
505Boolean
506hasRootAccess(serverSessionRef session)
507{
5e9ce69e
A
508#if !TARGET_IPHONE_SIMULATOR
509
a40a14f8 510 if (session->callerRootAccess == UNKNOWN) {
5e9ce69e
A
511#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
512 session->callerEUID = audit_token_to_euid(session->auditToken);
513#else // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
a40a14f8
A
514 audit_token_to_au32(session->auditToken,
515 NULL, // auidp
516 &session->callerEUID, // euid
517 NULL, // egid
518 NULL, // ruid
519 NULL, // rgid
520 NULL, // pid
521 NULL, // asid
522 NULL); // tid
5e9ce69e 523#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
a40a14f8
A
524 session->callerRootAccess = (session->callerEUID == 0) ? YES : NO;
525 }
526
527 return (session->callerRootAccess == YES) ? TRUE : FALSE;
5e9ce69e
A
528
529#else // !TARGET_IPHONE_SIMULATOR
530
531 /*
532 * assume that all processes interacting with
533 * the iOS Simulator "configd" are OK.
534 */
535 return TRUE;
536
537#endif // !TARGET_IPHONE_SIMULATOR
a40a14f8
A
538}
539
540
541__private_extern__
542Boolean
5e9ce69e 543hasWriteAccess(serverSessionRef session, CFStringRef key)
a40a14f8 544{
5e9ce69e 545 Boolean isSetup;
a40a14f8 546
5e9ce69e
A
547 // need to special case writing "Setup:" keys
548 isSetup = CFStringHasPrefix(key, kSCDynamicStoreDomainSetup);
549
550 if (hasRootAccess(session)) {
551 pid_t pid;
552
553 // grant write access to eUID==0 processes
554
555 pid = sessionPid(session);
556 if (isSetup && (pid != getpid())) {
557 /*
558 * WAIT!!!
559 *
560 * This is NOT configd (or a plugin) trying to
561 * write to an SCDynamicStore "Setup:" key. In
562 * general, this is unwise and we should at the
563 * very least complain.
564 */
9de8ab86
A
565 SC_log(LOG_NOTICE, "*** Non-configd process (pid=%d) attempting to modify \"%@\" ***",
566 pid,
567 key);
a40a14f8 568 }
5e9ce69e
A
569
570 return TRUE;
571 }
572
573 if (isSetup) {
574 /*
575 * STOP!!!
576 *
577 * This is a non-root process trying to write to
578 * an SCDynamicStore "Setup:" key. This is not
579 * something we should ever allow (regardless of
580 * any entitlements).
581 */
9de8ab86
A
582 SC_log(LOG_NOTICE, "*** Non-root process (pid=%d) attempting to modify \"%@\" ***",
583 sessionPid(session),
584 key);
5e9ce69e
A
585
586 //return FALSE; // return FALSE when rdar://9811832 has beed fixed
587 }
588
5e9ce69e
A
589 if (session->callerWriteEntitlement == kCFNull) {
590 session->callerWriteEntitlement = copyEntitlement(session,
591 kSCWriteEntitlementName);
592 }
593
594 if (session->callerWriteEntitlement == NULL) {
595 return FALSE;
596 }
597
598 if (isA_CFBoolean(session->callerWriteEntitlement) &&
599 CFBooleanGetValue(session->callerWriteEntitlement)) {
600 // grant write access to "entitled" processes
601 return TRUE;
602 }
603
604 if (isA_CFDictionary(session->callerWriteEntitlement)) {
605 CFArrayRef keys;
606 CFArrayRef patterns;
607
608 keys = CFDictionaryGetValue(session->callerWriteEntitlement, CFSTR("keys"));
609 if (isA_CFArray(keys)) {
610 if (CFArrayContainsValue(keys,
611 CFRangeMake(0, CFArrayGetCount(keys)),
612 key)) {
613 // if key matches one of the entitlement "keys", grant
614 // write access
615 return TRUE;
616 }
617 }
618
619 patterns = CFDictionaryGetValue(session->callerWriteEntitlement, CFSTR("patterns"));
620 if (isA_CFArray(patterns)) {
621 CFIndex i;
622 CFIndex n = CFArrayGetCount(patterns);
623
624 for (i = 0; i < n; i++) {
625 CFStringRef pattern;
626
627 pattern = CFArrayGetValueAtIndex(patterns, i);
628 if (isA_CFString(pattern)) {
629 if (patternKeyMatches(pattern, key)) {
630 // if key matches one of the entitlement
631 // "patterns", grant write access
632 return TRUE;
633 }
634 }
635 }
a40a14f8 636 }
a40a14f8
A
637 }
638
5e9ce69e 639 return FALSE;
a40a14f8 640}
6bb65964
A
641
642
643__private_extern__
644Boolean
645hasPathAccess(serverSessionRef session, const char *path)
646{
647 pid_t pid;
648 char realPath[PATH_MAX];
649
650 if (realpath(path, realPath) == NULL) {
9de8ab86 651 SC_log(LOG_INFO, "realpath() failed: %s", strerror(errno));
6bb65964
A
652 return FALSE;
653 }
654
5e9ce69e
A
655#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
656 pid = audit_token_to_pid(session->auditToken);
657#else // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
6bb65964
A
658 audit_token_to_au32(session->auditToken,
659 NULL, // auidp
660 NULL, // euid
661 NULL, // egid
662 NULL, // ruid
663 NULL, // rgid
664 &pid, // pid
665 NULL, // asid
666 NULL); // tid
5e9ce69e
A
667#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
668 if (sandbox_check(pid, // pid
669 "file-write-data", // operation
670 SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT, // sandbox_filter_type
671 realPath) > 0) { // ...
9de8ab86 672 SC_log(LOG_INFO, "sandbox access denied: %s", strerror(errno));
6bb65964
A
673 return FALSE;
674 }
675
676 return TRUE;
677}