X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..ce3c8656732c924baf7e88df75eab50891bdc471:/OSX/libsecurity_codesigning/lib/policyengine.cpp?ds=inline diff --git a/OSX/libsecurity_codesigning/lib/policyengine.cpp b/OSX/libsecurity_codesigning/lib/policyengine.cpp index f5b9cb29..3f49aebd 100644 --- a/OSX/libsecurity_codesigning/lib/policyengine.cpp +++ b/OSX/libsecurity_codesigning/lib/policyengine.cpp @@ -92,8 +92,7 @@ void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlag // perform the evaluation EvaluationTask *evaluationTask = evaluationManager->evaluationTask(this, path, type, flags, context, result); - evaluationManager->waitForCompletion(evaluationTask, flags, result); - evaluationManager->removeTask(evaluationTask); + evaluationManager->finalizeTask(evaluationTask, flags, result); // if rejected, reset the automatic rearm timer if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == kCFBooleanFalse) @@ -101,12 +100,11 @@ void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlag } -static std::string createWhitelistScreen(char type, SHA1 &hash) +static std::string createWhitelistScreen(char type, const Byte *digest, size_t length) { - SHA1::Digest digest; - hash.finish(digest); - char buffer[2*SHA1::digestLength + 2] = { type }; - for (size_t n = 0; n < SHA1::digestLength; n++) + char buffer[2*length + 2]; + buffer[0] = type; + for (size_t n = 0; n < length; n++) sprintf(buffer + 1 + 2*n, "%02.2x", digest[n]); return buffer; } @@ -236,13 +234,24 @@ bool PolicyEngine::temporarySigning(SecStaticCodeRef code, AuthorityType type, C if (CFRef info = rep->component(cdInfoSlot)) { SHA1 hash; hash.update(CFDataGetBytePtr(info), CFDataGetLength(info)); - screen = createWhitelistScreen('I', hash); + SHA1::Digest digest; + hash.finish(digest); + screen = createWhitelistScreen('I', digest, sizeof(digest)); + } else if (CFRef repSpecific = rep->component(cdRepSpecificSlot)) { + // got invented after SHA-1 deprecation, so we'll use SHA256, which is the new default + CCHashInstance hash(kCCDigestSHA256); + hash.update(CFDataGetBytePtr(repSpecific), CFDataGetLength(repSpecific)); + Byte digest[256/8]; + hash.finish(digest); + screen = createWhitelistScreen('R', digest, sizeof(digest)); } else if (rep->mainExecutableImage()) { screen = "N"; } else { SHA1 hash; hashFileData(rep->mainExecutablePath().c_str(), &hash); - screen = createWhitelistScreen('M', hash); + SHA1::Digest digest; + hash.finish(digest); + screen = createWhitelistScreen('M', digest, sizeof(digest)); } SQLite::Statement query(*this, "SELECT flags FROM authority " @@ -261,7 +270,8 @@ bool PolicyEngine::temporarySigning(SecStaticCodeRef code, AuthorityType type, C try { // ad-hoc sign the code and attach the signature CFRef signature = CFDataCreateMutable(NULL, 0); - CFTemp arguments("{%O=%O, %O=#N}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity); + CFTemp arguments("{%O=%O, %O=#N, %O=%d}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity, + kSecCodeSignerDigestAlgorithm, (matchFlags & kAuthorityFlagWhitelistSHA256) ? kSecCodeSignatureHashSHA256 : kSecCodeSignatureHashSHA1); CFRef signer; MacOSError::check(SecCodeSignerCreate(arguments, (matchFlags & kAuthorityFlagWhitelistV2) ? kSecCSSignOpaque : kSecCSSignV1, &signer.aref())); MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); @@ -312,6 +322,15 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment if (qtn.flag(QTN_FLAG_HARD)) MacOSError::throwMe(errSecCSFileHardQuarantined); + // hack: if caller passed a UTI, use that to turn off app-only checks for some well-known ones + bool appOk = false; + if (CFStringRef uti = CFStringRef(CFDictionaryGetValue(context, kSecAssessmentContextKeyUTI))) { + appOk = CFEqual(uti, CFSTR("com.apple.systempreference.prefpane")) + || CFEqual(uti, CFSTR("com.apple.systempreference.screen-saver")) + || CFEqual(uti, CFSTR("com.apple.systempreference.screen-slide-saver")) + || CFEqual(uti, CFSTR("com.apple.menu-extra")); + } + CFCopyRef code; MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref())); @@ -366,7 +385,10 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment })); // go for it! - switch (rc = SecStaticCodeCheckValidity(code, validationFlags | kSecCSCheckNestedCode | kSecCSRestrictSymlinks | kSecCSReportProgress, NULL)) { + SecCSFlags topFlags = validationFlags | kSecCSCheckNestedCode | kSecCSRestrictSymlinks | kSecCSReportProgress; + if (type == kAuthorityExecute && !appOk) + topFlags |= kSecCSRestrictToAppLike; + switch (rc = SecStaticCodeCheckValidity(code, topFlags, NULL)) { case errSecSuccess: // continue below break; case errSecCSUnsigned: @@ -386,6 +408,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment case errSecCSUnsealedAppRoot: case errSecCSUnsealedFrameworkRoot: case errSecCSInvalidSymlink: + case errSecCSNotAppLike: { // consult the whitelist bool allow = false; @@ -605,7 +628,7 @@ void PolicyEngine::evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDi addAuthority(flags, result, "Prior Assessment"); } else if (!overrideAssessment(flags)) { // no need to do more work if we're off try { - evaluateCode(path, kAuthorityExecute, flags, context, result, false); + evaluateCode(path, kAuthorityOpenDoc, flags, context, result, true); } catch (...) { // some documents can't be code signed, so this may be quite benign } @@ -716,7 +739,7 @@ CFDictionaryRef PolicyEngine::add(CFTypeRef inTarget, AuthorityType type, SecAss bool allow = true; double expires = never; string remarks; - SQLite::uint64 dbFlags = kAuthorityFlagWhitelistV2; + SQLite::uint64 dbFlags = kAuthorityFlagWhitelistV2 | kAuthorityFlagWhitelistSHA256; if (CFNumberRef pri = ctx.get(kSecAssessmentUpdateKeyPriority)) CFNumberGetValue(pri, kCFNumberDoubleType, &priority); @@ -1037,7 +1060,7 @@ void PolicyEngine::normalizeTarget(CFRef &target, AuthorityType type, } break; case errSecCSUnsigned: - if (signUnsigned && temporarySigning(code, type, path, kAuthorityFlagWhitelistV2)) { // ad-hoc signed the code temporarily + if (signUnsigned && temporarySigning(code, type, path, kAuthorityFlagWhitelistV2 | kAuthorityFlagWhitelistSHA256)) { // ad-hoc sign the code temporarily MacOSError::check(SecCodeCopyDesignatedRequirement(code, kSecCSDefaultFlags, (SecRequirementRef *)&target.aref())); CFRef info; MacOSError::check(SecCodeCopySigningInformation(code, kSecCSInternalInformation, &info.aref()));