]> git.saurik.com Git - apple/configd.git/blame - configd.tproj/session.c
configd-699.30.1.tar.gz
[apple/configd.git] / configd.tproj / session.c
CommitLineData
5958d7c0 1/*
78403150 2 * Copyright (c) 2000, 2001, 2003-2005, 2007-2014 Apple Inc. All rights reserved.
5958d7c0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
009ee3c6 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.
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
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.
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) {
a40a14f8 68 SCLog(TRUE, LOG_ERR, CFSTR("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
223 SCLog(TRUE, LOG_ERR, CFSTR("addSession: could not allocate mach port: %s"), mach_error_string(kr));
224 if ((kr == KERN_NO_SPACE) || (kr == KERN_RESOURCE_SHORTAGE)) {
225 sleep(1);
226 goto retry_allocate;
227 }
228
229 (void) asprintf(&err, "addSession: could not allocate mach port: %s", mach_error_string(kr));
230 _SC_crash(err != NULL ? err : "addSession: could not allocate mach port",
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 */
266 SCLog(TRUE, LOG_ERR, CFSTR("addSession mach_port_insert_right(): %s"), mach_error_string(kr));
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
009ee3c6
A
305 if (_configd_trace) {
306 SCTrace(TRUE, _configd_trace, CFSTR("cleanup : %5d\n"), server);
307 }
308
5958d7c0
A
309 /*
310 * Close any open connections including cancelling any outstanding
311 * notification requests and releasing any locks.
312 */
a40a14f8 313 __MACH_PORT_DEBUG(TRUE, "*** cleanupSession", server);
17d3ee29 314 (void) __SCDynamicStoreClose(&thisSession->store);
a40a14f8 315 __MACH_PORT_DEBUG(TRUE, "*** cleanupSession (after __SCDynamicStoreClose)", server);
5958d7c0 316
be997540 317 /*
a40a14f8 318 * Our send right has already been removed. Remove our receive right.
be997540 319 */
6f870c06
A
320#ifdef HAVE_MACHPORT_GUARDS
321 (void) mach_port_destruct(mach_task_self(), server, 0, thisSession);
322#else // HAVE_MACHPORT_GUARDS
a40a14f8 323 (void) mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_RECEIVE, -1);
6f870c06 324#endif // HAVE_MACHPORT_GUARDS
a40a14f8 325
5e9ce69e
A
326 /*
327 * release any entitlement info
328 */
329 if ((thisSession->callerWriteEntitlement != NULL) &&
330 (thisSession->callerWriteEntitlement != kCFNull)) {
331 CFRelease(thisSession->callerWriteEntitlement);
332 }
5e9ce69e 333
5958d7c0 334 /*
17d3ee29
A
335 * We don't need any remaining information in the
336 * sessionData dictionary, remove it.
337 */
338 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), server);
339 CFDictionaryRemoveValue(sessionData, sessionKey);
340 CFRelease(sessionKey);
341
342 /*
343 * get rid of the per-session structure.
5958d7c0 344 */
17d3ee29
A
345 free(thisSession);
346 sessions[i] = NULL;
347
348 if (i == lastSession) {
349 /* we are removing the last session, update last used slot */
350 while (--lastSession > 0) {
351 if (sessions[lastSession] != NULL) {
352 break;
353 }
354 }
355 }
5958d7c0
A
356
357 return;
358 }
359 }
a40a14f8
A
360
361 SCLog(TRUE, LOG_ERR, CFSTR("MACH_NOTIFY_NO_SENDERS w/no session, port = %d"), server);
362 __MACH_PORT_DEBUG(TRUE, "*** cleanupSession w/no session", server);
5958d7c0
A
363 return;
364}
365
366
009ee3c6 367__private_extern__
5958d7c0 368void
a40a14f8 369listSessions(FILE *f)
5958d7c0
A
370{
371 int i;
372
a40a14f8 373 SCPrint(TRUE, f, CFSTR("Current sessions :\n"));
17d3ee29 374 for (i = 0; i <= lastSession; i++) {
5958d7c0
A
375 serverSessionRef thisSession = sessions[i];
376
377 if (thisSession == NULL) {
378 continue;
379 }
380
a40a14f8
A
381 SCPrint(TRUE, f, CFSTR("\t%d : port = 0x%x"), i, thisSession->key);
382
383 if (thisSession->store != NULL) {
384 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)thisSession->store;
385
386 if (storePrivate->notifySignalTask != TASK_NULL) {
387 SCPrint(TRUE, f, CFSTR(", task = %d"), storePrivate->notifySignalTask);
388 }
389 }
390
391 if (sessionData != NULL) {
392 CFDictionaryRef info;
393 CFStringRef key;
394
395 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), thisSession->key);
396 info = CFDictionaryGetValue(sessionData, key);
397 CFRelease(key);
398 if (info != NULL) {
399 CFStringRef name;
400
401 name = CFDictionaryGetValue(info, kSCDName);
402 if (name != NULL) {
403 SCPrint(TRUE, f, CFSTR(", name = %@"), name);
404 }
405 }
406 }
407
408 if (thisSession->serverPort != NULL) {
409 SCPrint(TRUE, f, CFSTR("\n\t\t%@"), thisSession->serverPort);
410 }
411
412 if (thisSession->serverRunLoopSource != NULL) {
413 SCPrint(TRUE, f, CFSTR("\n\t\t%@"), thisSession->serverRunLoopSource);
414 }
415
416 SCPrint(TRUE, f, CFSTR("\n"));
417 }
418
419 SCPrint(TRUE, f, CFSTR("\n"));
420 return;
421}
422
423
a40a14f8
A
424#include <Security/Security.h>
425#include <Security/SecTask.h>
5958d7c0 426
a40a14f8
A
427static CFStringRef
428sessionName(serverSessionRef session)
429{
430 CFDictionaryRef info;
431 CFStringRef name = NULL;
432 CFStringRef sessionKey;
433
434 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), session->key);
435 info = CFDictionaryGetValue(sessionData, sessionKey);
436 CFRelease(sessionKey);
437
438 if (info != NULL) {
439 name = CFDictionaryGetValue(info, kSCDName);
440 }
5958d7c0 441
a40a14f8
A
442 return (name != NULL) ? name : CFSTR("???");
443}
444
5e9ce69e
A
445static CFTypeRef
446copyEntitlement(serverSessionRef session, CFStringRef entitlement)
a40a14f8 447{
a40a14f8 448 SecTaskRef task;
5e9ce69e 449 CFTypeRef value = NULL;
a40a14f8 450
5e9ce69e 451 // Create the security task from the audit token
a40a14f8
A
452 task = SecTaskCreateWithAuditToken(NULL, session->auditToken);
453 if (task != NULL) {
454 CFErrorRef error = NULL;
a40a14f8 455
5e9ce69e 456 // Get the value for the entitlement
6bb65964 457 value = SecTaskCopyValueForEntitlement(task, entitlement, &error);
5e9ce69e
A
458 if ((value == NULL) && (error != NULL)) {
459 CFIndex code = CFErrorGetCode(error);
460 CFStringRef domain = CFErrorGetDomain(error);
461
462 if (!CFEqual(domain, kCFErrorDomainMach) ||
463 ((code != kIOReturnInvalid) && (code != kIOReturnNotFound))) {
464 // if unexpected error
a40a14f8 465 SCLog(TRUE, LOG_ERR,
5e9ce69e
A
466 CFSTR("SecTaskCopyValueForEntitlement(,\"%@\",) failed, error = %@ : %@"),
467 entitlement,
468 error,
a40a14f8 469 sessionName(session));
5958d7c0 470 }
a40a14f8 471 CFRelease(error);
5958d7c0 472 }
a40a14f8
A
473
474 CFRelease(task);
475 } else {
476 SCLog(TRUE, LOG_ERR,
5e9ce69e 477 CFSTR("SecTaskCreateWithAuditToken() failed: %@"),
a40a14f8 478 sessionName(session));
5958d7c0 479 }
a40a14f8 480
5e9ce69e 481 return value;
5958d7c0
A
482}
483
5e9ce69e
A
484
485static pid_t
486sessionPid(serverSessionRef session)
487{
488 pid_t caller_pid;
489
490#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
491 caller_pid = audit_token_to_pid(session->auditToken);
492#else // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
493 audit_token_to_au32(session->auditToken,
494 NULL, // auidp
495 NULL, // euid
496 NULL, // egid
497 NULL, // ruid
498 NULL, // rgid
499 &caller_pid, // pid
500 NULL, // asid
501 NULL); // tid
502#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
503
504 return caller_pid;
505}
a40a14f8
A
506
507
508__private_extern__
509Boolean
510hasRootAccess(serverSessionRef session)
511{
5e9ce69e
A
512#if !TARGET_IPHONE_SIMULATOR
513
a40a14f8 514 if (session->callerRootAccess == UNKNOWN) {
5e9ce69e
A
515#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
516 session->callerEUID = audit_token_to_euid(session->auditToken);
517#else // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
a40a14f8
A
518 audit_token_to_au32(session->auditToken,
519 NULL, // auidp
520 &session->callerEUID, // euid
521 NULL, // egid
522 NULL, // ruid
523 NULL, // rgid
524 NULL, // pid
525 NULL, // asid
526 NULL); // tid
5e9ce69e 527#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
a40a14f8
A
528 session->callerRootAccess = (session->callerEUID == 0) ? YES : NO;
529 }
530
531 return (session->callerRootAccess == YES) ? TRUE : FALSE;
5e9ce69e
A
532
533#else // !TARGET_IPHONE_SIMULATOR
534
535 /*
536 * assume that all processes interacting with
537 * the iOS Simulator "configd" are OK.
538 */
539 return TRUE;
540
541#endif // !TARGET_IPHONE_SIMULATOR
a40a14f8
A
542}
543
544
545__private_extern__
546Boolean
5e9ce69e 547hasWriteAccess(serverSessionRef session, CFStringRef key)
a40a14f8 548{
5e9ce69e 549 Boolean isSetup;
a40a14f8 550
5e9ce69e
A
551 // need to special case writing "Setup:" keys
552 isSetup = CFStringHasPrefix(key, kSCDynamicStoreDomainSetup);
553
554 if (hasRootAccess(session)) {
555 pid_t pid;
556
557 // grant write access to eUID==0 processes
558
559 pid = sessionPid(session);
560 if (isSetup && (pid != getpid())) {
561 /*
562 * WAIT!!!
563 *
564 * This is NOT configd (or a plugin) trying to
565 * write to an SCDynamicStore "Setup:" key. In
566 * general, this is unwise and we should at the
567 * very least complain.
568 */
569 SCLog(TRUE, LOG_ERR,
570 CFSTR("*** Non-configd process (pid=%d) attempting to modify \"%@\" ***"),
571 pid,
572 key);
a40a14f8 573 }
5e9ce69e
A
574
575 return TRUE;
576 }
577
578 if (isSetup) {
579 /*
580 * STOP!!!
581 *
582 * This is a non-root process trying to write to
583 * an SCDynamicStore "Setup:" key. This is not
584 * something we should ever allow (regardless of
585 * any entitlements).
586 */
587 SCLog(TRUE, LOG_ERR,
588 CFSTR("*** Non-root process (pid=%d) attempting to modify \"%@\" ***"),
589 sessionPid(session),
590 key);
591
592 //return FALSE; // return FALSE when rdar://9811832 has beed fixed
593 }
594
5e9ce69e
A
595 if (session->callerWriteEntitlement == kCFNull) {
596 session->callerWriteEntitlement = copyEntitlement(session,
597 kSCWriteEntitlementName);
598 }
599
600 if (session->callerWriteEntitlement == NULL) {
601 return FALSE;
602 }
603
604 if (isA_CFBoolean(session->callerWriteEntitlement) &&
605 CFBooleanGetValue(session->callerWriteEntitlement)) {
606 // grant write access to "entitled" processes
607 return TRUE;
608 }
609
610 if (isA_CFDictionary(session->callerWriteEntitlement)) {
611 CFArrayRef keys;
612 CFArrayRef patterns;
613
614 keys = CFDictionaryGetValue(session->callerWriteEntitlement, CFSTR("keys"));
615 if (isA_CFArray(keys)) {
616 if (CFArrayContainsValue(keys,
617 CFRangeMake(0, CFArrayGetCount(keys)),
618 key)) {
619 // if key matches one of the entitlement "keys", grant
620 // write access
621 return TRUE;
622 }
623 }
624
625 patterns = CFDictionaryGetValue(session->callerWriteEntitlement, CFSTR("patterns"));
626 if (isA_CFArray(patterns)) {
627 CFIndex i;
628 CFIndex n = CFArrayGetCount(patterns);
629
630 for (i = 0; i < n; i++) {
631 CFStringRef pattern;
632
633 pattern = CFArrayGetValueAtIndex(patterns, i);
634 if (isA_CFString(pattern)) {
635 if (patternKeyMatches(pattern, key)) {
636 // if key matches one of the entitlement
637 // "patterns", grant write access
638 return TRUE;
639 }
640 }
641 }
a40a14f8 642 }
a40a14f8
A
643 }
644
5e9ce69e 645 return FALSE;
a40a14f8 646}
6bb65964
A
647
648
649__private_extern__
650Boolean
651hasPathAccess(serverSessionRef session, const char *path)
652{
653 pid_t pid;
654 char realPath[PATH_MAX];
655
656 if (realpath(path, realPath) == NULL) {
657 SCLog(TRUE, LOG_DEBUG, CFSTR("hasPathAccess realpath() failed: %s"), strerror(errno));
658 return FALSE;
659 }
660
5e9ce69e
A
661#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
662 pid = audit_token_to_pid(session->auditToken);
663#else // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
6bb65964
A
664 audit_token_to_au32(session->auditToken,
665 NULL, // auidp
666 NULL, // euid
667 NULL, // egid
668 NULL, // ruid
669 NULL, // rgid
670 &pid, // pid
671 NULL, // asid
672 NULL); // tid
5e9ce69e
A
673#endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) && !TARGET_OS_IPHONE
674 if (sandbox_check(pid, // pid
675 "file-write-data", // operation
676 SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT, // sandbox_filter_type
677 realPath) > 0) { // ...
6bb65964
A
678 SCLog(TRUE, LOG_DEBUG, CFSTR("hasPathAccess sandbox access denied: %s"), strerror(errno));
679 return FALSE;
680 }
681
682 return TRUE;
683}