#include "slcrep.h"
namespace Security {
namespace CodeSigning {
using namespace UnixPlusPlus;
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<const EmbeddedSignatureBlob>((uint32_t)mCache.mapSize());
if (mCache.totalSize() >= mCache.mapSize() + blob->length()) mSigningData = blob;
}
CODESIGN_DISKREP_CREATE_SLC(this, (char*)this->mainExecutablePath().c_str());
}
bool DYLDCacheRep::candidate(FileDesc &fd)
{
return DYLDCache::validate(fd);
}
size_t DYLDCacheRep::pageSize(const SigningContext &)
{
return segmentedPageSize;
}
size_t DYLDCacheRep::signingLimit()
{
return mCache.mapSize();
}
CFDataRef DYLDCacheRep::component(CodeDirectory::SpecialSlot slot)
{
return mSigningData ? mSigningData->component(slot) : NULL;
}
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)";
}
DiskRep::Writer *DYLDCacheRep::writer()
{
return new Writer(this);
}
void DYLDCacheRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
{
EmbeddedSignatureBlob::Maker::component(slot, data);
}
void DYLDCacheRep::Writer::flush()
{
delete mSigningData; mSigningData = Maker::make(); fd().seek(rep->mCache.mapSize()); fd().writeAll(*mSigningData);
}
void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder &builder)
{
bool execSegmentProcessed = false;
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);
if (dmap.maxProt() & VM_PROT_EXECUTE) {
if (execSegmentProcessed) {
CSError::throwMe(errSecMultipleExecSegments);
}
builder.execSeg(dmap.offset(), dmap.limit()-dmap.address(), 0);
}
}
}
} }