#include "requirement.h"
#include "reqinterp.h"
#include "codesigning_dtrace.h"
#include <security_utilities/errors.h>
#include <security_utilities/unix++.h>
#include <security_utilities/logging.h>
#include <security_utilities/cfutilities.h>
#include <security_utilities/hashing.h>
#ifdef DEBUGDUMP
#include <security_codesigning/reqdumper.h>
#endif
namespace Security {
namespace CodeSigning {
static const SHA1::Digest gAppleAnchorHash =
{ 0x61, 0x1e, 0x5b, 0x66, 0x2c, 0x59, 0x3a, 0x08, 0xff, 0x58,
0xd1, 0x4a, 0xe2, 0x24, 0x52, 0xd1, 0x98, 0xdf, 0x6c, 0x60 };
const char *const Requirement::typeNames[] = {
"invalid",
"host",
"guest",
"designated",
"library",
"plugin",
};
void Requirement::validate(const Requirement::Context &ctx, OSStatus failure ) const
{
if (!this->validates(ctx, failure))
MacOSError::throwMe(failure);
}
bool Requirement::validates(const Requirement::Context &ctx, OSStatus failure ) const
{
CODESIGN_EVAL_REQINT_START((void*)this, this->length());
switch (kind()) {
case exprForm:
if (Requirement::Interpreter(this, &ctx).evaluate()) {
CODESIGN_EVAL_REQINT_END(this, 0);
return true;
} else {
CODESIGN_EVAL_REQINT_END(this, failure);
return false;
}
default:
CODESIGN_EVAL_REQINT_END(this, errSecCSReqUnsupported);
MacOSError::throwMe(errSecCSReqUnsupported);
}
}
SecCertificateRef Requirement::Context::cert(int ix) const
{
if (certs) {
if (ix < 0)
ix += certCount();
if (ix >= CFArrayGetCount(certs))
return NULL;
if (CFTypeRef element = CFArrayGetValueAtIndex(certs, ix))
return SecCertificateRef(element);
}
return NULL;
}
unsigned int Requirement::Context::certCount() const
{
if (certs)
return CFArrayGetCount(certs);
else
return 0;
}
const SHA1::Digest &Requirement::appleAnchorHash()
{
return gAppleAnchorHash;
}
#if defined(TEST_APPLE_ANCHOR)
const char Requirement::testAppleAnchorEnv[] = "TEST_APPLE_ANCHOR";
const SHA1::Digest &Requirement::testAppleAnchorHash()
{
static bool tried = false;
static SHA1::Digest testHash;
if (!tried) {
if (const char *path = getenv(testAppleAnchorEnv))
try {
UnixPlusPlus::FileDesc fd(path);
char buffer[2048]; size_t size = fd.read(buffer, sizeof(buffer));
SHA1 hash;
hash(buffer, size);
hash.finish(testHash);
Syslog::alert("ACCEPTING TEST AUTHORITY %s FOR APPLE CODE IDENTITY", path);
} catch (...) { }
tried = true;
}
return testHash; }
#endif //TEST_APPLE_ANCHOR
#ifdef DEBUGDUMP
void Requirement::dump() const
{
Debug::dump("%s\n", Dumper::dump(this).c_str());
}
#endif //DEBUGDUMP
} }