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_entitlement_helpers.h"
28 #include <Security/SecTask.h>
29 #include <Security/SecTaskPriv.h>
30 #include "ipc/securityd_client.h"
31 #include <Security/SecEntitlements.h>
32 #include <Security/SecItem.h>
33 #include "utilities/SecCFRelease.h"
34 #include "utilities/SecCFWrappers.h"
35 #include "utilities/debugging.h"
37 CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
38 CFStringRef entitlement
)
40 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
42 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
49 CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
50 CFStringRef entitlement
)
52 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
55 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
56 CFIndex ix
, count
= CFArrayGetCount(value
);
57 for (ix
= 0; ix
< count
; ++ix
) {
58 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
59 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
72 CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
73 return SecTaskCopyStringForEntitlement(task
,
74 kSecEntitlementApplicationIdentifier
);
78 CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
79 return SecTaskCopyArrayOfStringsForEntitlement(task
,
80 kSecEntitlementAssociatedDomains
);
84 CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
)
86 CFMutableArrayRef groups
= NULL
;
88 CFArrayRef keychainAccessGroups
, appleSecurityApplicationGroups
;
90 CFArrayRef associatedAppIDs
;
92 keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
, kSecEntitlementKeychainAccessGroups
);
93 appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
, kSecEntitlementAppleSecurityApplicationGroups
);
94 appID
= SecTaskCopyApplicationIdentifier(task
);
95 // Marzipan apps (may?) have this entitlement.
96 associatedAppIDs
= SecTaskCopyArrayOfStringsForEntitlement(task
, kSecEntitlementAssociatedApplicationIdentifier
);
98 groups
= CFArrayCreateMutableForCFTypes(NULL
);
100 if (keychainAccessGroups
) {
101 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, CFArrayGetCount(keychainAccessGroups
)));
105 const bool entitlementsValidated
= SecTaskEntitlementsValidated(task
);
107 const bool entitlementsValidated
= true;
110 if (entitlementsValidated
) {
111 // If app-id or k-a-g are present but binary is not validated, just honor k-a-g.
112 // Because AMFI would not allow client to run if it would have k-a-g entitlement
113 // and not being properly signed. Assoc-app-id behaves similarly.
114 if (associatedAppIDs
) {
115 CFArrayAppendAll(groups
, associatedAppIDs
);
118 CFArrayAppendValue(groups
, appID
);
120 if (appleSecurityApplicationGroups
) {
121 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, CFArrayGetCount(appleSecurityApplicationGroups
)));
124 // Try to provide some hopefully helpful diagnostics for common failure cases.
125 if (CFArrayGetCount(groups
) == 0) {
127 secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile",
128 kSecEntitlementApplicationIdentifier
, appID
);
130 if (appleSecurityApplicationGroups
) {
131 secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile",
132 kSecEntitlementAppleSecurityApplicationGroups
, appleSecurityApplicationGroups
);
138 * We would like to add implicit token access group always, but we avoid doing that in case that application
139 * clearly intended to use non-smartcard functionality of keychain but messed up signing or provisioning. In this case,
140 * we want to return -34018 (errSecMissingEntitlements) to help diagnosing the issue for the app authors and adding
141 * implicit token access group would instead result in errSecItemNotFound.
143 bool entitlementsFailure
= (CFArrayGetCount(groups
) == 0 && appID
!= NULL
);
144 if (!entitlementsFailure
) {
145 CFArrayAppendValue(groups
, kSecAttrAccessGroupToken
);
148 CFReleaseNull(associatedAppIDs
);
149 CFReleaseNull(appID
);
150 CFReleaseNull(keychainAccessGroups
);
151 CFReleaseNull(appleSecurityApplicationGroups
);
157 SecTaskGetBooleanValueForEntitlement(SecTaskRef task
, CFStringRef entitlement
)
159 CFTypeRef value
= SecTaskCopyValueForEntitlement(task
, entitlement
, NULL
);
162 if (value
&& CFBooleanGetTypeID() == CFGetTypeID(value
)) {
163 ok
= CFBooleanGetValue(value
);
165 CFReleaseNull(value
);