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
);
172 MacOSError::throwMe(errSecCSUnimplemented
);
175 MacOSError::throwMe(errSecCSNoSuchCode
);
180 // Return the Hosting Port for this Code.
181 // May return MACH_PORT_NULL if the code is not a code host.
182 // Throws if we can't get the hosting port for some reason (and can't positively
183 // determine that there is none).
185 // Note that we do NOT cache negative outcomes. Being a host is a dynamic property,
186 // and this Code may not have commenced hosting operations yet. For non- (or not-yet-)hosts
187 // we simply return NULL.
189 Port
GenericCode::hostingPort()
192 if (staticCode()->codeDirectory()->flags
& kSecCodeSignatureHost
) {
193 mHostingPort
= getHostingPort();
194 CODESIGN_GUEST_HOSTINGPORT(this, mHostingPort
);
202 // A pure GenericHost has no idea where to get a hosting port from.
203 // This method must be overridden to get one.
204 // However, we do handle a contiguous chain of GenericCodes by deferring
205 // to our next-higher host for it.
207 mach_port_t
GenericCode::getHostingPort()
209 if (GenericCode
*genericHost
= dynamic_cast<GenericCode
*>(host()))
210 return genericHost
->getHostingPort();
212 MacOSError::throwMe(errSecCSNotAHost
);