2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <pthread/pthread.h>
26 #include "server_security_helpers.h"
27 #include "server_entitlement_helpers.h"
29 #include <Security/SecTask.h>
30 #include <Security/SecTaskPriv.h>
31 #include <ipc/securityd_client.h>
32 #include <Security/SecEntitlements.h>
33 #include <Security/SecItem.h>
34 #include <utilities/SecCFRelease.h>
35 #include <utilities/SecCFWrappers.h>
36 #include <utilities/debugging.h>
37 #include <securityd/SecDbQuery.h>
39 #if __has_include(<MobileKeyBag/MobileKeyBag.h>) && TARGET_HAS_KEYSTORE
40 #include <MobileKeyBag/MobileKeyBag.h>
41 #define HAVE_MOBILE_KEYBAG_SUPPORT 1
44 #if HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_EMBEDDED
46 device_is_multiuser(void)
48 static dispatch_once_t once
;
51 dispatch_once(&once
, ^{
52 CFDictionaryRef deviceMode
= MKBUserTypeDeviceMode(NULL
, NULL
);
53 CFTypeRef value
= NULL
;
55 if (deviceMode
&& CFDictionaryGetValueIfPresent(deviceMode
, kMKBDeviceModeKey
, &value
) && CFEqual(value
, kMKBDeviceModeMultiUser
)) {
58 CFReleaseNull(deviceMode
);
63 #endif /* HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_EMBEDDED */
65 void fill_security_client(SecurityClient
* client
, const uid_t uid
, audit_token_t auditToken
) {
72 #if HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_EMBEDDED
74 if (device_is_multiuser()) {
75 CFErrorRef error
= NULL
;
77 client
->inMultiUser
= true;
78 client
->activeUser
= MKBForegroundUserSessionID(&error
);
79 if (client
->activeUser
== -1 || client
->activeUser
== 0) {
81 client
->activeUser
= 0;
85 * If we are a edu mode user, and its not the active user,
86 * then the request is coming from inside the syncbubble.
88 * otherwise we are going to execute the request as the
92 if (client
->uid
> 501 && (uid_t
)client
->activeUser
!= client
->uid
) {
93 secinfo("serverxpc", "securityd client: sync bubble user");
94 client
->musr
= SecMUSRCreateSyncBubbleUserUUID(client
->uid
);
95 client
->keybag
= KEYBAG_DEVICE
;
97 secinfo("serverxpc", "securityd client: active user");
98 client
->musr
= SecMUSRCreateActiveUserUUID(client
->activeUser
);
99 client
->uid
= (uid_t
)client
->activeUser
;
100 client
->keybag
= KEYBAG_DEVICE
;
105 client
->task
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
107 client
->accessGroups
= SecTaskCopyAccessGroups(client
->task
);
110 client
->allowSystemKeychain
= SecTaskGetBooleanValueForEntitlement(client
->task
, kSecEntitlementPrivateSystemKeychain
);
111 client
->isNetworkExtension
= SecTaskGetBooleanValueForEntitlement(client
->task
, kSecEntitlementPrivateNetworkExtension
);
112 client
->canAccessNetworkExtensionAccessGroups
= SecTaskGetBooleanValueForEntitlement(client
->task
, kSecEntitlementNetworkExtensionAccessGroups
);
114 #if HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_EMBEDDED
115 if (client
->inMultiUser
) {
116 client
->allowSyncBubbleKeychain
= SecTaskGetBooleanValueForEntitlement(client
->task
, kSecEntitlementPrivateKeychainSyncBubble
);