// // Identify a guest by returning its StaticCode and running CodeDirectory hash. // This uses cshosting RPCs to ask the host (or its proxy). // SecStaticCode *GenericCode::identifyGuest(SecCode *guest, CFDataRef *cdhashOut) { if (GenericCode *iguest = dynamic_cast<GenericCode *>(guest)) { FilePathOut path; CFRef<CFDataRef> cdhash; CFDictionary attributes(errSecCSHostProtocolInvalidAttribute); identifyGuest(iguest->guestRef(), path, cdhash.aref(), attributes.aref()); DiskRep::Context ctx; if (CFNumberRef architecture = attributes.get<CFNumberRef>(kSecGuestAttributeArchitecture)) { cpu_type_t cpu = cfNumber<cpu_type_t>(architecture); if (CFNumberRef subarchitecture = attributes.get<CFNumberRef>(kSecGuestAttributeSubarchitecture)) ctx.arch = Architecture(cpu, cfNumber<cpu_subtype_t>(subarchitecture)); else ctx.arch = Architecture(cpu); } SecPointer<GenericStaticCode> code = new GenericStaticCode(DiskRep::bestGuess(path, &ctx)); CODESIGN_GUEST_IDENTIFY_GENERIC(iguest, iguest->guestRef(), code); if (cdhash) { CODESIGN_GUEST_CDHASH_GENERIC(iguest, (void *)CFDataGetBytePtr(cdhash), (unsigned)CFDataGetLength(cdhash)); *cdhashOut = cdhash.yield(); } return code.yield(); } else MacOSError::throwMe(errSecCSNotAHost); }
// // Given a bag of attribute values, automagically come up with a SecCode // without any other information. // This is meant to be the "just do what makes sense" generic call, for callers // who don't want to engage in the fascinating dance of manual guest enumeration. // // Note that we expect the logic embedded here to change over time (in backward // compatible fashion, one hopes), and that it's all right to use heuristics here // as long as it's done sensibly. // // Be warned that the present logic is quite a bit ad-hoc, and will likely not // handle arbitrary combinations of proxy hosting, dynamic hosting, and dedicated // hosting all that well. // SecCode *SecCode::autoLocateGuest(CFDictionaryRef attributes, SecCSFlags flags) { // special case: with no attributes at all, return the root of trust if (CFDictionaryGetCount(attributes) == 0) return KernelCode::active()->retain(); // main logic: we need a pid, and we'll take a canonical guest id as an option int pid = 0; if (!cfscan(attributes, "{%O=%d}", kSecGuestAttributePid, &pid)) CSError::throwMe(errSecCSUnsupportedGuestAttributes, kSecCFErrorGuestAttributes, attributes); if (SecCode *process = KernelCode::active()->locateGuest(attributes)) { SecPointer<SecCode> code; code.take(process); // locateGuest gave us a retained object if (code->staticCode()->flag(kSecCodeSignatureHost)) { // might be a code host. Let's find out CFRef<CFMutableDictionaryRef> rest = makeCFMutableDictionary(attributes); CFDictionaryRemoveValue(rest, kSecGuestAttributePid); if (SecCode *guest = code->locateGuest(rest)) return guest; } if (!CFDictionaryGetValue(attributes, kSecGuestAttributeCanonical)) { // only "soft" attributes, and no hosting is happening. Return the (non-)host itself return code.yield(); } } MacOSError::throwMe(errSecCSNoSuchCode); }
// // Identify a guest by attribute set, and return a new GenericCode representing it. // This uses cshosting RPCs to ask the host (or its proxy). // SecCode *GenericCode::locateGuest(CFDictionaryRef attributes) { if (Port host = hostingPort()) { CFRef<CFDataRef> attrData; void *attrPtr = NULL; size_t attrLength = 0; if (attributes) { attrData.take(CFPropertyListCreateXMLData(NULL, attributes)); attrPtr = (void *)CFDataGetBytePtr(attrData); attrLength = CFDataGetLength(attrData); } GuestChain guestPath; mach_msg_type_number_t guestPathLength; mach_port_t subport; CALL(host, findGuest, guestRef(), attrPtr, (mach_msg_type_number_t)attrLength, &guestPath, &guestPathLength, &subport); CODESIGN_GUEST_LOCATE_GENERIC(this, guestPath, guestPathLength, subport); SecPointer<SecCode> code = this; for (unsigned n = 0; n < guestPathLength; n++) code = new GenericCode(code, guestPath[n]); return code.yield(); } else return NULL; // not found, no error }