]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_codesigning/lib/resources.cpp
Security-59306.61.1.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / resources.cpp
index 490b1e07bb378d6dc4ca690dc3752b68d46078c7..221e298472d765f72c3d20c6667c5bd4665de34a 100644 (file)
@@ -74,7 +74,7 @@ ResourceBuilder::ResourceBuilder(const std::string &root, const std::string &rel
                UnixError::throwMe();
        mRelBase = realroot;
        if (mRoot != mRelBase && mRelBase != mRoot + "/Contents")
                UnixError::throwMe();
        mRelBase = realroot;
        if (mRoot != mRelBase && mRelBase != mRoot + "/Contents")
-               MacOSError::throwMe(errSecCSInternalError);
+               MacOSError::throwMe(errSecCSBadBundleFormat);
        const char * paths[2] = { mRoot.c_str(), NULL };
        mFTS = fts_open((char * const *)paths, FTS_PHYSICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
        if (!mFTS)
        const char * paths[2] = { mRoot.c_str(), NULL };
        mFTS = fts_open((char * const *)paths, FTS_PHYSICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
        if (!mFTS)
@@ -138,10 +138,15 @@ static bool findStringEndingNoCase(const char *path, const char * end)
 void ResourceBuilder::scan(Scanner next)
 {
        bool first = true;
 void ResourceBuilder::scan(Scanner next)
 {
        bool first = true;
-    
+
        while (FTSENT *ent = fts_read(mFTS)) {
                static const char ds_store[] = ".DS_Store";
        while (FTSENT *ent = fts_read(mFTS)) {
                static const char ds_store[] = ".DS_Store";
-               const char *relpath = ent->fts_path + mRoot.size() + 1; // skip prefix + "/"
+               const char *relpath = ent->fts_path + mRoot.size(); // skip prefix
+
+               if (strlen(relpath) > 0) {
+                       relpath += 1;   // skip "/"
+               }
+
                std::string rp;
                if (mRelBase != mRoot) {
                        assert(mRelBase == mRoot + "/Contents");
                std::string rp;
                if (mRelBase != mRoot) {
                        assert(mRelBase == mRoot + "/Contents");
@@ -152,7 +157,7 @@ void ResourceBuilder::scan(Scanner next)
                }
                switch (ent->fts_info) {
                case FTS_F:
                }
                switch (ent->fts_info) {
                case FTS_F:
-                       secdebug("rdirenum", "file %s", ent->fts_path);
+                       secinfo("rdirenum", "file %s", ent->fts_path);
                        GKBIS_Num_files++;
                 
                        // These are checks for the gatekeeper collection
                        GKBIS_Num_files++;
                 
                        // These are checks for the gatekeeper collection
@@ -169,7 +174,7 @@ void ResourceBuilder::scan(Scanner next)
                        break;
                case FTS_SL:
                        // symlinks cannot ever be nested code, so quietly convert to resource file
                        break;
                case FTS_SL:
                        // symlinks cannot ever be nested code, so quietly convert to resource file
-                       secdebug("rdirenum", "symlink %s", ent->fts_path);
+                       secinfo("rdirenum", "symlink %s", ent->fts_path);
                        GKBIS_Num_symlinks++;
 
                        if (strcasecmp(ent->fts_name, ds_store) == 0)
                        GKBIS_Num_symlinks++;
 
                        if (strcasecmp(ent->fts_name, ds_store) == 0)
@@ -180,10 +185,10 @@ void ResourceBuilder::scan(Scanner next)
                                        next(ent, rule->flags & ~nested, string(relpath), rule);
                        break;
                case FTS_D:
                                        next(ent, rule->flags & ~nested, string(relpath), rule);
                        break;
                case FTS_D:
-                       secdebug("rdirenum", "entering %s", ent->fts_path);
+                       secinfo("rdirenum", "entering %s", ent->fts_path);
                        GKBIS_Num_dirs++;
 
                        GKBIS_Num_dirs++;
 
-                       if (!first) {   // skip root directory (relpath invalid)
+                       if (!first) {   // skip root directory
                                if (Rule *rule = findRule(relpath)) {
                                        if (rule->flags & nested) {
                                                if (strchr(ent->fts_name, '.')) {       // nested, has extension -> treat as nested bundle
                                if (Rule *rule = findRule(relpath)) {
                                        if (rule->flags & nested) {
                                                if (strchr(ent->fts_name, '.')) {       // nested, has extension -> treat as nested bundle
@@ -203,15 +208,15 @@ void ResourceBuilder::scan(Scanner next)
 
                        break;
                case FTS_DP:
 
                        break;
                case FTS_DP:
-                       secdebug("rdirenum", "leaving %s", ent->fts_path);
+                       secinfo("rdirenum", "leaving %s", ent->fts_path);
                        break;
                case FTS_DNR:
                        break;
                case FTS_DNR:
-                       secdebug("rdirenum", "cannot read directory %s", ent->fts_path);
+                       secinfo("rdirenum", "cannot read directory %s", ent->fts_path);
                        if (mCheckUnreadable)
                                MacOSError::throwMe(errSecCSSignatureNotVerifiable);
                        break;
                default:
                        if (mCheckUnreadable)
                                MacOSError::throwMe(errSecCSSignatureNotVerifiable);
                        break;
                default:
-                       secdebug("rdirenum", "type %d (errno %d): %s",
+                       secinfo("rdirenum", "type %d (errno %d): %s",
                                ent->fts_info, ent->fts_errno, ent->fts_path);
                        if (mCheckUnknownType)
                                MacOSError::throwMe(errSecCSResourceNotSupported);
                                ent->fts_info, ent->fts_errno, ent->fts_path);
                        if (mCheckUnknownType)
                                MacOSError::throwMe(errSecCSResourceNotSupported);
@@ -248,21 +253,28 @@ bool ResourceBuilder::includes(string path) const
 ResourceBuilder::Rule *ResourceBuilder::findRule(string path) const
 {
        Rule *bestRule = NULL;
 ResourceBuilder::Rule *ResourceBuilder::findRule(string path) const
 {
        Rule *bestRule = NULL;
-       secdebug("rscan", "test %s", path.c_str());
+       secinfo("rscan", "test %s", path.c_str());
        for (Rules::const_iterator it = mRules.begin(); it != mRules.end(); ++it) {
                Rule *rule = *it;
        for (Rules::const_iterator it = mRules.begin(); it != mRules.end(); ++it) {
                Rule *rule = *it;
-               secdebug("rscan", "try %s", rule->source.c_str());
+               secinfo("rscan", "try %s", rule->source.c_str());
                if (rule->match(path.c_str())) {
                if (rule->match(path.c_str())) {
-                       secdebug("rscan", "match");
+                       secinfo("rscan", "match");
                        if (rule->flags & exclusion) {
                        if (rule->flags & exclusion) {
-                               secdebug("rscan", "excluded");
+                               secinfo("rscan", "excluded");
                                return rule;
                        }
                        if (!bestRule || rule->weight > bestRule->weight)
                                bestRule = rule;
                                return rule;
                        }
                        if (!bestRule || rule->weight > bestRule->weight)
                                bestRule = rule;
+
+
+#if TARGET_OS_WATCH
+/* rdar://problem/30517969 */
+                       if (bestRule && bestRule->weight == rule->weight && !(bestRule->flags & omitted) && (rule->flags & omitted))
+                               bestRule = rule;
+#endif
                }
        }
                }
        }
-       secdebug("rscan", "choosing %s (%d,0x%x)",
+       secinfo("rscan", "choosing %s (%d,0x%x)",
                bestRule ? bestRule->source.c_str() : "NOTHING",
                bestRule ? bestRule->weight : 0,
                bestRule ? bestRule->flags : 0);
                bestRule ? bestRule->source.c_str() : "NOTHING",
                bestRule ? bestRule->weight : 0,
                bestRule ? bestRule->flags : 0);
@@ -279,26 +291,30 @@ CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorit
        fd.fcntl(F_NOCACHE, true);              // turn off page caching (one-pass)
        RefPointer<DynamicHash> hasher(CodeDirectory::hashFor(type));
        hashFileData(fd, hasher.get());
        fd.fcntl(F_NOCACHE, true);              // turn off page caching (one-pass)
        RefPointer<DynamicHash> hasher(CodeDirectory::hashFor(type));
        hashFileData(fd, hasher.get());
-       Hashing::Byte digest[hasher->digestLength()];
-       hasher->finish(digest);
-       return CFDataCreate(NULL, digest, sizeof(digest));
+       vector<Hashing::Byte> digest_vector(hasher->digestLength());
+       hasher->finish(digest_vector.data());
+       return CFDataCreate(NULL, digest_vector.data(),
+                                               digest_vector.size() * sizeof(Hashing::Byte));
 }
 
 
 //
 // Hash a file to multiple hash types and return a dictionary suitable to form a resource seal
 //
 }
 
 
 //
 // Hash a file to multiple hash types and return a dictionary suitable to form a resource seal
 //
-CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorithms types)
+CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorithms types, bool strictCheck)
 {
        UnixPlusPlus::AutoFileDesc fd(path);
        fd.fcntl(F_NOCACHE, true);              // turn off page caching (one-pass)
 {
        UnixPlusPlus::AutoFileDesc fd(path);
        fd.fcntl(F_NOCACHE, true);              // turn off page caching (one-pass)
+       if (strictCheck)
+               if (fd.hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd.hasExtendedAttribute(XATTR_FINDERINFO_NAME))
+                       MacOSError::throwMe(errSecCSInvalidAssociatedFileData);
        CFRef<CFMutableDictionaryRef> result = makeCFMutableDictionary();
        CFMutableDictionaryRef resultRef = result;
        CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) {
                size_t length = hasher->digestLength();
        CFRef<CFMutableDictionaryRef> result = makeCFMutableDictionary();
        CFMutableDictionaryRef resultRef = result;
        CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) {
                size_t length = hasher->digestLength();
-               Hashing::Byte digest[length];
-               hasher->finish(digest);
-               CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest, length));
+               vector<Hashing::Byte> digest_vector(length);
+               hasher->finish(digest_vector.data());
+               CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest_vector.data(), length));
        });
        return result.yield();
 }
        });
        return result.yield();
 }
@@ -325,7 +341,7 @@ ResourceBuilder::Rule::Rule(const std::string &pattern, unsigned w, uint32_t f)
 {
        if (::regcomp(this, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) //@@@ REG_ICASE?
                MacOSError::throwMe(errSecCSResourceRulesInvalid);
 {
        if (::regcomp(this, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) //@@@ REG_ICASE?
                MacOSError::throwMe(errSecCSResourceRulesInvalid);
-       secdebug("csresource", "%p rule %s added (weight %d, flags 0x%x)",
+       secinfo("csresource", "%p rule %s added (weight %d, flags 0x%x)",
                this, pattern.c_str(), w, f);
 }
 
                this, pattern.c_str(), w, f);
 }
 
@@ -352,7 +368,7 @@ std::string ResourceBuilder::escapeRE(const std::string &s)
        string r;
        for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
                char c = *it;
        string r;
        for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
                char c = *it;
-               if (strchr("\\[]{}().+*?", c))
+               if (strchr("\\[]{}().+*?^$|", c))
                        r.push_back('\\');
                r.push_back(c);
        }
                        r.push_back('\\');
                r.push_back(c);
        }
@@ -396,6 +412,8 @@ const Hashing::Byte *ResourceSeal::hash(CodeDirectory::HashAlgorithm type) const
 {
        std::string name = ResourceBuilder::hashName(type);
        CFTypeRef hash = CFDictionaryGetValue(mDict, CFTempString(name));
 {
        std::string name = ResourceBuilder::hashName(type);
        CFTypeRef hash = CFDictionaryGetValue(mDict, CFTempString(name));
+       if (hash == NULL)       // pre-agility fallback
+               hash = CFDictionaryGetValue(mDict, CFSTR("hash"));
        if (hash == NULL || CFGetTypeID(hash) != CFDataGetTypeID())
                MacOSError::throwMe(errSecCSResourcesInvalid);
        return CFDataGetBytePtr(CFDataRef(hash));
        if (hash == NULL || CFGetTypeID(hash) != CFDataGetTypeID())
                MacOSError::throwMe(errSecCSResourcesInvalid);
        return CFDataGetBytePtr(CFDataRef(hash));