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  }