2  * Copyright (c) 2006-2007,2011-2012 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25 // csgeneric - generic Code representative 
  27 #include "csgeneric.h" 
  29 #include "StaticCode.h" 
  30 #include <securityd_client/cshosting.h> 
  31 #include <sys/param.h> 
  34 namespace CodeSigning 
{ 
  36 using MachPlusPlus::Port
; 
  40 // Common call-out code for cshosting RPC service 
  42 #define CALL(host, name, args...) \ 
  44         if (cshosting_client_ ## name (host, mig_get_reply_port(), &result, args)) \ 
  45                 MacOSError::throwMe(errSecCSNotAHost); \ 
  46         MacOSError::check(result); 
  50 // Construct a running process representation 
  52 GenericCode::GenericCode(SecCode 
*host
, SecGuestRef guestRef
) 
  53         : SecCode(host
), mGuestRef(guestRef
) 
  59 // Identify a guest by attribute set, and return a new GenericCode representing it. 
  60 // This uses cshosting RPCs to ask the host (or its proxy). 
  62 SecCode 
*GenericCode::locateGuest(CFDictionaryRef attributes
) 
  64         if (Port host 
= hostingPort()) { 
  65                 CFRef
<CFDataRef
> attrData
; 
  66                 void *attrPtr 
= NULL
; size_t attrLength 
= 0; 
  68                         attrData
.take(CFPropertyListCreateXMLData(NULL
, attributes
)); 
  69                         attrPtr 
= (void *)CFDataGetBytePtr(attrData
); 
  70                         attrLength 
= CFDataGetLength(attrData
); 
  73                 mach_msg_type_number_t guestPathLength
; 
  75                 CALL(host
, findGuest
, guestRef(), attrPtr
, (mach_msg_type_number_t
)attrLength
, 
  76                         &guestPath
, &guestPathLength
, &subport
); 
  77                 CODESIGN_GUEST_LOCATE_GENERIC(this, guestPath
, guestPathLength
, subport
); 
  78                 SecPointer
<SecCode
> code 
= this; 
  79                 for (unsigned n 
= 0; n 
< guestPathLength
; n
++) 
  80                         code 
= new GenericCode(code
, guestPath
[n
]); 
  83                 return NULL
;            // not found, no error 
  88 // Identify a guest by returning its StaticCode and running CodeDirectory hash. 
  89 // This uses cshosting RPCs to ask the host (or its proxy). 
  91 SecStaticCode 
*GenericCode::identifyGuest(SecCode 
*guest
, CFDataRef 
*cdhashOut
) 
  93         if (GenericCode 
*iguest 
= dynamic_cast<GenericCode 
*>(guest
)) { 
  95                 CFRef
<CFDataRef
> cdhash
; 
  96                 CFDictionary 
attributes(errSecCSHostProtocolInvalidAttribute
); 
  97                 identifyGuest(iguest
->guestRef(), path
, cdhash
.aref(), attributes
.aref()); 
  99                 if (CFNumberRef architecture 
= attributes
.get
<CFNumberRef
>(kSecGuestAttributeArchitecture
)) { 
 100                         cpu_type_t cpu 
= cfNumber
<cpu_type_t
>(architecture
); 
 101                         if (CFNumberRef subarchitecture 
= attributes
.get
<CFNumberRef
>(kSecGuestAttributeSubarchitecture
)) 
 102                                 ctx
.arch 
= Architecture(cpu
, cfNumber
<cpu_subtype_t
>(subarchitecture
)); 
 104                                 ctx
.arch 
= Architecture(cpu
); 
 106                 SecPointer
<GenericStaticCode
> code 
= new GenericStaticCode(DiskRep::bestGuess(path
, &ctx
)); 
 107                 CODESIGN_GUEST_IDENTIFY_GENERIC(iguest
, iguest
->guestRef(), code
); 
 109                         CODESIGN_GUEST_CDHASH_GENERIC(iguest
, (void *)CFDataGetBytePtr(cdhash
), (unsigned)CFDataGetLength(cdhash
)); 
 110                         *cdhashOut 
= cdhash
.yield(); 
 114                 MacOSError::throwMe(errSecCSNotAHost
); 
 117 // helper to drive the identifyGuest hosting IPC and return results as CF objects 
 118 void GenericCode::identifyGuest(SecGuestRef guest
, char *path
, CFDataRef 
&cdhash
, CFDictionaryRef 
&attributes
) 
 120         if (Port host 
= hostingPort()) { 
 125                 CALL(host
, identifyGuest
, guest
, path
, hash
, &hashLength
, &attr
, &attrLength
); 
 127                         cdhash 
= makeCFData(hash
, hashLength
); 
 129                         CFRef
<CFDataRef
> attrData 
= makeCFData(attr
, attrLength
); 
 130                         attributes 
= makeCFDictionaryFrom(attrData
); 
 131 #if ROSETTA_TEST_HACK 
 132                         CFMutableDictionaryRef hattr 
= makeCFMutableDictionary(attributes
); 
 133                         CFDictionaryAddValue(hattr
, kSecGuestAttributeArchitecture
, CFTempNumber(CPU_TYPE_POWERPC
)); 
 134                         CFRelease(attributes
); 
 139                 MacOSError::throwMe(errSecCSNotAHost
); 
 144 // Get the Code Signing Status Word for a Code. 
 145 // This uses cshosting RPCs to ask the host (or its proxy). 
 147 SecCodeStatus 
GenericCode::getGuestStatus(SecCode 
*guest
) 
 149         if (Port host 
= hostingPort()) { 
 151                 CALL(host
, guestStatus
, safe_cast
<GenericCode 
*>(guest
)->guestRef(), &status
); 
 154                 MacOSError::throwMe(errSecCSNotAHost
); 
 159 // Status changes are transmitted through the cshosting RPCs. 
 161 void GenericCode::changeGuestStatus(SecCode 
*iguest
, SecCodeStatusOperation operation
, CFDictionaryRef arguments
) 
 163         if (/* GenericCode *guest = */dynamic_cast<GenericCode 
*>(iguest
)) 
 165                 case kSecCodeOperationNull
: 
 167                 case kSecCodeOperationInvalidate
: 
 168                 case kSecCodeOperationSetHard
: 
 169                 case kSecCodeOperationSetKill
: 
 170                         MacOSError::throwMe(errSecCSUnimplemented
); 
 173                         MacOSError::throwMe(errSecCSUnimplemented
); 
 176                 MacOSError::throwMe(errSecCSNoSuchCode
); 
 181 // Return the Hosting Port for this Code. 
 182 // May return MACH_PORT_NULL if the code is not a code host. 
 183 // Throws if we can't get the hosting port for some reason (and can't positively 
 184 // determine that there is none). 
 186 // Note that we do NOT cache negative outcomes. Being a host is a dynamic property, 
 187 // and this Code may not have commenced hosting operations yet. For non- (or not-yet-)hosts 
 188 // we simply return NULL. 
 190 Port 
GenericCode::hostingPort() 
 193                 if (staticCode()->codeDirectory()->flags 
& kSecCodeSignatureHost
) { 
 194                         mHostingPort 
= getHostingPort(); 
 195                         CODESIGN_GUEST_HOSTINGPORT(this, mHostingPort
); 
 203 // A pure GenericHost has no idea where to get a hosting port from. 
 204 // This method must be overridden to get one. 
 205 // However, we do handle a contiguous chain of GenericCodes by deferring 
 206 // to our next-higher host for it. 
 208 mach_port_t 
GenericCode::getHostingPort() 
 210         if (GenericCode 
*genericHost 
= dynamic_cast<GenericCode 
*>(host())) 
 211                 return genericHost
->getHostingPort(); 
 213                 MacOSError::throwMe(errSecCSNotAHost
);