TrustedApplication.cpp [plain text]
#include <security_keychain/TrustedApplication.h>
#include <security_keychain/ACL.h>
#include <security_utilities/osxcode.h>
#include <security_utilities/trackingallocator.h>
#include <security_cdsa_utilities/acl_codesigning.h>
#include <sys/syslimits.h>
#include <memory>
using namespace KeychainCore;
TrustedApplication::TrustedApplication(const TypedList &subject)
{
try {
CodeSignatureAclSubject::Maker maker;
mForm = maker.make(subject);
secdebug("trustedapp", "%p created from list form", this);
IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from list"));
} catch (...) {
throw ACL::ParseError();
}
}
TrustedApplication::TrustedApplication(const std::string &path)
{
RefPointer<OSXCode> code(OSXCode::at(path));
mForm = new CodeSignatureAclSubject(OSXVerifier(code));
secdebug("trustedapp", "%p created from path %s", this, path.c_str());
IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from path"));
}
TrustedApplication::TrustedApplication()
{
RefPointer<OSXCode> me(OSXCode::main());
mForm = new CodeSignatureAclSubject(OSXVerifier(me));
secdebug("trustedapp", "%p created from self", this);
IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from self"));
}
TrustedApplication::TrustedApplication(const std::string &path, SecRequirementRef reqRef)
{
CFRef<CFDataRef> reqData;
MacOSError::check(SecRequirementCopyData(reqRef, kSecCSDefaultFlags, &reqData.aref()));
mForm = new CodeSignatureAclSubject(NULL, path);
mForm->add((const BlobCore *)CFDataGetBytePtr(reqData));
secdebug("trustedapp", "%p created from path %s and requirement %p",
this, path.c_str(), reqRef);
IFDUMPING("codesign", mForm->debugDump());
}
TrustedApplication::~TrustedApplication()
{ }
TrustedApplication::TrustedApplication(CFDataRef external)
{
AclSubject::Reader pubReader(CFDataGetBytePtr(external)), privReader;
mForm = CodeSignatureAclSubject::Maker().make(0, pubReader, privReader);
}
CFDataRef TrustedApplication::externalForm() const
{
AclSubject::Writer::Counter pubCounter, privCounter;
mForm->exportBlob(pubCounter, privCounter);
if (privCounter > 0) CssmError::throwMe(CSSMERR_CSSM_INTERNAL_ERROR);
CFRef<CFMutableDataRef> data = CFDataCreateMutable(NULL, pubCounter);
CFDataSetLength(data, pubCounter);
if (CFDataGetLength(data) < CFIndex(pubCounter))
CFError::throwMe();
AclSubject::Writer pubWriter(CFDataGetMutableBytePtr(data)), privWriter;
mForm->exportBlob(pubWriter, privWriter);
return data.yield();
}
bool TrustedApplication::verifyToDisk(const char *path)
{
if (SecRequirementRef requirement = mForm->requirement()) {
secdebug("trustedapp", "%p validating requirement against path %s", this, path);
CFRef<SecStaticCodeRef> ondisk;
if (path)
MacOSError::check(SecStaticCodeCreateWithPath(CFTempURL(path),
kSecCSDefaultFlags, &ondisk.aref()));
else
MacOSError::check(SecCodeCopySelf(kSecCSDefaultFlags, (SecCodeRef *)&ondisk.aref()));
return SecStaticCodeCheckValidity(ondisk, kSecCSDefaultFlags, requirement) == noErr;
} else {
secdebug("trustedapp", "%p validating hash against path %s", this, path);
RefPointer<OSXCode> code = path ? OSXCode::at(path) : OSXCode::main();
SHA1::Digest ondiskDigest;
OSXVerifier::makeLegacyHash(code, ondiskDigest);
return memcmp(ondiskDigest, mForm->legacyHash(), sizeof(ondiskDigest)) == 0;
}
}
CssmList TrustedApplication::makeSubject(Allocator &allocator)
{
return mForm->toList(allocator);
}
PathDatabase::PathDatabase(const char *path)
{
if (FILE *f = fopen(path, "r")) {
mQualifyAll = false;
char path[PATH_MAX+1];
while (fgets(path, sizeof(path), f)) {
path[strlen(path)-1] = '\0'; mPaths.insert(path);
}
fclose(f);
secdebug("equivdb", "read %ld paths from %s", mPaths.size(), path);
} else {
mQualifyAll = true;
secdebug("equivdb", "cannot open %s, will qualify all application paths", path);
}
}
bool PathDatabase::lookup(const string &inPath)
{
string path = inPath;
string::size_type lastSlash = path.rfind('/');
string::size_type bundleCore = path.find("/Contents/MacOS/");
if (lastSlash != string::npos && bundleCore != string::npos)
if (bundleCore + 15 == lastSlash)
path = path.substr(0, bundleCore); return mPaths.find(path) != mPaths.end();
}