#include "csutilities.h"
#include <Security/SecCertificatePriv.h>
#include <utilities/SecAppleAnchorPriv.h>
#include <utilities/SecInternalReleasePriv.h>
#include "requirement.h"
#include <security_utilities/hashing.h>
#include <security_utilities/debugging.h>
#include <security_utilities/errors.h>
#include <sys/utsname.h>
namespace Security {
namespace CodeSigning {
bool isAppleCA(SecCertificateRef cert)
{
SecAppleTrustAnchorFlags flags = 0;
if (SecIsInternalRelease())
flags |= kSecAppleTrustAnchorFlagsIncludeTestAnchors;
return SecIsAppleTrustAnchor(cert, flags);
}
void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest digest)
{
SHA1 hasher;
hasher(certData, certLength);
hasher.finish(digest);
}
void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest)
{
assert(cert);
#if TARGET_OS_OSX
CSSM_DATA certData;
MacOSError::check(SecCertificateGetData(cert, &certData));
hashOfCertificate(certData.Data, certData.Length, digest);
#else
hashOfCertificate(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert), digest);
#endif
}
bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest)
{
SHA1::Digest dig;
hashOfCertificate(cert, dig);
return !memcmp(dig, digest, SHA1::digestLength);
}
#if TARGET_OS_OSX
bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid)
{
assert(cert);
CSSM_DATA *value;
switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) {
case errSecSuccess:
MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value));
return true; case errSecUnknownTag:
break; default:
MacOSError::throwMe(rc); }
CSSM_DATA **values;
bool found = false;
if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values))
return false; if (values)
for (CSSM_DATA **p = values; *p; p++) {
const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data;
if (oid == ext->extnId) {
found = true;
break;
}
}
MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values));
return found;
}
bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid)
{
bool matched = false;
assert(cert);
CSSM_DATA *data;
if (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_CertificatePolicies, &data))
MacOSError::throwMe(rc);
if (data && data->Data && data->Length == sizeof(CSSM_X509_EXTENSION)) {
const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)data->Data;
assert(ext->format == CSSM_X509_DATAFORMAT_PARSED);
const CE_CertPolicies *policies = (const CE_CertPolicies *)ext->value.parsedValue;
if (policies)
for (unsigned int n = 0; n < policies->numPolicies; n++) {
const CE_PolicyInformation &cp = policies->policies[n];
if (cp.certPolicyId == policyOid) {
matched = true;
break;
}
}
}
SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data);
return matched;
}
#endif
Copyfile::Copyfile()
{
if (!(mState = copyfile_state_alloc()))
UnixError::throwMe();
}
void Copyfile::set(uint32_t flag, const void *value)
{
check(::copyfile_state_set(mState, flag, value));
}
void Copyfile::get(uint32_t flag, void *value)
{
check(::copyfile_state_set(mState, flag, value));
}
void Copyfile::operator () (const char *src, const char *dst, copyfile_flags_t flags)
{
check(::copyfile(src, dst, mState, flags));
}
void Copyfile::check(int rc)
{
if (rc < 0)
UnixError::throwMe();
}
MessageTrace::MessageTrace(const char *domain, const char *signature)
{
mAsl = asl_new(ASL_TYPE_MSG);
if (domain)
asl_set(mAsl, "com.apple.message.domain", domain);
if (signature)
asl_set(mAsl, "com.apple.message.signature", signature);
}
void MessageTrace::add(const char *key, const char *format, ...)
{
va_list args;
va_start(args, format);
char value[200];
vsnprintf(value, sizeof(value), format, args);
va_end(args);
asl_set(mAsl, (string("com.apple.message.") + key).c_str(), value);
}
void MessageTrace::send(const char *format, ...)
{
va_list args;
va_start(args, format);
asl_vlog(NULL, mAsl, ASL_LEVEL_NOTICE, format, args);
va_end(args);
}
LimitedAsync::LimitedAsync(bool async)
{
long async_workers = 0;
long ncpu = sysconf(_SC_NPROCESSORS_ONLN);
if (async && ncpu > 0)
async_workers = ncpu - 1;
mResourceSemaphore = new Dispatch::Semaphore(async_workers);
}
LimitedAsync::LimitedAsync(LimitedAsync &limitedAsync)
{
mResourceSemaphore = new Dispatch::Semaphore(*limitedAsync.mResourceSemaphore);
}
LimitedAsync::~LimitedAsync()
{
delete mResourceSemaphore;
}
bool LimitedAsync::perform(Dispatch::Group &groupRef, void (^block)()) {
__block Dispatch::SemaphoreWait wait(*mResourceSemaphore, DISPATCH_TIME_NOW);
if (wait.acquired()) {
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
groupRef.enqueue(defaultQueue, ^{
Dispatch::SemaphoreWait innerWait(wait);
block();
});
return true;
} else {
block();
return false;
}
}
} }