#include "codesign.h"
#include <Security/SecCodeSigner.h>
#include <cstdio>
#include <cmath>
using namespace CodeSigning;
using namespace UnixPlusPlus;
static CFMutableDictionaryRef parameters; static SecCodeSignerRef signerRef;
void prepareToSign()
{
parameters =
makeCFMutableDictionary(1,
kSecCodeSignerIdentity, signer
);
if (uniqueIdentifier)
CFDictionaryAddValue(parameters,
kSecCodeSignerIdentifier, CFTempString(uniqueIdentifier));
if (identifierPrefix)
CFDictionaryAddValue(parameters,
kSecCodeSignerIdentifierPrefix, CFTempString(identifierPrefix));
if (internalReq) {
const Requirements *internalReqs = readRequirement<Requirements>(internalReq);
CFDictionaryAddValue(parameters,
kSecCodeSignerRequirements, CFTempData(*internalReqs));
if (internalReqs->find(kSecGuestRequirementType)) {
secdebug("codesign", "has guest requirements; setting host flag");
cdFlags |= kSecCodeSignatureHost;
}
}
if (signatureSize)
CFDictionaryAddValue(parameters, CFSTR("cmssize"), CFTempNumber(signatureSize));
if (pagesize != pagesizeUnspecified)
CFDictionaryAddValue(parameters, kSecCodeSignerPageSize, CFTempNumber(pagesize));
if (cdFlags)
CFDictionaryAddValue(parameters, kSecCodeSignerFlags, CFTempNumber(cdFlags));
if (detached)
CFDictionaryAddValue(parameters, kSecCodeSignerDetached, CFTempURL(detached));
if (signingTime)
CFDictionaryAddValue(parameters, kSecCodeSignerSigningTime, signingTime);
if (resourceRules) {
if (CFRef<CFDataRef> data = cfLoadFile(resourceRules)) {
CFDictionaryAddValue(parameters, kSecCodeSignerResourceRules,
CFRef<CFDictionaryRef>(makeCFDictionaryFrom(data)));
} else
fail("%s: cannot read resources", resourceRules);
}
if (entitlements) {
AutoFileDesc fd(entitlements);
BlobCore *blob = BlobCore::readBlob(fd);
if (!blob)
fail("%s: cannot read entitlements", entitlements);
if (blob->length() != fd.fileSize())
fail("%s: invalid length in entitlement blob", entitlements);
CFDictionaryAddValue(parameters, kSecCodeSignerEntitlements, CFTempData(*blob));
}
if (dryrun)
CFDictionaryAddValue(parameters, kSecCodeSignerDryRun, kCFBooleanTrue);
MacOSError::check(SecCodeSignerCreate(parameters, kSecCSDefaultFlags, &signerRef));
}
void sign(const char *target)
{
secdebug("codesign", "BEGIN SIGNING %s", target);
CFRef<SecStaticCodeRef> code;
MacOSError::check(SecStaticCodeCreateWithPath(CFTempURL(target), kSecCSDefaultFlags,
&code.aref()));
CFRef<CFDictionaryRef> dict;
switch (OSStatus rc = SecCodeCopySigningInformation(code,
preserveMetadata ? SecCSFlags(kSecCSRequirementInformation) : kSecCSDefaultFlags,
&dict.aref())) {
case noErr:
if (CFDictionaryGetValue(dict, kSecCodeInfoIdentifier)) { if (detached)
note(0, "%s: not disturbing embedded signature", target);
else if (force)
note(0, "%s: replacing existing signature", target);
else if (signer)
fail("%s: is already signed", target);
}
break;
case errSecCSSignatureFailed: case CSSMERR_TP_NOT_TRUSTED: if (detached)
note(0, "%s: ignoring invalid embedded signature", target);
else if (force)
note(0, "%s: replacing invalid existing signature", target);
else if (signer)
fail("%s: is already signed", target);
break;
default:
MacOSError::throwMe(rc);
}
CFRef<SecCodeSignerRef> currentSigner = signerRef; if (preserveMetadata) {
CFRef<CFMutableDictionaryRef> param = CFDictionaryCreateMutableCopy(NULL, 0, parameters);
if (!CFDictionaryGetValue(param, kSecCodeSignerRequirements))
if (CFTypeRef ireqs = CFDictionaryGetValue(dict, kSecCodeInfoRequirementData))
CFDictionaryAddValue(param, kSecCodeSignerRequirements, ireqs);
if (!CFDictionaryGetValue(param, kSecCodeSignerEntitlements))
if (CFTypeRef entitlements = CFDictionaryGetValue(dict, kSecCodeInfoEntitlements))
CFDictionaryAddValue(param, kSecCodeSignerEntitlements, entitlements);
MacOSError::check(SecCodeSignerCreate(param, kSecCSDefaultFlags, ¤tSigner.aref()));
}
ErrorCheck check;
check(SecCodeSignerAddSignatureWithErrors(currentSigner, code, kSecCSDefaultFlags, check));
SecCSFlags flags = kSecCSDefaultFlags;
if (modifiedFiles)
flags |= kSecCSContentInformation;
MacOSError::check(SecCodeCopySigningInformation(code, flags, &dict.aref()));
note(1, "%s: signed %s [%s]", target,
cfString(CFStringRef(CFDictionaryGetValue(dict, kSecCodeInfoFormat))).c_str(),
cfString(CFStringRef(CFDictionaryGetValue(dict, kSecCodeInfoIdentifier))).c_str()
);
if (modifiedFiles)
writeFileList(CFArrayRef(CFDictionaryGetValue(dict, kSecCodeInfoChangedFiles)), modifiedFiles, "a");
}