server_entitlement_helpers.c [plain text]
#include <pthread/pthread.h>
#include "server_entitlement_helpers.h"
#include <Security/SecTask.h>
#include <Security/SecTaskPriv.h>
#include "ipc/securityd_client.h"
#include <Security/SecEntitlements.h>
#include "sectask/SystemEntitlements.h"
#include <Security/SecItem.h>
#include "utilities/SecCFRelease.h"
#include "utilities/SecCFWrappers.h"
#include "utilities/debugging.h"
#include <os/feature_private.h>
CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task,
CFStringRef entitlement)
{
CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task,
entitlement, NULL);
if (value && CFGetTypeID(value) != CFStringGetTypeID()) {
CFReleaseNull(value);
}
return value;
}
CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task,
CFStringRef entitlement)
{
CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task,
entitlement, NULL);
if (value) {
if (CFGetTypeID(value) == CFArrayGetTypeID()) {
CFIndex ix, count = CFArrayGetCount(value);
for (ix = 0; ix < count; ++ix) {
CFStringRef string = (CFStringRef)CFArrayGetValueAtIndex(value, ix);
if (CFGetTypeID(string) != CFStringGetTypeID()) {
CFReleaseNull(value);
break;
}
}
} else {
CFReleaseNull(value);
}
}
return value;
}
CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) {
CFStringRef result = SecTaskCopyStringForEntitlement(task,
kSecEntitlementBasicApplicationIdentifier);
if (!result) {
result = SecTaskCopyStringForEntitlement(task,
kSecEntitlementAppleApplicationIdentifier);
}
return result;
}
#if TARGET_OS_IOS
CFArrayRef SecTaskCopySharedWebCredentialDomains(SecTaskRef task) {
return SecTaskCopyArrayOfStringsForEntitlement(task,
kSecEntitlementAssociatedDomains);
}
#endif
CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task)
{
CFMutableArrayRef groups = NULL;
bool onDemandInstallable = SecTaskGetBooleanValueForEntitlement(task, kSystemEntitlementOnDemandInstallCapable);
CFArrayRef keychainAccessGroups, appleSecurityApplicationGroups;
CFStringRef appID;
CFArrayRef associatedAppIDs;
keychainAccessGroups = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementKeychainAccessGroups);
appleSecurityApplicationGroups = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementAppleSecurityApplicationGroups);
appID = SecTaskCopyApplicationIdentifier(task);
associatedAppIDs = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementAssociatedApplicationIdentifier);
groups = CFArrayCreateMutableForCFTypes(NULL);
if (keychainAccessGroups) {
CFArrayAppendArray(groups, keychainAccessGroups, CFRangeMake(0, CFArrayGetCount(keychainAccessGroups)));
}
#if TARGET_OS_OSX
const bool entitlementsValidated = SecTaskEntitlementsValidated(task);
#else
const bool entitlementsValidated = true;
#endif
if (entitlementsValidated) {
if (associatedAppIDs) {
CFArrayAppendAll(groups, associatedAppIDs);
}
if (appID) {
CFArrayAppendValue(groups, appID);
}
if (appleSecurityApplicationGroups) {
if (onDemandInstallable) {
secnotice("entitlements", "Ignoring \"%@\" because client is API-restricted", kSecEntitlementAppleSecurityApplicationGroups);
} else {
CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, CFArrayGetCount(appleSecurityApplicationGroups)));
}
}
} else {
if (CFArrayGetCount(groups) == 0) {
if (appID) {
secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile",
kSecEntitlementApplicationIdentifier, appID);
}
if (appleSecurityApplicationGroups) {
secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile",
kSecEntitlementAppleSecurityApplicationGroups, appleSecurityApplicationGroups);
}
}
}
CFIndex index = CFArrayGetFirstIndexOfValue(groups, CFRangeMake(0, CFArrayGetCount(groups)), kSecAttrAccessGroupToken);
if (index != kCFNotFound) {
if (os_feature_enabled(CryptoTokenKit, UseTokens)) {
CFArrayRemoveValueAtIndex(groups, index);
CFArrayAppendValue(groups, kSecAttrAccessGroupToken);
} else {
secwarning("Keychain access group com.apple.token ignored, feature not available");
CFArrayRemoveValueAtIndex(groups, index);
}
}
#if TARGET_OS_OSX
bool entitlementsFailure = (CFArrayGetCount(groups) == 0 && appID != NULL);
if (!entitlementsFailure) {
bool addTokenGroup = os_feature_enabled(CryptoTokenKit, UseTokens);
if (addTokenGroup && !CFArrayContainsValue(groups, CFRangeMake(0, CFArrayGetCount(groups)), kSecAttrAccessGroupToken)) {
CFArrayAppendValue(groups, kSecAttrAccessGroupToken);
}
}
#endif
CFReleaseNull(associatedAppIDs);
CFReleaseNull(appID);
CFReleaseNull(keychainAccessGroups);
CFReleaseNull(appleSecurityApplicationGroups);
return groups;
}
bool
SecTaskGetBooleanValueForEntitlement(SecTaskRef task, CFStringRef entitlement)
{
CFTypeRef value = SecTaskCopyValueForEntitlement(task, entitlement, NULL);
bool ok = false;
if (value && CFBooleanGetTypeID() == CFGetTypeID(value)) {
ok = CFBooleanGetValue(value);
}
CFReleaseNull(value);
return ok;
}