]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_codesigning/lib/signer.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / signer.cpp
index b5f07c40ce5e92c738ddcf10a4d5c088d84d6e71..576459c8e4c41e005ac0b707584ab8ea72f2b8f5 100644 (file)
@@ -143,12 +143,17 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags)
        if (CFRef<CFDataRef> infoData = rep->component(cdInfoSlot))
                infoDict.take(makeCFDictionaryFrom(infoData));
        
        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;
 
        // work out the canonical identifier
        identifier = state.mIdentifier;
-       if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier))
+       if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier)) {
                identifier = code->identifier();
                identifier = code->identifier();
+       }
        if (identifier.empty()) {
                identifier = rep->recommendedIdentifier(*this);
                if (identifier.find('.') == string::npos)
        if (identifier.empty()) {
                identifier = rep->recommendedIdentifier(*this);
                if (identifier.find('.') == string::npos)
@@ -174,8 +179,6 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags)
        entitlements = state.mEntitlementData;
        if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements))
                entitlements = code->component(cdEntitlementSlot);
        entitlements = state.mEntitlementData;
        if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements))
                entitlements = code->component(cdEntitlementSlot);
-
-       generateEntitlementDER = signingFlags() & kSecCSSignGenerateEntitlementDER;
        
        // work out the CodeDirectory flags word
        bool haveCdFlags = false;
        
        // work out the CodeDirectory flags word
        bool haveCdFlags = false;
@@ -409,12 +412,12 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase
        if (!(signingFlags() & kSecCSSignV1)) {
                CFCopyRef<CFDictionaryRef> rules2 = cfget<CFDictionaryRef>(rulesDict, "rules2");
                if (!rules2) {
        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.
                        // 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
                                "'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=0}" // exclude dynamic repositories
-                       "}", rules);
+                       "}", rules));
                }
 
                Dispatch::Group group;
                }
 
                Dispatch::Group group;
@@ -429,11 +432,12 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase
 
                resources.scan(^(FTSENT *ent, uint32_t ruleFlags, const std::string relpath, Rule *rule) {
                        bool isSymlink = (ent->fts_info == FTS_SL);
 
                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;
                        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];
                                        seal.take(signNested(path, relpath));
                                } else if (isSymlink) {
                                        char target[PATH_MAX];
@@ -445,6 +449,10 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase
                                } else {
                                        seal.take(resources.hashFile(accpath.c_str(), digestAlgorithms(), signingFlags() & kSecCSSignStrictPreflight));
                                }
                                } 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 (ruleFlags & ResourceBuilder::optional)
                                        CFDictionaryAddValue(seal, CFSTR("optional"), kCFBooleanTrue);
                                CFTypeRef hash;
@@ -535,7 +543,7 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context
        if (state.mPreserveAFSC)
                writer->setPreserveAFSC(state.mPreserveAFSC);
 
        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);
                ? static_cast<ArchEditor *>(new BlobEditor(*fat, *this))
                : new MachOEditor(writer, *fat, this->digestAlgorithms(), rep->mainExecutablePath()));
        assert(editor->count() > 0);
@@ -553,6 +561,22 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context
                                MacOSError::throwMe(errSecCSBadLVArch);
                        }
                }
                                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;
 
 
                bool mainBinary = arch.source.get()->type() == MH_EXECUTE;
 
@@ -576,7 +600,7 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context
                                                 arch.source->offset(), arch.source->signingExtent(),
                                                 mainBinary, rep->execSegBase(&(arch.architecture)), rep->execSegLimit(&(arch.architecture)),
                                                 unsigned(digestAlgorithms().size()-1),
                                                 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);
                        });
                }
        
                        });
                }
        
@@ -655,7 +679,8 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context
                                 rep->execSegBase(NULL), rep->execSegLimit(NULL),
                                 unsigned(digestAlgorithms().size()-1),
                                 preEncryptHashMaps[preEncryptMainArch], // Only one map, the default.
                                 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)
                
                CodeDirectory *cd = builder.build();
                if (!state.mDryRun)
@@ -703,7 +728,7 @@ void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::W
                                                                         bool mainBinary, size_t execSegBase, size_t execSegLimit,
                                                                         unsigned alternateDigestCount,
                                                                         PreEncryptHashMap const &preEncryptHashMap,
                                                                         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);
 {
        // fill the CodeDirectory
        builder.executable(rep->mainExecutablePath(), pagesize, offset, length);
@@ -787,7 +812,7 @@ CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd,
        // generate CMS signature
        CFRef<CMSEncoderRef> cms;
        MacOSError::check(CMSEncoderCreate(&cms.aref()));
        // generate CMS signature
        CFRef<CMSEncoderRef> cms;
        MacOSError::check(CMSEncoderCreate(&cms.aref()));
-       MacOSError::check(CMSEncoderSetCertificateChainMode(cms, kCMSCertificateChainWithRoot));
+       MacOSError::check(CMSEncoderSetCertificateChainMode(cms, kCMSCertificateChainWithRootOrFail));
        CMSEncoderAddSigners(cms, state.mSigner);
        CMSEncoderSetSignerAlgorithm(cms, kCMSEncoderDigestAlgorithmSHA256);
        MacOSError::check(CMSEncoderSetHasDetachedContent(cms, true));
        CMSEncoderAddSigners(cms, state.mSigner);
        CMSEncoderSetSignerAlgorithm(cms, kCMSEncoderDigestAlgorithmSHA256);
        MacOSError::check(CMSEncoderSetHasDetachedContent(cms, true));