X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/b1ab9ed8d0e0f1c3b66d7daa8fd5564444c56195..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_codesigning/lib/Code.cpp diff --git a/libsecurity_codesigning/lib/Code.cpp b/libsecurity_codesigning/lib/Code.cpp deleted file mode 100644 index ab5072ae..00000000 --- a/libsecurity_codesigning/lib/Code.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// Code - SecCode API objects -// -#include "Code.h" -#include "StaticCode.h" -#include -#include "cskernel.h" -#include -#include - -namespace Security { -namespace CodeSigning { - - -// -// Construction -// -SecCode::SecCode(SecCode *host) - : mHost(host), mIdentified(false) -{ - CODESIGN_DYNAMIC_CREATE(this, host); -} - - -// -// Clean up a SecCode object -// -SecCode::~SecCode() throw() -try { -} catch (...) { - return; -} - - -// -// CF-level comparison of SecStaticCode objects compares CodeDirectory hashes if signed, -// and falls back on comparing canonical paths if (both are) not. -// -bool SecCode::equal(SecCFObject &secOther) -{ - SecCode *other = static_cast(&secOther); - CFDataRef mine = this->cdHash(); - CFDataRef his = other->cdHash(); - if (mine || his) - return mine && his && CFEqual(mine, his); - else - return this->staticCode()->equal(*other->staticCode()); -} - -CFHashCode SecCode::hash() -{ - if (CFDataRef h = this->cdHash()) - return CFHash(h); - else - return this->staticCode()->hash(); -} - - -// -// Yield the host Code -// -SecCode *SecCode::host() const -{ - return mHost; -} - - -// -// Yield the static code. This is cached. -// The caller does not own the object returned; it lives (at least) as long -// as the SecCode it was derived from. -// -SecStaticCode *SecCode::staticCode() -{ - if (!mIdentified) { - this->identify(); - mIdentified = true; - } - assert(mStaticCode); - return mStaticCode; -} - - -// -// Yield the CodeDirectory hash as presented by our host. -// This usually is the same as the hash of staticCode().codeDirectory(), but might not -// if files are changing on disk while code is running. -// -CFDataRef SecCode::cdHash() -{ - if (!mIdentified) { - this->identify(); - mIdentified = true; - } - return mCDHash; // can be NULL (host has no dynamic identity for guest) -} - - -// -// Retrieve current dynamic status. -// -SecCodeStatus SecCode::status() -{ - if (this->isRoot()) - return kSecCodeStatusValid; // root of trust, presumed valid - else - return this->host()->getGuestStatus(this); -} - -void SecCode::status(SecCodeStatusOperation operation, CFDictionaryRef arguments) -{ - if (this->isRoot()) - MacOSError::throwMe(errSecCSHostProtocolStateError); - else - this->host()->changeGuestStatus(this, operation, arguments); -} - - -// -// By default, we have no guests -// -SecCode *SecCode::locateGuest(CFDictionaryRef) -{ - return NULL; -} - - -// -// By default, we self-identify by asking our host to identify us. -// (This is currently only overridden in the root-of-trust (kernel) implementation.) -// -void SecCode::identify() -{ - mStaticCode.take(host()->identifyGuest(this, &mCDHash.aref())); -} - - -// -// The default implementation cannot map guests to disk -// -SecStaticCode *SecCode::identifyGuest(SecCode *, CFDataRef *) -{ - MacOSError::throwMe(errSecCSNoSuchCode); -} - - -// -// Master validation function. -// -// This is the most important function in all of Code Signing. It performs -// dynamic validation on running code. Despite its simple structure, it does -// everything that's needed to establish whether a Code is currently valid... -// with a little help from StaticCode, format drivers, type drivers, and so on. -// -// This function validates internal requirements in the hosting chain. It does -// not validate external requirements - the caller needs to do that with a separate call. -// -void SecCode::checkValidity(SecCSFlags flags) -{ - if (this->isRoot()) { - // the root-of-trust is valid by definition - CODESIGN_EVAL_DYNAMIC_ROOT(this); - return; - } - DTRACK(CODESIGN_EVAL_DYNAMIC, this, (char*)this->staticCode()->mainExecutablePath().c_str()); - - // - // Do not reorder the operations below without thorough cogitation. There are - // interesting dependencies and significant performance issues. There is also - // client code that relies on errors being noticed in a particular order. - // - // For the most part, failure of (reliable) identity will cause exceptions to be - // thrown, and success is indicated by survival. If you make it to the end, - // you have won the validity race. (Good rat.) - // - - // check my host first, recursively - this->host()->checkValidity(flags); - - SecStaticCode *myDisk = this->staticCode(); - SecStaticCode *hostDisk = this->host()->staticCode(); - - // check my static state - myDisk->validateDirectory(); - - // check my own dynamic state - if (!(this->host()->getGuestStatus(this) & kSecCodeStatusValid)) - MacOSError::throwMe(errSecCSGuestInvalid); - - // check that static and dynamic views are consistent - if (this->cdHash() && !CFEqual(this->cdHash(), myDisk->cdHash())) - MacOSError::throwMe(errSecCSStaticCodeChanged); - - // check host/guest constraints - if (!this->host()->isRoot()) { // not hosted by root of trust - myDisk->validateRequirements(kSecHostRequirementType, hostDisk, errSecCSHostReject); - hostDisk->validateRequirements(kSecGuestRequirementType, myDisk); - } -} - - -// -// By default, we track no validity for guests (we don't have any) -// -uint32_t SecCode::getGuestStatus(SecCode *guest) -{ - MacOSError::throwMe(errSecCSNoSuchCode); -} - -void SecCode::changeGuestStatus(SecCode *guest, SecCodeStatusOperation operation, CFDictionaryRef arguments) -{ - MacOSError::throwMe(errSecCSNoSuchCode); -} - - -// -// 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(CFTemp("{%O=%d}", kSecGuestAttributePid, pid))) { - SecPointer 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 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); -} - - -} // end namespace CodeSigning -} // end namespace Security