1/* 2 * Copyright (c) 2012 Apple Computer, 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 "piddiskrep.h" 24#include "sigblob.h" 25#include <sys/param.h> 26#include <sys/utsname.h> 27#include <System/sys/codesign.h> 28#include <libproc.h> 29#include <xpc/xpc.h> 30 31namespace Security { 32namespace CodeSigning { 33 34using namespace UnixPlusPlus; 35 36void 37PidDiskRep::fetchData(void) 38{ 39 xpc_connection_t conn = xpc_connection_create("com.apple.CodeSigningHelper", 40 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 41 xpc_connection_set_event_handler(conn, ^(xpc_object_t object){ }); 42 xpc_connection_resume(conn); 43 44 xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0); 45 assert(request != NULL); 46 xpc_dictionary_set_string(request, "command", "fetchData"); 47 xpc_dictionary_set_int64(request, "pid", mPid); 48 49 xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, request); 50 if (reply && xpc_get_type(reply) == XPC_TYPE_DICTIONARY) { 51 const void *data; 52 size_t size; 53 54 if (!mInfoPlist) { 55 data = xpc_dictionary_get_data(reply, "infoPlist", &size); 56 if (data && size > 0 && size < 50 * 1024) 57 mInfoPlist.take(CFDataCreate(NULL, (const UInt8 *)data, (CFIndex)size)); 58 } 59 if (!mBundleURL) { 60 data = xpc_dictionary_get_data(reply, "bundleURL", &size); 61 if (data && size > 0 && size < 50 * 1024) 62 mBundleURL.take(CFURLCreateWithBytes(NULL, (const UInt8 *)data, (CFIndex)size, kCFStringEncodingUTF8, NULL)); 63 } 64 } 65 if (reply) 66 xpc_release(reply); 67 68 xpc_release(request); 69 xpc_release(conn); 70} 71 72 73PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist) 74{ 75 BlobCore header; 76 CODESIGN_DISKREP_CREATE_KERNEL(this); 77 78 mPid = pid; 79 mInfoPlist = infoPlist; 80 81 fetchData(); 82 83 int rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header)); 84 if (rcent == 0) 85 MacOSError::throwMe(errSecCSNoSuchCode); 86 87 if (errno != ERANGE) 88 UnixError::throwMe(errno); 89 90 if (header.length() > 1024 * 1024) 91 MacOSError::throwMe(errSecCSNoSuchCode); 92 93 uint32_t bufferLen = (uint32_t)header.length(); 94 mBuffer = new uint8_t [bufferLen]; 95 96 UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen)); 97 98 const BlobCore *b = (const BlobCore *)mBuffer; 99 if (b->magic() != kSecCodeMagicEmbeddedSignature) 100 MacOSError::throwMe(errSecCSSignatureInvalid); 101 if (b->length() < sizeof(*b)) 102 MacOSError::throwMe(errSecCSNoSuchCode); 103} 104 105PidDiskRep::~PidDiskRep() 106{ 107 if (mBuffer) 108 delete [] mBuffer; 109} 110 111 112bool PidDiskRep::supportInfoPlist() 113{ 114 return mInfoPlist; 115} 116 117 118CFDataRef PidDiskRep::component(CodeDirectory::SpecialSlot slot) 119{ 120 if (slot == cdInfoSlot) 121 return mInfoPlist.retain(); 122 123 EmbeddedSignatureBlob *b = (EmbeddedSignatureBlob *)this->blob(); 124 return b->component(slot); 125} 126 127CFDataRef PidDiskRep::identification() 128{ 129 return NULL; 130} 131 132 133CFURLRef PidDiskRep::copyCanonicalPath() 134{ 135 return mBundleURL.retain(); 136} 137 138string PidDiskRep::recommendedIdentifier(const SigningContext &) 139{ 140 return string("pid") + to_string(mPid); 141} 142 143size_t PidDiskRep::signingLimit() 144{ 145 return 0; 146} 147 148string PidDiskRep::format() 149{ 150 return "pid diskrep"; 151} 152 153UnixPlusPlus::FileDesc &PidDiskRep::fd() 154{ 155 UnixError::throwMe(EINVAL); 156} 157 158string PidDiskRep::mainExecutablePath() 159{ 160 char path[MAXPATHLEN * 2]; 161 if(::proc_pidpath(mPid, path, sizeof(path)) == 0) 162 UnixError::throwMe(errno); 163 164 return path; 165} 166 167 168} // end namespace CodeSigning 169} // end namespace Security 170