if (CFRef<CFDataRef> infoData = rep->component(cdInfoSlot))
infoDict.take(makeCFDictionaryFrom(infoData));
- uint32_t inherit = code->isSigned() ? state.mPreserveMetadata : 0;
+ uint32_t inherit = 0;
+
+ if (code->isSigned() && (code->codeDirectory(false)->flags & kSecCodeSignatureLinkerSigned) == 0) {
+ inherit = state.mPreserveMetadata;
+ }
// work out the canonical identifier
identifier = state.mIdentifier;
- if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier))
+ if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier)) {
identifier = code->identifier();
+ }
if (identifier.empty()) {
identifier = rep->recommendedIdentifier(*this);
if (identifier.find('.') == string::npos)
entitlements = state.mEntitlementData;
if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements))
entitlements = code->component(cdEntitlementSlot);
-
- generateEntitlementDER = signingFlags() & kSecCSSignGenerateEntitlementDER;
// work out the CodeDirectory flags word
bool haveCdFlags = false;
if (!(signingFlags() & kSecCSSignV1)) {
CFCopyRef<CFDictionaryRef> rules2 = cfget<CFDictionaryRef>(rulesDict, "rules2");
if (!rules2) {
- // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules,
- // because the default weight, according to ResourceBuilder::addRule(), is 1).
+ // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules,
+ // because the default weight, according to ResourceBuilder::addRule(), is 1).
// V1 rules typically do not cover these places so we'll prevail, but if they do, we defer to them.
- rules2 = cfmake<CFDictionaryRef>("{+%O"
+ rules2.take(cfmake<CFDictionaryRef>("{+%O"
"'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=0}" // exclude dynamic repositories
- "}", rules);
+ "}", rules));
}
Dispatch::Group group;
resources.scan(^(FTSENT *ent, uint32_t ruleFlags, const std::string relpath, Rule *rule) {
bool isSymlink = (ent->fts_info == FTS_SL);
+ bool isNested = (ruleFlags & ResourceBuilder::nested);
const std::string path(ent->fts_path);
const std::string accpath(ent->fts_accpath);
this->state.mLimitedAsync->perform(groupRef, ^{
CFRef<CFMutableDictionaryRef> seal;
- if (ruleFlags & ResourceBuilder::nested) {
+ if (isNested) {
seal.take(signNested(path, relpath));
} else if (isSymlink) {
char target[PATH_MAX];
} else {
seal.take(resources.hashFile(accpath.c_str(), digestAlgorithms(), signingFlags() & kSecCSSignStrictPreflight));
}
+ if (seal.get() == NULL) {
+ secerror("Failed to generate sealed resource: %d, %d, %s", isNested, isSymlink, accpath.c_str());
+ MacOSError::throwMe(errSecCSBadResource);
+ }
if (ruleFlags & ResourceBuilder::optional)
CFDictionaryAddValue(seal, CFSTR("optional"), kCFBooleanTrue);
CFTypeRef hash;
if (state.mPreserveAFSC)
writer->setPreserveAFSC(state.mPreserveAFSC);
- auto_ptr<ArchEditor> editor(state.mDetached
+ unique_ptr<ArchEditor> editor(state.mDetached
? static_cast<ArchEditor *>(new BlobEditor(*fat, *this))
: new MachOEditor(writer, *fat, this->digestAlgorithms(), rep->mainExecutablePath()));
assert(editor->count() > 0);
MacOSError::throwMe(errSecCSBadLVArch);
}
}
+
+ bool generateEntitlementDER = false;
+ if (signingFlags() & kSecCSSignGenerateEntitlementDER) {
+ generateEntitlementDER = true;
+ } else {
+ uint32_t platform = arch.source->platform();
+ switch (platform) {
+ case PLATFORM_WATCHOS:
+ case PLATFORM_BRIDGEOS:
+ generateEntitlementDER = false;
+ break;
+ default:
+ generateEntitlementDER = true;
+ break;
+ }
+ }
bool mainBinary = arch.source.get()->type() == MH_EXECUTE;
arch.source->offset(), arch.source->signingExtent(),
mainBinary, rep->execSegBase(&(arch.architecture)), rep->execSegLimit(&(arch.architecture)),
unsigned(digestAlgorithms().size()-1),
- preEncryptHashMaps[arch.architecture], runtimeVersionToUse);
+ preEncryptHashMaps[arch.architecture], runtimeVersionToUse, generateEntitlementDER);
});
}
rep->execSegBase(NULL), rep->execSegLimit(NULL),
unsigned(digestAlgorithms().size()-1),
preEncryptHashMaps[preEncryptMainArch], // Only one map, the default.
- (cdFlags & kSecCodeSignatureRuntime) ? state.mRuntimeVersionOverride : 0);
+ (cdFlags & kSecCodeSignatureRuntime) ? state.mRuntimeVersionOverride : 0,
+ signingFlags() & kSecCSSignGenerateEntitlementDER);
CodeDirectory *cd = builder.build();
if (!state.mDryRun)
bool mainBinary, size_t execSegBase, size_t execSegLimit,
unsigned alternateDigestCount,
PreEncryptHashMap const &preEncryptHashMap,
- uint32_t runtimeVersion)
+ uint32_t runtimeVersion, bool generateEntitlementDER)
{
// fill the CodeDirectory
builder.executable(rep->mainExecutablePath(), pagesize, offset, length);