#include <Security/CodeSigning.h>
#include <Security/SecCodePriv.h>
#include <xpc/xpc.h>
#include <sandbox.h>
#include <security_utilities/cfutilities.h>
#include <security_utilities/cfmunge.h>
#include <security_utilities/logging.h>
#include "codedirectory.h"
static void
request(xpc_connection_t peer, xpc_object_t event)
{
pid_t pid = (pid_t)xpc_dictionary_get_int64(event, "pid");
if (pid <= 0)
return;
size_t audit_size;
audit_token_t const *audit =
(audit_token_t const *)xpc_dictionary_get_data(event, "audit", &audit_size);
if (audit != NULL && audit_size != sizeof(audit_token_t)) {
Syslog::error("audit token has unexpected size %zu", audit_size);
return;
}
xpc_object_t reply = xpc_dictionary_create_reply(event);
if (reply == NULL)
return;
CFTemp<CFMutableDictionaryRef> attributes("{%O=%d}", kSecGuestAttributePid, pid);
if (audit != NULL) {
CFRef<CFDataRef> auditData = makeCFData(audit, audit_size);
CFDictionaryAddValue(attributes.get(), kSecGuestAttributeAudit,
auditData);
}
CFRef<SecCodeRef> code;
if (SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref()) == noErr) {
CFRef<CFURLRef> codePath;
if (SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref()) == noErr) {
CFRef<CFDataRef> data = CFURLCreateData(NULL, codePath, kCFStringEncodingUTF8, true);
xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data));
}
size_t iphLength;
if (const void *iphash = xpc_dictionary_get_data(event, "infohash", &iphLength)) {
if (CFRef<CFDataRef> data = SecCodeCopyComponent(code, Security::CodeSigning::cdInfoSlot, CFTempData(iphash, iphLength))) {
xpc_dictionary_set_data(reply, "infoPlist", CFDataGetBytePtr(data), CFDataGetLength(data));
}
}
}
xpc_connection_send_message(peer, reply);
xpc_release(reply);
}
static void CodeSigningHelper_peer_event_handler(xpc_connection_t peer, xpc_object_t event)
{
xpc_type_t type = xpc_get_type(event);
if (type == XPC_TYPE_ERROR)
return;
assert(type == XPC_TYPE_DICTIONARY);
const char *cmd = xpc_dictionary_get_string(event, "command");
if (cmd == NULL) {
xpc_connection_cancel(peer);
} else if (strcmp(cmd, "fetchData") == 0)
request(peer, event);
else {
Syslog::error("peer sent invalid command %s", cmd);
xpc_connection_cancel(peer);
}
}
static void CodeSigningHelper_event_handler(xpc_connection_t peer)
{
xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
CodeSigningHelper_peer_event_handler(peer, event);
});
xpc_connection_resume(peer);
}
int main(int argc, const char *argv[])
{
char *error = NULL;
if (sandbox_init("com.apple.CodeSigningHelper", SANDBOX_NAMED, &error)) {
Syslog::error("failed to enter sandbox: %s", error);
exit(EXIT_FAILURE);
}
xpc_main(CodeSigningHelper_event_handler);
return 0;
}