X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_codesigning/lib/slcrep.cpp diff --git a/Security/libsecurity_codesigning/lib/slcrep.cpp b/Security/libsecurity_codesigning/lib/slcrep.cpp new file mode 100644 index 00000000..8a0ecbd4 --- /dev/null +++ b/Security/libsecurity_codesigning/lib/slcrep.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2009,2011-2012 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@ + */ + +// +// slcrep - DiskRep representing the Mac OS Shared Library Cache +// +#include "slcrep.h" + + +namespace Security { +namespace CodeSigning { + +using namespace UnixPlusPlus; + + +// +// Object management. +// We open the file lazily, so nothing much happens on constructions. +// We can construct directly from a file path, or from an architecture +// (represented by Context), which will find the file in its usual +// location on disk. +// +DYLDCacheRep::DYLDCacheRep(const char *path) + : SingleDiskRep(path), mCache(path) +{ + this->setup(); +} + +DYLDCacheRep::DYLDCacheRep(const Context *ctx) + : SingleDiskRep(DYLDCache::pathFor(((ctx && ctx->arch) ? ctx->arch : Architecture::local()))), + mCache(this->path()) +{ + this->setup(); +} + +void DYLDCacheRep::setup() +{ + mSigningData = NULL; + if (mCache.totalSize() >= mCache.mapSize() + sizeof(BlobCore)) { + const EmbeddedSignatureBlob *blob = mCache.at((uint32_t)mCache.mapSize()); + if (mCache.totalSize() >= mCache.mapSize() + blob->length()) // entire blob fits in file + mSigningData = blob; + } + CODESIGN_DISKREP_CREATE_SLC(this, (char*)this->mainExecutablePath().c_str()); +} + + +// +// Sniffer function for "plausible shared library cache file". +// +bool DYLDCacheRep::candidate(FileDesc &fd) +{ + return DYLDCache::validate(fd); +} + + +// +// Default to system page size for segmented (paged) signatures +// +size_t DYLDCacheRep::pageSize(const SigningContext &) +{ + return segmentedPageSize; +} + + +// +// Signing limit is the start of the (trailing) signature +// +size_t DYLDCacheRep::signingLimit() +{ + return mCache.mapSize(); +} + + +// +// Retrieve a component from the executable. +// Our mCache has mapped the entire file, so we just fish the contents out of +// the mapped area as needed. +// +CFDataRef DYLDCacheRep::component(CodeDirectory::SpecialSlot slot) +{ + return mSigningData ? mSigningData->component(slot) : NULL; +} + + +// +// Provide a (vaguely) human readable characterization of this code +// +string DYLDCacheRep::format() +{ + if (const char *name = mCache.architecture().name()) { + char result[100]; + snprintf(result, sizeof(result), "OS X Shared Library Cache (%s @ 0x%llx)", + name, mCache.baseAddress()); + return result; + } else + return "OS X Shared Library Cache (unknown type)"; +} + + +// +// DYLDCacheRep::Writers +// +DiskRep::Writer *DYLDCacheRep::writer() +{ + return new Writer(this); +} + + +// +// Write a component. +// +void DYLDCacheRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + EmbeddedSignatureBlob::Maker::component(slot, data); +} + + +// +// Append the superblob we built to the cache file. +// +void DYLDCacheRep::Writer::flush() +{ + delete mSigningData; // ditch previous blob just in case + mSigningData = Maker::make(); // assemble new signature SuperBlob + fd().seek(rep->mCache.mapSize()); // end of impage proper + fd().writeAll(*mSigningData); +} + + +// +// The discretionary additions insert a Scatter vector describing the file's mapping table. +// +void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder &builder) +{ + unsigned count = rep->mCache.mappingCount(); + builder.scatter(count); + for (unsigned n = 0; n < count; n++) { + const DYLDCache::Mapping dmap = rep->mCache.mapping(n); + CodeDirectory::Scatter *scatter = builder.scatter() + n; + scatter->targetOffset = dmap.address(); + scatter->base = (uint32_t)(dmap.offset() / segmentedPageSize); + assert(dmap.offset() % segmentedPageSize == 0); + scatter->count = (uint32_t)(dmap.size() / segmentedPageSize); + assert(dmap.size() % segmentedPageSize == 0); + } +} + + +} // end namespace CodeSigning +} // end namespace Security