Skip to content

Instantly share code, notes, and snippets.

@knightsc
Created February 20, 2019 19:45
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knightsc/9b3fba827317cbf980ad8e99d8a17c7f to your computer and use it in GitHub Desktop.
Save knightsc/9b3fba827317cbf980ad8e99d8a17c7f to your computer and use it in GitHub Desktop.
Example of how the Security.framework calls into `syspolicyd` for Gatekeeper functionality
#import <Foundation/Foundation.h>
#import <Security/Security.h>
#import <xpc/xpc.h>
#include <CoreFoundation/CoreFoundation.h>
#include <stdint.h>
typedef uint64_t SecAssessmentFlags;
enum {
kSecAssessmentDefaultFlags = 0, // default behavior
kSecAssessmentFlagDirect = 1 << 30, // in-process evaluation
kSecAssessmentFlagAsynchronous = 1 << 29, // request asynchronous operation
kSecAssessmentFlagIgnoreCache = 1 << 28, // do not search cache
kSecAssessmentFlagNoCache = 1 << 27, // do not populate cache
kSecAssessmentFlagEnforce = 1 << 26, // force on (disable bypass switches)
kSecAssessmentFlagAllowWeak = 1 << 25, // allow weak signatures
kSecAssessmentFlagIgnoreWhitelist = 1 << 24, // do not search weak signature whitelist
kSecAssessmentFlagDequarantine = 1 << 23,
// 1 << 23 removed (was kSecAssessmentFlagDequarantine)
kSecAssessmentFlagIgnoreActiveAssessments = 1 << 22, // permit parallel re-assessment of the same target
kSecAssessmentFlagLowPriority = 1 << 21, // run the assessment in low priority
};
static const char serviceName[] = "com.apple.security.syspolicy";
//static dispatch_once_t dispatchInit; // one-time init marker
static xpc_connection_t service; // connection to spd
static dispatch_queue_t queue; // dispatch queue for service
static void doProgress(xpc_object_t msg)
{
uint64_t current = xpc_dictionary_get_uint64(msg, "current");
uint64_t total = xpc_dictionary_get_uint64(msg, "total");
uint64_t ref = xpc_dictionary_get_uint64(msg, "ref");
const char *token = xpc_dictionary_get_string(msg, "token");
// Skip handling cancellations for now.
//
// SecAssessmentFeedback feedback = SecAssessmentFeedback(ref);
// CFTemp<CFDictionaryRef> info("{current=%d,total=%d}", current, total);
// Boolean proceed = feedback(kSecAssessmentFeedbackProgress, info);
// if (!proceed) {
// xpc_connection_t connection = xpc_dictionary_get_remote_connection(msg);
// xpc_object_t cancelRequest = xpc_dictionary_create(NULL, NULL, 0);
// xpc_dictionary_set_string(cancelRequest, "function", "cancel");
// xpc_dictionary_set_string(cancelRequest, "token", token);
// xpc_connection_send_message(connection, cancelRequest);
// xpc_release(cancelRequest);
// }
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
const char *name = serviceName;
queue = dispatch_queue_create("spd-client", 0);
service = xpc_connection_create_mach_service(name, queue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
xpc_connection_set_event_handler(service, ^(xpc_object_t msg) {
if (xpc_get_type(msg) == XPC_TYPE_DICTIONARY) {
const char *function = xpc_dictionary_get_string(msg, "function");
if (!strcmp(function, "progress")) {
doProgress(msg);
}
}
});
xpc_connection_resume(service);
xpc_object_t obj;
obj = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(obj, "function", "assess");
xpc_dictionary_set_string(obj, "path", [@"/bin/ls" UTF8String]);
xpc_dictionary_set_uint64(obj, "flags", 0);
// Leaving off context causes syspolicyd to crash
CFMutableDictionaryRef ctx = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// Set some values
CFDataRef contextData = CFPropertyListCreateData(NULL, ctx, kCFPropertyListXMLFormat_v1_0, 0, NULL);
xpc_dictionary_set_data(obj, "context", CFDataGetBytePtr(contextData), CFDataGetLength(contextData));
xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, obj);
obj = NULL;
xpc_type_t type = xpc_get_type(reply);
if (type == XPC_TYPE_DICTIONARY) {
obj = reply;
int64_t error = xpc_dictionary_get_int64(obj, "error");
if (error) {
printf("Error\n");
}
else {
size_t resultLength;
const void *resultData = xpc_dictionary_get_data(obj, "result", &resultLength);
CFDataRef tempData = CFDataCreate(NULL, (const UInt8 *)resultData, resultLength);
CFPropertyListRef plist = CFPropertyListCreateFromXMLData(NULL, tempData, kCFPropertyListImmutable, NULL);
}
} else if (type == XPC_TYPE_ERROR) {
const char *s = xpc_copy_description(reply);
printf("Error returned: %s\n", s);
printf("code signing internal problem: unexpected error from xpc: %s", s);
free((char*)s);
} else {
const char *s = xpc_copy_description(reply);
printf("Unexpected type of return object: %s\n", s);
free((char*)s);
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment