#include "codesign.h"
#include <Security/Security.h>
#include <Security/SecCodeSigner.h>
#include <Security/SecRequirementPriv.h>
#include <Security/CSCommonPriv.h>
#include <security_utilities/blob.h>
#include <cstdio>
#include <cmath>
using namespace UnixPlusPlus;
static CFMutableDictionaryRef parameters; static SecCodeSignerRef signerRef;
void prepareToSign()
{
parameters = makeCFMutableDictionary();
SecCSFlags flags = kSecCSDefaultFlags;
if (signer)
CFDictionaryAddValue(parameters,
kSecCodeSignerIdentity, signer);
else
flags |= kSecCSRemoveSignature;
if (uniqueIdentifier)
CFDictionaryAddValue(parameters,
kSecCodeSignerIdentifier, CFTempString(uniqueIdentifier));
if (identifierPrefix)
CFDictionaryAddValue(parameters,
kSecCodeSignerIdentifierPrefix, CFTempString(identifierPrefix));
if (internalReq)
CFDictionaryAddValue(parameters,
kSecCodeSignerRequirements, readRequirements(internalReq));
if (signatureSize)
CFDictionaryAddValue(parameters, CFSTR("cmssize"), CFTempNumber(signatureSize));
if (pagesize != pagesizeUnspecified)
CFDictionaryAddValue(parameters, kSecCodeSignerPageSize, CFTempNumber(pagesize));
if (cdFlags)
CFDictionaryAddValue(parameters, kSecCodeSignerFlags, CFTempNumber(cdFlags));
if (signingTime)
CFDictionaryAddValue(parameters, kSecCodeSignerSigningTime, signingTime);
if (detached)
CFDictionaryAddValue(parameters, kSecCodeSignerDetached, CFTempURL(detached));
else if (detachedDb)
CFDictionaryAddValue(parameters, kSecCodeSignerDetached, kCFNull);
if (resourceRules) {
if (CFRef<CFDataRef> data = cfLoadFile(resourceRules)) {
CFDictionaryAddValue(parameters, kSecCodeSignerResourceRules,
CFRef<CFDictionaryRef>(makeCFDictionaryFrom(data)));
} else
fail("%s: cannot read resources", resourceRules);
}
if (entitlements) {
if (CFRef<CFDataRef> data = cfLoadFile(entitlements)) { if (CFRef<CFDictionaryRef> dict = makeCFDictionaryFrom(data)) {
BlobWrapper *wrap = BlobWrapper::alloc(CFDataGetBytePtr(data), CFDataGetLength(data), kSecCodeMagicEntitlement);
CFDictionaryAddValue(parameters, kSecCodeSignerEntitlements, CFTempData(*(BlobCore*)wrap));
::free(wrap);
} else {
const BlobCore *blob = reinterpret_cast<const BlobCore *>(CFDataGetBytePtr(data));
if (blob->magic() != kSecCodeMagicEntitlement)
note(0, "%s: unrecognized blob type (accepting blindly)", entitlements);
if (blob->length() != CFDataGetLength(data))
fail("%s: invalid length in entitlement blob", entitlements);
CFDictionaryAddValue(parameters, kSecCodeSignerEntitlements, CFTempData(*blob));
}
} else
fail("%s: cannot read entitlement data", entitlements);
}
if (dryrun)
CFDictionaryAddValue(parameters, kSecCodeSignerDryRun, kCFBooleanTrue);
MacOSError::check(SecCodeSignerCreate(parameters, flags, &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 || detachedDb)
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);
}
CFCopyRef<SecCodeSignerRef> currentSigner = signerRef; if (preserveMetadata) {
CFRef<CFMutableDictionaryRef> param = CFDictionaryCreateMutableCopy(NULL, 0, parameters);
if (dict && !CFDictionaryGetValue(param, kSecCodeSignerRequirements))
if (CFTypeRef ireqs = CFDictionaryGetValue(dict, kSecCodeInfoRequirementData))
CFDictionaryAddValue(param, kSecCodeSignerRequirements, ireqs);
if (dict && !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");
}