main.cpp
1 /* 2 * Copyright (c) 2016 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 #include <Security/CodeSigning.h> 24 #include <Security/SecCodePriv.h> 25 #include <xpc/xpc.h> 26 #include <sandbox.h> 27 #include <security_utilities/cfutilities.h> 28 #include <security_utilities/cfmunge.h> 29 #include <security_utilities/logging.h> 30 #include "codedirectory.h" 31 32 33 34 static void 35 request(xpc_connection_t peer, xpc_object_t event) 36 { 37 pid_t pid = (pid_t)xpc_dictionary_get_int64(event, "pid"); 38 if (pid <= 0) 39 return; 40 41 size_t audit_size; 42 audit_token_t const *audit = 43 (audit_token_t const *)xpc_dictionary_get_data(event, "audit", &audit_size); 44 45 if (audit != NULL && audit_size != sizeof(audit_token_t)) { 46 Syslog::error("audit token has unexpected size %zu", audit_size); 47 return; 48 } 49 50 xpc_object_t reply = xpc_dictionary_create_reply(event); 51 if (reply == NULL) 52 return; 53 54 CFTemp<CFMutableDictionaryRef> attributes("{%O=%d}", kSecGuestAttributePid, pid); 55 56 if (audit != NULL) { 57 CFRef<CFDataRef> auditData = makeCFData(audit, audit_size); 58 CFDictionaryAddValue(attributes.get(), kSecGuestAttributeAudit, 59 auditData); 60 } 61 CFRef<SecCodeRef> code; 62 if (SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref()) == noErr) { 63 64 // path to base of client code 65 CFRef<CFURLRef> codePath; 66 if (SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref()) == noErr) { 67 CFRef<CFDataRef> data = CFURLCreateData(NULL, codePath, kCFStringEncodingUTF8, true); 68 xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data)); 69 } 70 71 // if the caller wants the Info.plist, get it and verify the hash passed by the caller 72 size_t iphLength; 73 if (const void *iphash = xpc_dictionary_get_data(event, "infohash", &iphLength)) { 74 if (CFRef<CFDataRef> data = SecCodeCopyComponent(code, Security::CodeSigning::cdInfoSlot, CFTempData(iphash, iphLength))) { 75 xpc_dictionary_set_data(reply, "infoPlist", CFDataGetBytePtr(data), CFDataGetLength(data)); 76 } 77 } 78 } 79 xpc_connection_send_message(peer, reply); 80 xpc_release(reply); 81 } 82 83 84 static void CodeSigningHelper_peer_event_handler(xpc_connection_t peer, xpc_object_t event) 85 { 86 xpc_type_t type = xpc_get_type(event); 87 if (type == XPC_TYPE_ERROR) 88 return; 89 90 assert(type == XPC_TYPE_DICTIONARY); 91 92 const char *cmd = xpc_dictionary_get_string(event, "command"); 93 if (cmd == NULL) { 94 xpc_connection_cancel(peer); 95 } else if (strcmp(cmd, "fetchData") == 0) 96 request(peer, event); 97 else { 98 Syslog::error("peer sent invalid command %s", cmd); 99 xpc_connection_cancel(peer); 100 } 101 } 102 103 104 static void CodeSigningHelper_event_handler(xpc_connection_t peer) 105 { 106 xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { 107 CodeSigningHelper_peer_event_handler(peer, event); 108 }); 109 xpc_connection_resume(peer); 110 } 111 112 int main(int argc, const char *argv[]) 113 { 114 char *error = NULL; 115 if (sandbox_init("com.apple.CodeSigningHelper", SANDBOX_NAMED, &error)) { 116 Syslog::error("failed to enter sandbox: %s", error); 117 exit(EXIT_FAILURE); 118 } 119 xpc_main(CodeSigningHelper_event_handler); 120 return 0; 121 }