#include "SecTaskPriv.h"
#include <utilities/debugging.h>
+#include <utilities/entitlements.h>
#include <AssertMacros.h>
#include <CoreFoundation/CFRuntime.h>
#include <inttypes.h>
#include <syslog.h>
#include <utilities/SecCFWrappers.h>
+#include <xpc/private.h>
#include <sys/sysctl.h>
#if TARGET_OS_OSX
/* These won't exist until we unify codesigning */
-#include "SecCode.h"
-#include "SecCodePriv.h"
-#include "SecRequirement.h"
+#include <Security/SecCode.h>
+#include <Security/SecCodePriv.h>
+#include <Security/SecRequirement.h>
#endif /* TARGET_OS_OSX */
struct __SecTask {
return task;
}
+_Nullable SecTaskRef
+SecTaskCreateWithXPCMessage(xpc_object_t _Nonnull message)
+{
+ audit_token_t token;
+
+ if (message == NULL || xpc_get_type(message) != XPC_TYPE_DICTIONARY) {
+ return NULL;
+ }
+ xpc_dictionary_get_audit_token(message, &token);
+
+ return SecTaskCreateWithAuditToken(NULL, token);
+}
+
+
+
struct csheader {
uint32_t magic;
uint32_t length;
uint32_t bufferlen;
int ret;
-
ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, &header, sizeof(header));
/* Any other combination means no entitlements */
- if (ret == -1) {
- if (errno != ERANGE) {
+ if (ret == -1) {
+ if (errno != ERANGE) {
int entitlementErrno = errno;
- uint32_t cs_flags = -1;
+ uint32_t cs_flags = -1;
if (-1 == csops_task(task, CS_OPS_STATUS, &cs_flags, sizeof(cs_flags))) {
syslog(LOG_NOTICE, "Failed to get cs_flags, error=%d", errno);
}
- if (cs_flags != 0) { // was signed
-
- pid_t pid;
- audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
- syslog(LOG_NOTICE, "SecTaskLoadEntitlements failed error=%d cs_flags=%x, pid=%d", entitlementErrno, cs_flags, pid); // to ease diagnostics
-
- CFStringRef description = SecTaskCopyDebugDescription(task);
- char *descriptionBuf = NULL;
- CFIndex descriptionSize = CFStringGetLength(description) * 4;
- descriptionBuf = (char *)malloc(descriptionSize);
- if (!CFStringGetCString(description, descriptionBuf, descriptionSize, kCFStringEncodingUTF8)) {
- descriptionBuf[0] = 0;
- }
-
- syslog(LOG_NOTICE, "SecTaskCopyDebugDescription: %s", descriptionBuf);
- CFReleaseNull(description);
- free(descriptionBuf);
- }
- task->lastFailure = entitlementErrno; // was overwritten by csops_task(CS_OPS_STATUS) above
-
- // EINVAL is what the kernel says for unsigned code, so we'll have to let that pass
- if (entitlementErrno == EINVAL) {
- task->entitlementsLoaded = true;
- return true;
- }
- ret = entitlementErrno; // what really went wrong
- goto out; // bail out
- }
+ if (cs_flags != 0) { // was signed
+ pid_t pid;
+ audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
+ syslog(LOG_NOTICE, "SecTaskLoadEntitlements failed error=%d cs_flags=%x, pid=%d", entitlementErrno, cs_flags, pid); // to ease diagnostics
+
+ CFStringRef description = SecTaskCopyDebugDescription(task);
+ char *descriptionBuf = NULL;
+ CFIndex descriptionSize = CFStringGetLength(description) * 4;
+ descriptionBuf = (char *)malloc(descriptionSize);
+ if (!CFStringGetCString(description, descriptionBuf, descriptionSize, kCFStringEncodingUTF8)) {
+ descriptionBuf[0] = 0;
+ }
+
+ syslog(LOG_NOTICE, "SecTaskCopyDebugDescription: %s", descriptionBuf);
+ CFReleaseNull(description);
+ free(descriptionBuf);
+ }
+ task->lastFailure = entitlementErrno; // was overwritten by csops_task(CS_OPS_STATUS) above
+
+ // EINVAL is what the kernel says for unsigned code, so we'll have to let that pass
+ if (entitlementErrno == EINVAL) {
+ task->entitlementsLoaded = true;
+ return true;
+ }
+ ret = entitlementErrno; // what really went wrong
+ goto out; // bail out
+ }
bufferlen = ntohl(header.length);
/* check for insane values */
if (bufferlen > 1024 * 1024 || bufferlen < 8) {
entitlements = (CFMutableDictionaryRef) CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListMutableContainers, NULL, error);
CFReleaseNull(data);
- if((entitlements==NULL) || (CFGetTypeID(entitlements)!=CFDictionaryGetTypeID())){
+ if ((entitlements==NULL) || (CFGetTypeID(entitlements)!=CFDictionaryGetTypeID())){
ret = EDOM; // don't use EINVAL here; it conflates problems with syscall error returns
goto out;
}
+
+ bool entitlementsModified = updateCatalystEntitlements(entitlements);
+ if (entitlementsModified) {
+ pid_t pid;
+ audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
+ secinfo("SecTask", "Fixed catalyst entitlements for process %d", pid);
+ }
}
task->entitlements = entitlements ? CFRetain(entitlements) : NULL;
return values;
}
-#if TARGET_OS_OSX
+#if SEC_OS_OSX
/*
* Determine if the given task meets a specified requirement.
*/
return status;
}
-#endif /* TARGET_OS_OSX */
+#endif /* SEC_OS_OSX */
Boolean SecTaskEntitlementsValidated(SecTaskRef task) {
// TODO: Cache the result