From 313fa17b58b78d3c26fb986be9e8fce975cec88c Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 10 Sep 2012 21:05:25 +0000 Subject: [PATCH] Security-55179.1.tar.gz --- Security.xcodeproj/project.pbxproj | 28 +++ lib/Info-Security.plist | 2 +- lib/plugins/csparser-Info.plist | 2 +- libsecurity_cdsa_client/lib/cryptoclient.cpp | 1 + libsecurity_cdsa_client/lib/cryptoclient.h | 1 + libsecurity_cdsa_client/lib/cspclient.cpp | 4 + libsecurity_cdsa_client/lib/cspclient.h | 1 + libsecurity_cdsa_client/lib/cssmclient.cpp | 6 + libsecurity_cdsa_client/lib/cssmclient.h | 1 + libsecurity_cdsa_client/lib/dlclient.cpp | 12 ++ libsecurity_cdsa_client/lib/dlclient.h | 2 + libsecurity_cdsa_client/lib/genkey.cpp | 1 + libsecurity_cdsa_client/lib/keyclient.cpp | 3 + libsecurity_cdsa_client/lib/macclient.cpp | 1 + libsecurity_cdsa_client/lib/multidldb.cpp | 2 + libsecurity_cdsa_client/lib/signclient.cpp | 1 + libsecurity_codesigning/dtrace/sp-watch.d | 18 +- .../gke/com.apple.gkreport.plist | 18 ++ libsecurity_codesigning/gke/gkgenerate | 17 +- libsecurity_codesigning/gke/gkreport | 11 + libsecurity_codesigning/gke/gkunpack.cpp | 31 +++ libsecurity_codesigning/lib/CSCommon.h | 2 +- libsecurity_codesigning/lib/SecAssessment.cpp | 16 +- libsecurity_codesigning/lib/StaticCode.cpp | 25 +++ libsecurity_codesigning/lib/codedirectory.cpp | 27 +++ libsecurity_codesigning/lib/codedirectory.h | 8 + libsecurity_codesigning/lib/csutilities.cpp | 35 ++++ libsecurity_codesigning/lib/csutilities.h | 22 +- libsecurity_codesigning/lib/drmaker.cpp | 2 +- libsecurity_codesigning/lib/policydb.cpp | 9 +- libsecurity_codesigning/lib/policyengine.cpp | 141 +++++++++++-- libsecurity_codesigning/lib/policyengine.h | 3 +- libsecurity_codesigning/lib/reqinterp.cpp | 2 +- libsecurity_codesigning/lib/requirement.cpp | 16 +- libsecurity_codesigning/lib/requirement.h | 1 - libsecurity_codesigning/lib/syspolicy.sql | 7 +- .../project.pbxproj | 197 +++++++++++++++++- libsecurity_ssl/lib/cipherSpecs.c | 2 +- libsecurity_ssl/lib/tls1Callouts.c | 24 ++- libsecurity_utilities/lib/sqlite++.cpp | 7 +- 40 files changed, 623 insertions(+), 86 deletions(-) create mode 100644 libsecurity_codesigning/gke/com.apple.gkreport.plist create mode 100755 libsecurity_codesigning/gke/gkreport create mode 100644 libsecurity_codesigning/gke/gkunpack.cpp diff --git a/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index 29b940f8..a6d6c969 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -39,6 +39,7 @@ ); dependencies = ( 186F779114E5A00F00434E1F /* PBXTargetDependency */, + C2432A2515C726B50096DB5B /* PBXTargetDependency */, ); name = Security_executables; productName = Other; @@ -976,6 +977,20 @@ remoteGlobalIDString = 52200F8F14F2B88000F7F6E7; remoteInfo = XPCTimeStampingService; }; + C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C209696015BF52040093035F; + remoteInfo = gkunpack; + }; + C2432A2415C726B50096DB5B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C209695F15BF52040093035F; + remoteInfo = gkunpack; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -1865,6 +1880,7 @@ 1879B666146DE757007E536C /* libsecurity_codesigning.a */, 1879B66A146DE757007E536C /* libintegrity.a */, 1879B66C146DE757007E536C /* libcodehost.a */, + C2432A0815C7112A0096DB5B /* gkunpack */, ); name = Products; sourceTree = ""; @@ -2776,6 +2792,13 @@ remoteRef = 52B5A8F5151928B400664F11 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + C2432A0815C7112A0096DB5B /* gkunpack */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = gkunpack; + remoteRef = C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ @@ -3143,6 +3166,11 @@ name = XPCTimeStampingService; targetProxy = 529FF21F1523BD7F0029D842 /* PBXContainerItemProxy */; }; + C2432A2515C726B50096DB5B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = gkunpack; + targetProxy = C2432A2415C726B50096DB5B /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ diff --git a/lib/Info-Security.plist b/lib/Info-Security.plist index 99d3ceba..e8eda2ec 100644 --- a/lib/Info-Security.plist +++ b/lib/Info-Security.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 55178.0.1 + 55179.1 diff --git a/lib/plugins/csparser-Info.plist b/lib/plugins/csparser-Info.plist index a17c62bc..8636a5fc 100644 --- a/lib/plugins/csparser-Info.plist +++ b/lib/plugins/csparser-Info.plist @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 55178.0.1 + 55179.1 CFBundleShortVersionString 3.0 diff --git a/libsecurity_cdsa_client/lib/cryptoclient.cpp b/libsecurity_cdsa_client/lib/cryptoclient.cpp index e271f311..3a4bb7e7 100644 --- a/libsecurity_cdsa_client/lib/cryptoclient.cpp +++ b/libsecurity_cdsa_client/lib/cryptoclient.cpp @@ -40,6 +40,7 @@ void Crypt::key(const Key &key) void Crypt::activate() { + StLock _(mActivateMutex); if (!mActive) { // Key is required unless we have a NULL algorithm (cleartext wrap/unwrap), diff --git a/libsecurity_cdsa_client/lib/cryptoclient.h b/libsecurity_cdsa_client/lib/cryptoclient.h index 18ab4b79..707bcd32 100644 --- a/libsecurity_cdsa_client/lib/cryptoclient.h +++ b/libsecurity_cdsa_client/lib/cryptoclient.h @@ -56,6 +56,7 @@ protected: Key mKey; const CssmData *mInitVector; CSSM_PADDING mPadding; + RecursiveMutex mActivateMutex; }; diff --git a/libsecurity_cdsa_client/lib/cspclient.cpp b/libsecurity_cdsa_client/lib/cspclient.cpp index 8e4a313f..8f189336 100644 --- a/libsecurity_cdsa_client/lib/cspclient.cpp +++ b/libsecurity_cdsa_client/lib/cspclient.cpp @@ -73,6 +73,7 @@ void Context::init() void Context::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive = false; @@ -175,6 +176,7 @@ PassThrough::operator() (uint32 passThroughId, const void *inData, void **outDat void PassThrough::activate() { + StLock _(mActivateMutex); if (!mActive) { check(CSSM_CSP_CreatePassThroughContext(attachment()->handle(), mKey, &mHandle)); mActive = true; @@ -187,6 +189,7 @@ void PassThrough::activate() // void Digest::activate() { + StLock _(mActivateMutex); if (!mActive) { check(CSSM_CSP_CreateDigestContext(attachment()->handle(), mAlgorithm, &mHandle)); mActive = true; @@ -239,6 +242,7 @@ void Random::size(uint32 sz) void Random::activate() { + StLock _(mActivateMutex); if (!mActive) { check(CSSM_CSP_CreateRandomGenContext(attachment()->handle(), mAlgorithm, mSeed, mSize, &mHandle)); diff --git a/libsecurity_cdsa_client/lib/cspclient.h b/libsecurity_cdsa_client/lib/cspclient.h index 2ffe7210..add128b5 100644 --- a/libsecurity_cdsa_client/lib/cspclient.h +++ b/libsecurity_cdsa_client/lib/cspclient.h @@ -130,6 +130,7 @@ protected: CSSM_CC_HANDLE mHandle; // CSSM CC handle bool mStaged; // staged in progress const AccessCredentials *mCred; // if explicitly set + RecursiveMutex mActivateMutex; }; diff --git a/libsecurity_cdsa_client/lib/cssmclient.cpp b/libsecurity_cdsa_client/lib/cssmclient.cpp index ec3fb44d..a86f3bde 100644 --- a/libsecurity_cdsa_client/lib/cssmclient.cpp +++ b/libsecurity_cdsa_client/lib/cssmclient.cpp @@ -193,6 +193,7 @@ CssmImpl::standard() void CssmImpl::activate() { + StLock _(mActivateMutex); if (!mActive) { // currently, no choices on PVC mode and key hierarchy @@ -213,6 +214,7 @@ CssmImpl::activate() void CssmImpl::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive = false; @@ -396,6 +398,7 @@ ModuleImpl::appNotifyCallback(RawModuleEvents *handler) void ModuleImpl::activate() { + StLock _(mActivateMutex); if (!mActive) { session()->init(); @@ -411,6 +414,7 @@ ModuleImpl::activate() void ModuleImpl::deactivate() { + StLock _(mActivateMutex); if (!isIdle()) Error::throwMe(Error::objectBusy); if (mActive) @@ -463,6 +467,7 @@ AttachmentImpl::make(CSSM_SERVICE_TYPE subserviceType) void AttachmentImpl::activate() { + StLock _(mActivateMutex); if (!mActive) { module()->load(); @@ -483,6 +488,7 @@ AttachmentImpl::activate() void AttachmentImpl::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive = false; diff --git a/libsecurity_cdsa_client/lib/cssmclient.h b/libsecurity_cdsa_client/lib/cssmclient.h index b6b2f321..43fb3141 100644 --- a/libsecurity_cdsa_client/lib/cssmclient.h +++ b/libsecurity_cdsa_client/lib/cssmclient.h @@ -100,6 +100,7 @@ public: protected: bool mActive; // loaded, attached, etc. + RecursiveMutex mActivateMutex; mutable Allocator *mAllocator; // allocator hierarchy (NULL => TBD) template Obj parent() const diff --git a/libsecurity_cdsa_client/lib/dlclient.cpp b/libsecurity_cdsa_client/lib/dlclient.cpp index 3f1d466c..6fa631bf 100644 --- a/libsecurity_cdsa_client/lib/dlclient.cpp +++ b/libsecurity_cdsa_client/lib/dlclient.cpp @@ -111,6 +111,8 @@ DbImpl::open() check(CSSM_DL_DbOpen(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(), mAccessRequest, mAccessCredentials, mOpenParameters, &mHandle.DBHandle)); + + StLock _(mActivateMutex); mActive = true; if (!mAccessCredentials && mDefaultCredentials) @@ -150,6 +152,7 @@ DbImpl::createWithBlob(CssmData &blob) void DbImpl::create() { + StLock _(mActivateMutex); if (mActive) CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS); @@ -176,6 +179,7 @@ DbImpl::create() void DbImpl::close() { + StLock _(mActivateMutex); if (mActive) { check(CSSM_DL_DbClose (mHandle)); @@ -186,6 +190,7 @@ DbImpl::close() void DbImpl::activate() { + StLock _(mActivateMutex); if (!mActive) { if (mDbInfo) @@ -198,6 +203,7 @@ DbImpl::activate() void DbImpl::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive = false; @@ -640,6 +646,8 @@ DbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniq attributes, data, unique); + + StLock _(mActivateMutex); if (result == CSSM_OK) mActive = true; else if (data != NULL) @@ -666,6 +674,7 @@ DbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniq if (result == CSSMERR_DL_ENDOFDATA) { + StLock _(mActivateMutex); mActive = false; return false; } @@ -686,6 +695,7 @@ DbDbCursorImpl::activate() void DbDbCursorImpl::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive = false; @@ -836,12 +846,14 @@ DbUniqueRecordImpl::getWithoutEncryption(DbAttributes *attributes, void DbUniqueRecordImpl::activate() { + StLock _(mActivateMutex); mActive = true; } void DbUniqueRecordImpl::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive = false; diff --git a/libsecurity_cdsa_client/lib/dlclient.h b/libsecurity_cdsa_client/lib/dlclient.h index ae8e0787..2579a428 100644 --- a/libsecurity_cdsa_client/lib/dlclient.h +++ b/libsecurity_cdsa_client/lib/dlclient.h @@ -491,6 +491,7 @@ protected: CSSM_DB_UNIQUE_RECORD_PTR mUniqueId; bool mDestroyID; + RecursiveMutex mActivateMutex; }; class DbUniqueRecord : public Object @@ -547,6 +548,7 @@ protected: private: CSSM_HANDLE mResultsHandle; + RecursiveMutex mActivateMutex; }; } // end namespace CssmClient diff --git a/libsecurity_cdsa_client/lib/genkey.cpp b/libsecurity_cdsa_client/lib/genkey.cpp index 3e5d52d9..aabcb225 100644 --- a/libsecurity_cdsa_client/lib/genkey.cpp +++ b/libsecurity_cdsa_client/lib/genkey.cpp @@ -39,6 +39,7 @@ GenerateKey::database(const Db &inDb) void GenerateKey::activate() { + StLock _(mActivateMutex); if (!mActive) { check(CSSM_CSP_CreateKeyGenContext(attachment()->handle(), mAlgorithm, diff --git a/libsecurity_cdsa_client/lib/keyclient.cpp b/libsecurity_cdsa_client/lib/keyclient.cpp index 00c738e0..f179e432 100644 --- a/libsecurity_cdsa_client/lib/keyclient.cpp +++ b/libsecurity_cdsa_client/lib/keyclient.cpp @@ -57,6 +57,7 @@ KeyImpl::~KeyImpl() void KeyImpl::deleteKey(const CSSM_ACCESS_CREDENTIALS *cred) { + StLock _(mActivateMutex); if (mActive) { mActive=false; @@ -104,11 +105,13 @@ KeyImpl::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, void KeyImpl::activate() { + StLock _(mActivateMutex); mActive=true; } void KeyImpl::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive=false; diff --git a/libsecurity_cdsa_client/lib/macclient.cpp b/libsecurity_cdsa_client/lib/macclient.cpp index 38c8b6a7..1fdc177a 100644 --- a/libsecurity_cdsa_client/lib/macclient.cpp +++ b/libsecurity_cdsa_client/lib/macclient.cpp @@ -29,6 +29,7 @@ using namespace CssmClient; // void MacContext::activate() { + StLock _(mActivateMutex); if (!mActive) { check(CSSM_CSP_CreateMacContext(attachment()->handle(), mAlgorithm, diff --git a/libsecurity_cdsa_client/lib/multidldb.cpp b/libsecurity_cdsa_client/lib/multidldb.cpp index 71332079..03829193 100644 --- a/libsecurity_cdsa_client/lib/multidldb.cpp +++ b/libsecurity_cdsa_client/lib/multidldb.cpp @@ -210,6 +210,7 @@ MultiDLDbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, void MultiDLDbDbCursorImpl::activate() { + StLock _(mActivateMutex); if (!mActive) { mListRef = multiDLDb()->listRef(); @@ -222,6 +223,7 @@ MultiDLDbDbCursorImpl::activate() void MultiDLDbDbCursorImpl::deactivate() { + StLock _(mActivateMutex); if (mActive) { mActive = false; diff --git a/libsecurity_cdsa_client/lib/signclient.cpp b/libsecurity_cdsa_client/lib/signclient.cpp index 6b5e0377..39c7a02f 100644 --- a/libsecurity_cdsa_client/lib/signclient.cpp +++ b/libsecurity_cdsa_client/lib/signclient.cpp @@ -29,6 +29,7 @@ using namespace CssmClient; // void SigningContext::activate() { + StLock _(mActivateMutex); if (!mActive) { check(CSSM_CSP_CreateSignatureContext(attachment()->handle(), mAlgorithm, diff --git a/libsecurity_codesigning/dtrace/sp-watch.d b/libsecurity_codesigning/dtrace/sp-watch.d index 194d5724..988d938e 100755 --- a/libsecurity_codesigning/dtrace/sp-watch.d +++ b/libsecurity_codesigning/dtrace/sp-watch.d @@ -10,25 +10,27 @@ syspolicy*:::assess-* } self string type; -syspolicy*:::assess-outcome-* / arg1 == 1 / { type = "execute"; } -syspolicy*:::assess-outcome-* / arg1 == 2 / { type = "install"; } +syspolicy*:::assess-outcome-* { self->type = "???"; } +syspolicy*:::assess-outcome-* / arg1 == 1 / { self->type = "execute"; } +syspolicy*:::assess-outcome-* / arg1 == 2 / { self->type = "install"; } +syspolicy*:::assess-outcome-* / arg1 == 3 / { self->type = "open"; } syspolicy*:::assess-outcome-accept { - printf("accept %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg1)); - self->cdhash = copyin(arg2, 20); + printf("accept %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg2)); + self->cdhash = copyin(arg3, 20); } syspolicy*:::assess-outcome-deny { - printf("deny %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg1)); - self->cdhash = copyin(arg2, 20); + printf("deny %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg2)); + self->cdhash = copyin(arg3, 20); } syspolicy*:::assess-outcome-default { - printf("default %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg1)); - self->cdhash = copyin(arg2, 20); + printf("default %s %s;%s", self->type, copyinstr(arg0), copyinstr(arg2)); + self->cdhash = copyin(arg3, 20); } syspolicy*:::assess-outcome-unsigned diff --git a/libsecurity_codesigning/gke/com.apple.gkreport.plist b/libsecurity_codesigning/gke/com.apple.gkreport.plist new file mode 100644 index 00000000..b55efe62 --- /dev/null +++ b/libsecurity_codesigning/gke/com.apple.gkreport.plist @@ -0,0 +1,18 @@ + + + + + Label + com.apple.gkreport + ProgramArguments + + /usr/libexec/gkreport + + StartCalendarInterval + + Minute52 + Hour3 + WeekDay5 + + + diff --git a/libsecurity_codesigning/gke/gkgenerate b/libsecurity_codesigning/gke/gkgenerate index b62383f1..127d9b0c 100755 --- a/libsecurity_codesigning/gke/gkgenerate +++ b/libsecurity_codesigning/gke/gkgenerate @@ -22,7 +22,6 @@ import uuid authfile = "gke.auth" sigfile = "gke.dsig" - # # Usage and fail # @@ -49,6 +48,20 @@ authfile = args.output + ".auth" sigsfile = args.output + ".sigs" +# +# Augment a snippet record +# +def augment(data): + for auth in data.authority.values(): + if auth.path in data.signatures: + signature = data.signatures[auth.path].signature.data + unpack = subprocess.Popen(["/usr/local/bin/gkunpack"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = unpack.communicate(input=signature) + if stderr: + fail("signature unpack failed for %s" % auth.path) + auth.screen = stdout.rstrip(); + + # # Start by collecting authority evidence from the authority records # @@ -57,10 +70,12 @@ sigs = { } for source in args.source: if source[0] == '+': data = plistlib.readPlist(source[1:]) + augment(data) auth.update(data["authority"]) sigs.update(data["signatures"]) else: data = plistlib.readPlist(source) + augment(data) auth.update(data["authority"]) if not auth and not args.empty: diff --git a/libsecurity_codesigning/gke/gkreport b/libsecurity_codesigning/gke/gkreport new file mode 100755 index 00000000..8bf49fa5 --- /dev/null +++ b/libsecurity_codesigning/gke/gkreport @@ -0,0 +1,11 @@ +#!/bin/bash +# +# gkreport - report Gatekeeper state to MessageTracer +# +main=$(/usr/sbin/spctl --status) +gk=$(/usr/sbin/spctl --test-devid-status) +/usr/bin/syslog -s -k \ + com.apple.message.domain com.apple.security.assessment.current_state \ + com.apple.message.signature "$main" \ + com.apple.message.signature2 "$gk" \ + Message "Gatekeeper state $main/$gk" diff --git a/libsecurity_codesigning/gke/gkunpack.cpp b/libsecurity_codesigning/gke/gkunpack.cpp new file mode 100644 index 00000000..11e16cad --- /dev/null +++ b/libsecurity_codesigning/gke/gkunpack.cpp @@ -0,0 +1,31 @@ +// +// gkunpack - an ad-hoc tool for unpacking certain binary data from a detached code signature +// +// gkunpack prescreen_filter_data +// +#include +#include +#include + +using namespace CodeSigning; + + +int main(int argc, const char * argv[]) +{ + if (const EmbeddedSignatureBlob *top = (const EmbeddedSignatureBlob *)BlobCore::readBlob(stdin)) { + if (top->magic() == DetachedSignatureBlob::typeMagic) { // multiple architectures - pick the native one + Architecture local = Architecture::local(); + const EmbeddedSignatureBlob *sig = EmbeddedSignatureBlob::specific(top->find(local.cpuType())); + if (!sig) + sig = EmbeddedSignatureBlob::specific(top->find(local.cpuType() & ~CPU_ARCH_MASK)); + top = sig; + } + if (top) + if (const CodeDirectory *cd = top->find(cdCodeDirectorySlot)) { + printf("%s\n", cd->screeningCode().c_str()); + exit(0); + } + } + fprintf(stderr, "Invalid signature structure\n"); + exit(1); +} diff --git a/libsecurity_codesigning/lib/CSCommon.h b/libsecurity_codesigning/lib/CSCommon.h index 883d57bc..3a3d17e8 100644 --- a/libsecurity_codesigning/lib/CSCommon.h +++ b/libsecurity_codesigning/lib/CSCommon.h @@ -92,7 +92,7 @@ enum { errSecCSNoMatches = -67027, /* no matches for search or update operation */ errSecCSFileHardQuarantined = -67026, /* File created by an AppSandbox, exec/open not allowed */ errSecCSOutdated = -67025, /* presented data is out of date */ - errSecCSDbCorrupt = -67024, /* a system database of file is corrupt */ + errSecCSDbCorrupt = -67024, /* a system database or file is corrupt */ }; diff --git a/libsecurity_codesigning/lib/SecAssessment.cpp b/libsecurity_codesigning/lib/SecAssessment.cpp index 7acc660a..954f4ae8 100644 --- a/libsecurity_codesigning/lib/SecAssessment.cpp +++ b/libsecurity_codesigning/lib/SecAssessment.cpp @@ -40,9 +40,10 @@ using namespace CodeSigning; // struct _SecAssessment : private CFRuntimeBase { public: - _SecAssessment(CFURLRef p, CFDictionaryRef r) : path(p), result(r) { } + _SecAssessment(CFURLRef p, AuthorityType typ, CFDictionaryRef r) : path(p), type(typ), result(r) { } CFCopyRef path; + AuthorityType type; CFRef result; public: @@ -149,7 +150,7 @@ SecAssessmentRef SecAssessmentCreate(CFURLRef path, // check the object cache first unless caller denied that or we need extended processing if (!(flags & (kSecAssessmentFlagRequestOrigin | kSecAssessmentFlagIgnoreCache))) { if (gDatabase().checkCache(path, type, result)) - return new SecAssessment(path, result.yield()); + return new SecAssessment(path, type, result.yield()); } if (flags & kSecAssessmentFlagDirect) { @@ -178,13 +179,13 @@ SecAssessmentRef SecAssessmentCreate(CFURLRef path, throw; // let it go as an error cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); } - return new SecAssessment(path, result.yield()); + return new SecAssessment(path, type, result.yield()); END_CSAPI_ERRORS1(NULL) } -static void traceResult(SecAssessment &assessment, CFDictionaryRef result) +static void traceResult(SecAssessment &assessment, AuthorityType type, CFDictionaryRef result) { if (CFDictionaryGetValue(result, CFSTR("assessment:remote"))) return; // just traced in syspolicyd @@ -219,6 +220,7 @@ static void traceResult(SecAssessment &assessment, CFDictionaryRef result) MessageTrace trace("com.apple.security.assessment.outcome", NULL); trace.add("signature2", "bundle:%s", identifier.c_str()); + trace.add("signature4", "%d", type); if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == kCFBooleanFalse) { trace.add("signature", "denied:%s", authority.c_str()); trace.add("signature3", sanitized.c_str()); @@ -263,7 +265,7 @@ CFDictionaryRef SecAssessmentCopyResult(SecAssessmentRef assessmentRef, result = adulterated.get(); } } - traceResult(assessment, result); + traceResult(assessment, assessment.type, result); return result.yield(); END_CSAPI_ERRORS1(NULL) @@ -367,11 +369,15 @@ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *e CFTemp ctx("{%O=%s}", kSecAssessmentUpdateKeyLabel, "Developer ID"); if (CFDictionaryRef result = gEngine().enable(NULL, kAuthorityInvalid, kSecCSDefaultFlags, ctx)) CFRelease(result); + MessageTrace trace("com.apple.security.assessment.state", "enable-devid"); + trace.send("enable Developer ID approval"); return true; } else if (CFEqual(control, CFSTR("ui-disable-devid"))) { CFTemp ctx("{%O=%s}", kSecAssessmentUpdateKeyLabel, "Developer ID"); if (CFDictionaryRef result = gEngine().disable(NULL, kAuthorityInvalid, kSecCSDefaultFlags, ctx)) CFRelease(result); + MessageTrace trace("com.apple.security.assessment.state", "disable-devid"); + trace.send("disable Developer ID approval"); return true; } else if (CFEqual(control, CFSTR("ui-get-devid"))) { CFBooleanRef &result = *(CFBooleanRef*)(arguments); diff --git a/libsecurity_codesigning/lib/StaticCode.cpp b/libsecurity_codesigning/lib/StaticCode.cpp index 9a124458..7c51c792 100644 --- a/libsecurity_codesigning/lib/StaticCode.cpp +++ b/libsecurity_codesigning/lib/StaticCode.cpp @@ -383,6 +383,7 @@ CFAbsoluteTime SecStaticCode::signingTimestamp() // or throws if it is not. As a side effect, a successful return sets up the // cached certificate chain for future use. // Returns true if the signature is expired (the X.509 sense), false if it's not. +// Expiration is fatal (throws) if a secure timestamp is included, but not otherwise. // bool SecStaticCode::verifySignature() { @@ -472,6 +473,30 @@ bool SecStaticCode::verifySignature() MacOSError::throwMe(result); } } + + if (mSigningTimestamp) { + CFIndex rootix = CFArrayGetCount(mCertChain); + if (SecCertificateRef mainRoot = SecCertificateRef(CFArrayGetValueAtIndex(mCertChain, rootix-1))) + if (isAppleCA(mainRoot)) { + // impose policy: if the signature itself draws to Apple, then so must the timestamp signature + CFRef tsCerts; + MacOSError::check(CMSDecoderCopySignerTimestampCertificates(cms, 0, &tsCerts.aref())); + CFIndex tsn = CFArrayGetCount(tsCerts); + bool good = tsn > 0 && isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(tsCerts, tsn-1))); +#ifndef WORKAROUND_12007637 + // TS certificates are reordered weirdly; check them all + for (CFIndex n = 0; n < tsn; n++) + if (SecCertificateRef tsRoot = SecCertificateRef(CFArrayGetValueAtIndex(tsCerts, n))) + if ((good = isAppleCA(tsRoot))) { + secdebug("BUG", "Apple root at TS cert %ld", n); + break; + } +#endif //WORKAROUND_12007637 + if (!good) + MacOSError::throwMe(CSSMERR_TP_NOT_TRUSTED); + } + } + return actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED; } } diff --git a/libsecurity_codesigning/lib/codedirectory.cpp b/libsecurity_codesigning/lib/codedirectory.cpp index 0bcb9801..4b584138 100644 --- a/libsecurity_codesigning/lib/codedirectory.cpp +++ b/libsecurity_codesigning/lib/codedirectory.cpp @@ -252,6 +252,33 @@ size_t CodeDirectory::generateHash(DynamicHash *hasher, const void *data, size_t } +// +// Turn a hash of canonical type into a hex string +// +std::string CodeDirectory::hexHash(const unsigned char *hash) const +{ + size_t size = this->hashSize; + char result[2*size+1]; + for (unsigned n = 0; n < size; n++) + sprintf(result+2*n, "%02.2x", hash[n]); + return result; +} + + +// +// Generate a screening code string from a (complete) CodeDirectory. +// This can be used to make a lightweight pre-screening code from (just) a CodeDirectory. +// +std::string CodeDirectory::screeningCode() const +{ + if (slotIsPresent(-cdInfoSlot)) // has Info.plist + return "I" + hexHash((*this)[-cdInfoSlot]); // use Info.plist hash + if (pageSize == 0) // good-enough proxy for "not a Mach-O file" + return "M" + hexHash((*this)[0]); // use hash of main executable + return "N"; // no suitable screening code +} + + } // CodeSigning } // Security diff --git a/libsecurity_codesigning/lib/codedirectory.h b/libsecurity_codesigning/lib/codedirectory.h index 1028fd7f..08c81c68 100644 --- a/libsecurity_codesigning/lib/codedirectory.h +++ b/libsecurity_codesigning/lib/codedirectory.h @@ -241,6 +241,8 @@ public: public: static DynamicHash *hashFor(HashAlgorithm hashType); // create a DynamicHash subclass for (hashType) digests DynamicHash *getHash() const { return hashFor(this->hashType); } // make one for me + + std::string hexHash(const unsigned char *hash) const; // encode any canonical-type hash as a hex string protected: static size_t generateHash(DynamicHash *hash, UnixPlusPlus::FileDesc fd, Hashing::Byte *digest, size_t limit = 0); // hash to count or end of file @@ -255,6 +257,12 @@ public: static const char *canonicalSlotName(SpecialSlot slot); static unsigned slotAttributes(SpecialSlot slot); IFDEBUG(static const char * const debugSlotName[]); + +public: + // + // Canonical screening code. Requires a fully formed CodeDirectory. + // + std::string screeningCode() const; }; diff --git a/libsecurity_codesigning/lib/csutilities.cpp b/libsecurity_codesigning/lib/csutilities.cpp index 6ac5db8f..c3d3d926 100644 --- a/libsecurity_codesigning/lib/csutilities.cpp +++ b/libsecurity_codesigning/lib/csutilities.cpp @@ -27,6 +27,7 @@ #include "csutilities.h" #include #include +#include #include #include @@ -34,6 +35,29 @@ namespace Security { namespace CodeSigning { +// +// The (SHA-1) hash of the canonical Apple certificate root anchor +// +static const SHA1::Digest gAppleAnchorHash = + { 0x61, 0x1e, 0x5b, 0x66, 0x2c, 0x59, 0x3a, 0x08, 0xff, 0x58, + 0xd1, 0x4a, 0xe2, 0x24, 0x52, 0xd1, 0x98, 0xdf, 0x6c, 0x60 }; + + + +// +// Test for the canonical Apple CA certificate +// +bool isAppleCA(SecCertificateRef cert) +{ + return verifyHash(cert, gAppleAnchorHash); +} + +bool isAppleCA(const Hashing::Byte *sha1) +{ + return !memcmp(sha1, gAppleAnchorHash, SHA1::digestLength); +} + + // // Calculate the canonical hash of a certificate, given its raw (DER) data. // @@ -57,6 +81,17 @@ void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest) } +// +// One-stop hash-certificate-and-compare +// +bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest) +{ + SHA1::Digest dig; + hashOfCertificate(cert, dig); + return !memcmp(dig, digest, SHA1::digestLength); +} + + // // Check to see if a certificate contains a particular field, by OID. This works for extensions, // even ones not recognized by the local CL. It does not return any value, only presence. diff --git a/libsecurity_codesigning/lib/csutilities.h b/libsecurity_codesigning/lib/csutilities.h index 10b33f80..ebe3590b 100644 --- a/libsecurity_codesigning/lib/csutilities.h +++ b/libsecurity_codesigning/lib/csutilities.h @@ -42,12 +42,20 @@ namespace Security { namespace CodeSigning { +// +// Test for the canonical Apple CA certificate +// +bool isAppleCA(SecCertificateRef cert); +bool isAppleCA(const Hashing::Byte *sha1); + + // // Calculate canonical hashes of certificate. // This is simply defined as (always) the SHA1 hash of the DER. // void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest digest); void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest); +bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest); // @@ -56,13 +64,6 @@ void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest); // Extends to end of file, or (if limit > 0) at most limit bytes. // Returns number of bytes digested. // -template -size_t hashFileData(const char *path, _Hash *hasher) -{ - UnixPlusPlus::AutoFileDesc fd(path); - return hashFileData(fd, hasher); -} - template size_t hashFileData(UnixPlusPlus::FileDesc fd, _Hash *hasher, size_t limit = 0) { @@ -83,6 +84,13 @@ size_t hashFileData(UnixPlusPlus::FileDesc fd, _Hash *hasher, size_t limit = 0) return total; } +template +size_t hashFileData(const char *path, _Hash *hasher) +{ + UnixPlusPlus::AutoFileDesc fd(path); + return hashFileData(fd, hasher); +} + // // Check to see if a certificate contains a particular field, by OID. This works for extensions, diff --git a/libsecurity_codesigning/lib/drmaker.cpp b/libsecurity_codesigning/lib/drmaker.cpp index 98f887d8..1d72f8d8 100644 --- a/libsecurity_codesigning/lib/drmaker.cpp +++ b/libsecurity_codesigning/lib/drmaker.cpp @@ -70,7 +70,7 @@ Requirement *DRMaker::make() SHA1::Digest anchorHash; hashOfCertificate(ctx.cert(Requirement::anchorCert), anchorHash); - if (!memcmp(anchorHash, Requirement::appleAnchorHash(), SHA1::digestLength) + if (isAppleCA(anchorHash) #if defined(TEST_APPLE_ANCHOR) || !memcmp(anchorHash, Requirement::testAppleAnchorHash(), SHA1::digestLength) #endif diff --git a/libsecurity_codesigning/lib/policydb.cpp b/libsecurity_codesigning/lib/policydb.cpp index 63b3c934..9036fe15 100644 --- a/libsecurity_codesigning/lib/policydb.cpp +++ b/libsecurity_codesigning/lib/policydb.cpp @@ -253,6 +253,10 @@ void PolicyDatabase::upgradeDatabase() update.bind(":flag") = kAuthorityFlagDefault; update.execute(); }); + + simpleFeature("filter_unsigned", + "ALTER TABLE authority ADD COLUMN filter_unsigned TEXT NULL" + ); } @@ -313,14 +317,15 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil CFDictionaryRef values[count]; CFDictionaryGetKeysAndValues(content, (const void **)keys, (const void **)values); - SQLite::Statement insert(*this, "INSERT INTO authority (type, allow, requirement, label, flags, remarks)" - " VALUES (:type, 1, :requirement, 'GKE', :flags, :path)"); + SQLite::Statement insert(*this, "INSERT INTO authority (type, allow, requirement, label, filter_unsigned, flags, remarks)" + " VALUES (:type, 1, :requirement, 'GKE', :filter, :flags, :path)"); for (CFIndex n = 0; n < count; n++) { CFDictionary info(values[n], errSecCSDbCorrupt); insert.reset(); insert.bind(":type") = cfString(info.get(CFSTR("type"))); insert.bind(":path") = cfString(info.get(CFSTR("path"))); insert.bind(":requirement") = "cdhash H\"" + cfString(info.get(CFSTR("cdhash"))) + "\""; + insert.bind(":filter") = cfString(info.get(CFSTR("screen"))); insert.bind(":flags") = kAuthorityFlagWhitelist; insert(); } diff --git a/libsecurity_codesigning/lib/policyengine.cpp b/libsecurity_codesigning/lib/policyengine.cpp index 4cae2d96..9c139834 100644 --- a/libsecurity_codesigning/lib/policyengine.cpp +++ b/libsecurity_codesigning/lib/policyengine.cpp @@ -35,6 +35,11 @@ #include #include +#include "diskrep.h" +#include "codedirectory.h" +#include "csutilities.h" +#include "StaticCode.h" + #include #include "SecCodePriv.h" #undef check // Macro! Yech. @@ -58,7 +63,7 @@ enum { static void authorizeUpdate(SecAssessmentFlags flags, CFDictionaryRef context); -static void normalizeTarget(CFRef &target, CFDictionary &context, bool signUnsigned = false); +static void normalizeTarget(CFRef &target, CFDictionary &context, std::string *signUnsigned = NULL); static bool codeInvalidityExceptions(SecStaticCodeRef code, CFMutableDictionaryRef result); static CFTypeRef installerPolicy() CF_RETURNS_RETAINED; @@ -80,6 +85,9 @@ PolicyEngine::~PolicyEngine() // void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) { + // update GKE + installExplicitSet(gkeAuthFile, gkeSigsFile); + switch (type) { case kAuthorityExecute: evaluateCode(path, kAuthorityExecute, flags, context, result); @@ -97,11 +105,72 @@ void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlag } +// +// Whitelist pre-screen processing. +// Whitelist-matching unsigned code is expensive since we have to generate a full code signature +// just to see if we match a whitelist authority entry. This class generates a light(er)-weight +// prescreen and matches it against a hint in an authority record generated from the (detached recorded) +// code signature at time of whitelist recording. +// This is just a heuristic to cheaply rule out guaranteed mismatches. When in doubt, we go ahead +// and do the full work. +// +class WhitelistPrescreen { +public: + WhitelistPrescreen(SecStaticCodeRef code) + : mRep(SecStaticCode::requiredStatic(code)->diskRep()) { } + + bool reject(const char *screen, const char *remarks); + +private: + std::string create(char type, SHA1 &hash); + + RefPointer mRep; // DiskRep representing the code + std::string mScreen; // calculated screen (on demand) +}; + +bool WhitelistPrescreen::reject(const char *screen, const char *remarks) +{ + if (!screen) { // authority record has no screen to match - apply heuristic + if (remarks && mRep->mainExecutablePath() != remarks) // not an allow record (or moved) + return true; + else + return false; // can't rule out; proceed + } + + if (mScreen.empty()) { + if (CFRef info = mRep->component(cdInfoSlot)) { + SHA1 hash; + hash.update(CFDataGetBytePtr(info), CFDataGetLength(info)); + mScreen = create('I', hash); + } else if (mRep->mainExecutableImage()) { + mScreen = "N"; + } else { + SHA1 hash; + hashFileData(mRep->mainExecutablePath().c_str(), &hash); + mScreen = create('M', hash); + } + } + + return screen != mScreen; +} + +std::string WhitelistPrescreen::create(char type, SHA1 &hash) +{ + SHA1::Digest digest; + hash.finish(digest); + char buffer[2*SHA1::digestLength + 2] = { type }; + for (size_t n = 0; n < SHA1::digestLength; n++) + sprintf(buffer + 1 + 2*n, "%02.2x", digest[n]); + return buffer; +} + + // // Executable code. // Read from disk, evaluate properly, cache as indicated. The whole thing, so far. // -void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) +void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result, + bool handleUnsignedCode /* = true */) { FileQuarantine qtn(cfString(path).c_str()); if (qtn.flag(QTN_FLAG_HARD)) @@ -109,11 +178,14 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment CFRef code; MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref())); + OSStatus rc = noErr; // last validation error const SecCSFlags validationFlags = kSecCSEnforceRevocationChecks; + + WhitelistPrescreen whitelistScreen(code); // pre-screening filter for whitelist pre-screening (only) SQLite::Statement query(*this, - "SELECT allow, requirement, id, label, expires, flags, disabled FROM scan_authority" + "SELECT allow, requirement, id, label, expires, flags, disabled, filter_unsigned, remarks FROM scan_authority" " WHERE type = :type" " ORDER BY priority DESC;"); query.bind(":type").integer(type); @@ -127,12 +199,22 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment double expires = query[4]; sqlite3_int64 ruleFlags = query[5]; SQLite3::int64 disabled = query[6]; + const char *filter = query[7]; + const char *remarks = query[8]; CFRef requirement; MacOSError::check(SecRequirementCreateWithString(CFTempString(reqString), kSecCSDefaultFlags, &requirement.aref())); - OSStatus rc = SecStaticCodeCheckValidity(code, validationFlags, requirement); + rc = SecStaticCodeCheckValidity(code, validationFlags, requirement); - if (rc == errSecCSUnsigned) { + // ad-hoc sign unsigned code, skip of Gatekeeper is off or the rule is disabled; but always do it for whitelist recording + if (rc == errSecCSUnsigned && handleUnsignedCode && (!(disabled || overrideAssessment()) || SYSPOLICY_RECORDER_MODE_ENABLED())) { + if (!SYSPOLICY_RECORDER_MODE_ENABLED()) { + // apply whitelist pre-screening to speed things up for non-matches + if (ruleFlags & kAuthorityFlagDefault) // can't ever match standard rules with unsigned code + continue; + if (whitelistScreen.reject(filter, remarks)) // apply whitelist pre-filter + continue; + } try { // ad-hoc sign the code and attach the signature CFRef signature = CFDataCreateMutable(NULL, 0); @@ -141,7 +223,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment MacOSError::check(SecCodeSignerCreate(arguments, kSecCSDefaultFlags, &signer.aref())); MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); MacOSError::check(SecCodeSetDetachedSignature(code, signature, kSecCSDefaultFlags)); - + // if we're in GKE recording mode, save that signature and report its location if (SYSPOLICY_RECORDER_MODE_ENABLED()) { int status = recorder_code_unable; // ephemeral signature (not recorded) @@ -182,8 +264,10 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment SYSPOLICY_ASSESS_OUTCOME_BROKEN(cfString(path).c_str(), type, true); // treat as unsigned to fix problems in the field case errSecCSUnsigned: - cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); - addAuthority(result, "no usable signature"); + if (handleUnsignedCode) { + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "no usable signature"); + } return; case errSecCSReqFailed: // requirement missed, but otherwise okay continue; @@ -239,8 +323,14 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment addAuthority(result, label, id); return; } + + if (rc == errSecCSUnsigned) { // skipped all applicable rules due to pre-screening + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "no usable signature"); + return; + } - // no applicable authority. Deny by default + // no applicable authority (but signed, perhaps temporarily). Deny by default CFRef info; MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); if (flags & kSecAssessmentFlagRequestOrigin) { @@ -428,9 +518,16 @@ void PolicyEngine::evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDi } else if (qtn.flag(QTN_FLAG_ASSESSMENT_OK)) { cfadd(result, "{%O=#T}", kSecAssessmentAssessmentVerdict); addAuthority(result, "Prior Assessment"); - } else { - cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); - addAuthority(result, "_XProtect"); + } else if (!overrideAssessment()) { // no need to do more work if we're off + try { + evaluateCode(path, kAuthorityExecute, flags, context, result, false); + } catch (...) { + // some documents can't be code signed, so this may be quite benign + } + if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == NULL) { // no code signature to help us out + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(result, "_XProtect"); + } } addToAuthority(result, kLSDownloadRiskCategoryKey, riskCategory); return; @@ -480,10 +577,11 @@ CFDictionaryRef PolicyEngine::add(CFTypeRef inTarget, AuthorityType type, SecAss CFDictionary ctx(context, errSecCSInvalidAttributeValues); CFCopyRef target = inTarget; CFRef bookmark = NULL; + std::string filter_unsigned; switch (type) { case kAuthorityExecute: - normalizeTarget(target, ctx, true); + normalizeTarget(target, ctx, &filter_unsigned); // bookmarks are untrusted and just a hint to callers bookmark = ctx.get(kSecAssessmentRuleKeyBookmark); break; @@ -538,8 +636,8 @@ CFDictionaryRef PolicyEngine::add(CFTypeRef inTarget, AuthorityType type, SecAss MacOSError::check(SecRequirementCopyString(target.as(), kSecCSDefaultFlags, &requirementText.aref())); SQLite::Transaction xact(*this, SQLite3::Transaction::deferred, "add_rule"); SQLite::Statement insert(*this, - "INSERT INTO authority (type, allow, requirement, priority, label, expires, remarks)" - " VALUES (:type, :allow, :requirement, :priority, :label, :expires, :remarks);"); + "INSERT INTO authority (type, allow, requirement, priority, label, expires, filter_unsigned, remarks)" + " VALUES (:type, :allow, :requirement, :priority, :label, :expires, :filter_unsigned, :remarks);"); insert.bind(":type").integer(type); insert.bind(":allow").integer(allow); insert.bind(":requirement") = requirementText.get(); @@ -547,6 +645,7 @@ CFDictionaryRef PolicyEngine::add(CFTypeRef inTarget, AuthorityType type, SecAss if (!label.empty()) insert.bind(":label") = label; insert.bind(":expires") = expires; + insert.bind(":filter_unsigned") = filter_unsigned.empty() ? NULL : filter_unsigned.c_str(); if (!remarks.empty()) insert.bind(":remarks") = remarks; insert.execute(); @@ -635,6 +734,9 @@ CFDictionaryRef PolicyEngine::find(CFTypeRef target, AuthorityType type, SecAsse CFDictionaryRef PolicyEngine::update(CFTypeRef target, SecAssessmentFlags flags, CFDictionaryRef context) { + // update GKE + installExplicitSet(gkeAuthFile, gkeSigsFile); + AuthorityType type = typeFor(context, kAuthorityInvalid); CFStringRef edit = CFStringRef(CFDictionaryGetValue(context, kSecAssessmentContextKeyUpdate)); CFDictionaryRef result; @@ -665,7 +767,8 @@ void PolicyEngine::selectRules(SQLite::Statement &action, std::string phrase, st { CFDictionary ctx(context, errSecCSInvalidAttributeValues); CFCopyRef target = inTarget; - normalizeTarget(target, ctx); + std::string filter_unsigned; // ignored; used just to trigger ad-hoc signing + normalizeTarget(target, ctx, &filter_unsigned); string label; if (CFStringRef lab = ctx.get(kSecAssessmentUpdateKeyLabel)) @@ -804,7 +907,7 @@ static void authorizeUpdate(SecAssessmentFlags flags, CFDictionaryRef context) // // Perform common argument normalizations for update operations // -static void normalizeTarget(CFRef &target, CFDictionary &context, bool signUnsigned) +static void normalizeTarget(CFRef &target, CFDictionary &context, std::string *signUnsigned) { // turn CFURLs into (designated) SecRequirements if (target && CFGetTypeID(target) == CFURLGetTypeID()) { @@ -828,6 +931,10 @@ static void normalizeTarget(CFRef &target, CFDictionary &context, boo MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); MacOSError::check(SecCodeSetDetachedSignature(code, signature, kSecCSDefaultFlags)); MacOSError::check(SecCodeCopyDesignatedRequirement(code, kSecCSDefaultFlags, (SecRequirementRef *)&target.aref())); + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSInternalInformation, &info.aref())); + if (CFDataRef cdData = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoCodeDirectory))) + *signUnsigned = ((const CodeDirectory *)CFDataGetBytePtr(cdData))->screeningCode(); break; } MacOSError::check(rc); diff --git a/libsecurity_codesigning/lib/policyengine.h b/libsecurity_codesigning/lib/policyengine.h index 7ae9bfc7..65ff6bf1 100644 --- a/libsecurity_codesigning/lib/policyengine.h +++ b/libsecurity_codesigning/lib/policyengine.h @@ -65,7 +65,8 @@ public: static void addToAuthority(CFMutableDictionaryRef parent, CFStringRef key, CFTypeRef value); private: - void evaluateCode(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); + void evaluateCode(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result, + bool handleUnsignedCode = true); void evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); void evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); diff --git a/libsecurity_codesigning/lib/reqinterp.cpp b/libsecurity_codesigning/lib/reqinterp.cpp index e3e82338..cce6d48f 100644 --- a/libsecurity_codesigning/lib/reqinterp.cpp +++ b/libsecurity_codesigning/lib/reqinterp.cpp @@ -292,7 +292,7 @@ bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match & bool Requirement::Interpreter::appleAnchored() { if (SecCertificateRef cert = mContext->cert(anchorCert)) - if (verifyAnchor(cert, appleAnchorHash()) + if (isAppleCA(cert) #if defined(TEST_APPLE_ANCHOR) || verifyAnchor(cert, testAppleAnchorHash()) #endif diff --git a/libsecurity_codesigning/lib/requirement.cpp b/libsecurity_codesigning/lib/requirement.cpp index cc527291..a503a42d 100644 --- a/libsecurity_codesigning/lib/requirement.cpp +++ b/libsecurity_codesigning/lib/requirement.cpp @@ -41,14 +41,6 @@ namespace Security { namespace CodeSigning { -// -// The (SHA-1) hash of the canonical Apple certificate root anchor -// -static const SHA1::Digest gAppleAnchorHash = - { 0x61, 0x1e, 0x5b, 0x66, 0x2c, 0x59, 0x3a, 0x08, 0xff, 0x58, - 0xd1, 0x4a, 0xe2, 0x24, 0x52, 0xd1, 0x98, 0xdf, 0x6c, 0x60 }; - - // // Canonical names for requirement types // @@ -120,14 +112,8 @@ unsigned int Requirement::Context::certCount() const // -// Return the hash of the canonical Apple certificate root (anchor). -// In a special test mode, also return an alternate root hash for testing. +// Produce the hash of a fake Apple root (only if compiled for internal testing) // -const SHA1::Digest &Requirement::appleAnchorHash() -{ - return gAppleAnchorHash; -} - #if defined(TEST_APPLE_ANCHOR) const char Requirement::testAppleAnchorEnv[] = "TEST_APPLE_ANCHOR"; diff --git a/libsecurity_codesigning/lib/requirement.h b/libsecurity_codesigning/lib/requirement.h index dc59fa10..c6e46bff 100644 --- a/libsecurity_codesigning/lib/requirement.h +++ b/libsecurity_codesigning/lib/requirement.h @@ -76,7 +76,6 @@ public: // the SHA1 hash of the canonical "Apple Anchor", i.e. the X509 Anchor // that is considered "Apple's anchor certificate", as defined by hashOfCertificate(). - static const SHA1::Digest &appleAnchorHash(); #if defined(TEST_APPLE_ANCHOR) static const char testAppleAnchorEnv[]; static const SHA1::Digest &testAppleAnchorHash(); diff --git a/libsecurity_codesigning/lib/syspolicy.sql b/libsecurity_codesigning/lib/syspolicy.sql index 9e3eecee..be551339 100644 --- a/libsecurity_codesigning/lib/syspolicy.sql +++ b/libsecurity_codesigning/lib/syspolicy.sql @@ -65,6 +65,7 @@ CREATE TABLE authority ( expires FLOAT NOT NULL DEFAULT (5000000), -- expiration of rule authority (Julian date) priority REAL NOT NULL DEFAULT (0), -- rule priority (full float) label TEXT NULL, -- text label for authority rule + filter_unsigned TEXT NULL, -- prescreen for handling unsigned code flags INTEGER NOT NULL DEFAULT (0), -- amalgamated binary flags -- following fields are for documentation only ctime FLOAT NOT NULL DEFAULT (JULIANDAY('now')), -- rule creation time (Julian) @@ -111,9 +112,11 @@ CREATE TABLE bookmarkhints ( -- See policydatabase.cpp for upgrade code. -- INSERT INTO feature (name, value, remarks) - VALUES ('bookmarkhints', 'value', 'builtin'); + VALUES ('bookmarkhints', 'present', 'builtin'); INSERT INTO feature (name, value, remarks) - VALUES ('codesignedpackages', 'value', 'builtin'); + VALUES ('codesignedpackages', 'present', 'builtin'); +INSERT INTO feature (name, value, remarks) + VALUES ('filter_unsigned', 'present', 'builtin'); -- diff --git a/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj b/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj index e1a82958..d2402b65 100644 --- a/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj +++ b/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ C26AC0F4143BD1C4001C98CE /* CopyFiles */, C2F24DFE14BCBBF200309FCD /* ShellScript */, C2578CB11579627200D4FE48 /* CopyFiles */, + C25C18CD15CB0C470007A2DE /* CopyFiles */, + C25C18D015CB0FB30007A2DE /* CopyFiles */, ); dependencies = ( ); @@ -53,6 +55,7 @@ C250F6C50B5EF4E40076098F /* PBXTargetDependency */, C2E287430B5D8F9A009336A0 /* PBXTargetDependency */, C26AC0F2143BD02B001C98CE /* PBXTargetDependency */, + C209697015BF53330093035F /* PBXTargetDependency */, ); name = Everything; productName = Everything; @@ -69,7 +72,10 @@ 18B9658C1472FC9E005A4D2E /* codedirectory.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383170A237F47005C63A2 /* codedirectory.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18B965941472FE27005A4D2E /* renum.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EF100F0A49BD89005A44BB /* renum.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18B965951472FE30005A4D2E /* cdbuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383150A237F47005C63A2 /* cdbuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C200424D15D425D9004AE0A1 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */; }; + C200424E15D425D9004AE0A1 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */; }; C2093AA80BB0948000EB8599 /* reqreader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2093AA60BB0948000EB8599 /* reqreader.cpp */; }; + C209696415BF52040093035F /* gkunpack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C209696315BF52040093035F /* gkunpack.cpp */; }; C211070A158C1082001D7F76 /* gkmerge in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2110704158BF5C8001D7F76 /* gkmerge */; }; C21CFC5F0A250D1C006CD5B1 /* reqdumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */; }; C21EA3DD0AD2F81300E6E31C /* SecCodeSigner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */; }; @@ -83,6 +89,8 @@ C24EABAD1421433700C16AA9 /* policydb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C24EABAC1421433700C16AA9 /* policydb.cpp */; }; C250F6C30B5EF1910076098F /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = C250F6C20B5EF1910076098F /* SecIntegrity.h */; }; C259DFD60AD6D9BA00C9ACC6 /* sigblob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */; }; + C25C18CE15CB0C5C0007A2DE /* gkreport in CopyFiles */ = {isa = PBXBuildFile; fileRef = C25C18C615CB0BC10007A2DE /* gkreport */; }; + C25C18D115CB0FC30007A2DE /* com.apple.gkreport.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */; }; C26763D714FD9EBE00A46EDF /* drmaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26763D514FD9EBE00A46EDF /* drmaker.cpp */; }; C26763D814FD9EBE00A46EDF /* drmaker.h in Headers */ = {isa = PBXBuildFile; fileRef = C26763D614FD9EBE00A46EDF /* drmaker.h */; }; C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */ = {isa = PBXBuildFile; fileRef = C26AC0F3143BD1B3001C98CE /* SystemPolicy */; }; @@ -198,6 +206,13 @@ remoteGlobalIDString = C26AC7090DAEB3A7005BFB40; remoteInfo = DTrace; }; + C209696F15BF53330093035F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C209695F15BF52040093035F; + remoteInfo = gkunpack; + }; C250F6C40B5EF4E40076098F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; @@ -244,6 +259,26 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + C25C18CD15CB0C470007A2DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/libexec; + dstSubfolderSpec = 0; + files = ( + C25C18CE15CB0C5C0007A2DE /* gkreport in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + C25C18D015CB0FB30007A2DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchDaemons; + dstSubfolderSpec = 0; + files = ( + C25C18D115CB0FC30007A2DE /* com.apple.gkreport.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; C26AC0F4143BD1C4001C98CE /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -263,9 +298,14 @@ 184461A1146E9AD100B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; 184461A2146E9AD100B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_codesigning.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = ../../../usr/local/lib/libsecurity_codesigning.a; sourceTree = ""; }; + C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = ../../../usr/local/lib/libsecurity_utilities.a; sourceTree = ""; }; C2093AA60BB0948000EB8599 /* reqreader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqreader.cpp; sourceTree = ""; }; C2093AA70BB0948000EB8599 /* reqreader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqreader.h; sourceTree = ""; }; - C2110704158BF5C8001D7F76 /* gkmerge */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; name = gkmerge; path = gke/gkmerge; sourceTree = SOURCE_ROOT; }; + C209696015BF52040093035F /* gkunpack */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gkunpack; sourceTree = BUILT_PRODUCTS_DIR; }; + C209696315BF52040093035F /* gkunpack.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = gkunpack.cpp; sourceTree = ""; }; + C209697215BF57EB0093035F /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; sourceTree = ""; }; + C2110704158BF5C8001D7F76 /* gkmerge */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gkmerge; sourceTree = ""; }; C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqdumper.cpp; sourceTree = ""; }; C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqdumper.h; sourceTree = ""; }; C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCodeSigner.cpp; sourceTree = ""; }; @@ -282,11 +322,13 @@ C24EABAC1421433700C16AA9 /* policydb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = policydb.cpp; sourceTree = ""; }; C250F6C20B5EF1910076098F /* SecIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrity.h; sourceTree = ""; }; C250F6C60B5EF5B50076098F /* SecIntegrity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIntegrity.cpp; sourceTree = ""; }; - C2578CC215798D0F00D4FE48 /* gkclear */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gkclear; path = gke/gkclear; sourceTree = SOURCE_ROOT; }; - C2578CC315798D0F00D4FE48 /* gkgenerate */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gkgenerate; path = gke/gkgenerate; sourceTree = SOURCE_ROOT; }; - C2578CC415798D0F00D4FE48 /* gkrecord */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gkrecord; path = gke/gkrecord; sourceTree = SOURCE_ROOT; }; + C2578CC215798D0F00D4FE48 /* gkclear */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkclear; sourceTree = ""; }; + C2578CC315798D0F00D4FE48 /* gkgenerate */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkgenerate; sourceTree = ""; }; + C2578CC415798D0F00D4FE48 /* gkrecord */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkrecord; sourceTree = ""; }; C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sigblob.cpp; sourceTree = ""; }; C259DFD50AD6D9BA00C9ACC6 /* sigblob.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sigblob.h; sourceTree = ""; }; + C25C18C615CB0BC10007A2DE /* gkreport */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = gkreport; path = gke/gkreport; sourceTree = SOURCE_ROOT; }; + C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.gkreport.plist; path = gke/com.apple.gkreport.plist; sourceTree = SOURCE_ROOT; }; C26763D514FD9EBE00A46EDF /* drmaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drmaker.cpp; sourceTree = ""; }; C26763D614FD9EBE00A46EDF /* drmaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drmaker.h; sourceTree = ""; }; C26AC0F3143BD1B3001C98CE /* SystemPolicy */ = {isa = PBXFileReference; lastKnownFileType = text; name = SystemPolicy; path = cstemp/SystemPolicy; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -294,13 +336,13 @@ C26B45C00B8A9C00003C0ACA /* ucspc */ = {isa = PBXFileReference; lastKnownFileType = text; name = ucspc; path = cstemp/ucspc; sourceTree = BUILT_PRODUCTS_DIR; }; C27249D2143237CD0058B552 /* syspolicy.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = syspolicy.sql; sourceTree = ""; }; C273601D1432A60B00A9A5FF /* policyengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = policyengine.h; sourceTree = ""; }; - C27360201432A61900A9A5FF /* policyengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = policyengine.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - C273606C1433F09000A9A5FF /* SecAssessment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecAssessment.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C27360201432A61900A9A5FF /* policyengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = policyengine.cpp; sourceTree = ""; }; + C273606C1433F09000A9A5FF /* SecAssessment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecAssessment.cpp; sourceTree = ""; }; C273606D1433F09000A9A5FF /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SecAssessment.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - C27360D41436866C00A9A5FF /* xpcengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = xpcengine.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C27360D41436866C00A9A5FF /* xpcengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = xpcengine.cpp; sourceTree = ""; }; C27360D71436868600A9A5FF /* xpcengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xpcengine.h; sourceTree = ""; }; - C278A19B158AB2C300FA6767 /* gkhandmake */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gkhandmake; path = gke/gkhandmake; sourceTree = SOURCE_ROOT; }; - C278A19C158AB2C300FA6767 /* gklist */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gklist; path = gke/gklist; sourceTree = SOURCE_ROOT; }; + C278A19B158AB2C300FA6767 /* gkhandmake */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkhandmake; sourceTree = ""; }; + C278A19C158AB2C300FA6767 /* gklist */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gklist; sourceTree = ""; }; C28342E40E366E6800E54360 /* csdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = csdatabase.cpp; sourceTree = ""; }; C28342E50E366E6800E54360 /* csdatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = csdatabase.h; sourceTree = ""; }; C28342EB0E36719D00E54360 /* detachedrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detachedrep.cpp; sourceTree = ""; }; @@ -404,6 +446,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + C209695D15BF52040093035F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C200424D15D425D9004AE0A1 /* libsecurity_codesigning.a in Frameworks */, + C200424E15D425D9004AE0A1 /* libsecurity_utilities.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C2BC1F240B580D3A003EC9DC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -468,6 +519,7 @@ 4CA1FEA7052A3C3800F22E42 = { isa = PBXGroup; children = ( + C209697215BF57EB0093035F /* libsecurity_utilities.a */, 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */, 4C308388053237100028A8C6 /* lib */, 1844619E146E9AD100B12992 /* config */, @@ -483,6 +535,7 @@ 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */, C2BC1F260B580D3A003EC9DC /* libintegrity.a */, C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */, + C209696015BF52040093035F /* gkunpack */, ); name = Products; sourceTree = ""; @@ -533,9 +586,11 @@ C2578CC215798D0F00D4FE48 /* gkclear */, C2578CC315798D0F00D4FE48 /* gkgenerate */, C2578CC415798D0F00D4FE48 /* gkrecord */, + C25C18C615CB0BC10007A2DE /* gkreport */, + C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */, + C209696315BF52040093035F /* gkunpack.cpp */, ); - name = gke; - path = whitelist; + path = gke; sourceTree = SOURCE_ROOT; }; C2BC1F370B580DAE003EC9DC /* Static Support */ = { @@ -673,6 +728,8 @@ C2CC30EF0B8519CF005FA59D /* Frameworks */ = { isa = PBXGroup; children = ( + C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */, + C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */, C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */, ); name = Frameworks; @@ -813,6 +870,22 @@ productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */; productType = "com.apple.product-type.library.static"; }; + C209695F15BF52040093035F /* gkunpack */ = { + isa = PBXNativeTarget; + buildConfigurationList = C209696B15BF52040093035F /* Build configuration list for PBXNativeTarget "gkunpack" */; + buildPhases = ( + C209695C15BF52040093035F /* Sources */, + C209695D15BF52040093035F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = gkunpack; + productName = gkunpack; + productReference = C209696015BF52040093035F /* gkunpack */; + productType = "com.apple.product-type.tool"; + }; C2BC1F250B580D3A003EC9DC /* libintegrity */ = { isa = PBXNativeTarget; buildConfigurationList = C2BC1F270B580D3F003EC9DC /* Build configuration list for PBXNativeTarget "libintegrity" */; @@ -884,6 +957,7 @@ C2BC1F2E0B580D4B003EC9DC /* libcodehost */, C26AC7090DAEB3A7005BFB40 /* DTrace */, C26AC0EB143BCF01001C98CE /* SystemPolicy */, + C209695F15BF52040093035F /* gkunpack */, ); }; /* End PBXProject section */ @@ -1066,6 +1140,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + C209695C15BF52040093035F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C209696415BF52040093035F /* gkunpack.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C2BC1F230B580D3A003EC9DC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1100,6 +1182,11 @@ target = C26AC7090DAEB3A7005BFB40 /* DTrace */; targetProxy = 1844617C146E9A5200B12992 /* PBXContainerItemProxy */; }; + C209697015BF53330093035F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C209695F15BF52040093035F /* gkunpack */; + targetProxy = C209696F15BF53330093035F /* PBXContainerItemProxy */; + }; C250F6C50B5EF4E40076098F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C2BC1F250B580D3A003EC9DC /* libintegrity */; @@ -1123,6 +1210,57 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + C209696C15BF52040093035F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C209696D15BF52040093035F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = NO; + }; + name = Release; + }; C263E67609A2971B000043F1 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; @@ -1153,6 +1291,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; }; name = Debug; @@ -1161,6 +1306,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; }; name = Release; @@ -1236,18 +1388,41 @@ C2E287480B5D8FD8009336A0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); }; name = Debug; }; C2E2874A0B5D8FD8009336A0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + C209696B15BF52040093035F /* Build configuration list for PBXNativeTarget "gkunpack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C209696C15BF52040093035F /* Debug */, + C209696D15BF52040093035F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_codesigning" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/libsecurity_ssl/lib/cipherSpecs.c b/libsecurity_ssl/lib/cipherSpecs.c index 67c4e344..f3394255 100644 --- a/libsecurity_ssl/lib/cipherSpecs.c +++ b/libsecurity_ssl/lib/cipherSpecs.c @@ -1379,7 +1379,7 @@ cipherSuitesToCipherSuites( if(*numCiphers < numCipherSuites) { return errSSLBufferOverflow; } - memcpy(ciphers, cipherSuites, numCipherSuites * sizeof(SSLCipherSuite)); + memcpy(ciphers, cipherSuites, numCipherSuites * sizeof(SSLCipherSuite)); *numCiphers = numCipherSuites; return noErr; } diff --git a/libsecurity_ssl/lib/tls1Callouts.c b/libsecurity_ssl/lib/tls1Callouts.c index 6f26712d..ca06db05 100644 --- a/libsecurity_ssl/lib/tls1Callouts.c +++ b/libsecurity_ssl/lib/tls1Callouts.c @@ -289,6 +289,7 @@ static OSStatus tls1DecryptRecord( { OSStatus err; SSLBuffer content; + bool decryption_failed_or_bad_record_mac = false; if ((ctx->readCipher.symCipher->blockSize > 0) && ((payload->length % ctx->readCipher.symCipher->blockSize) != 0)) { @@ -301,8 +302,12 @@ static OSStatus tls1DecryptRecord( payload->data, payload->length, &ctx->readCipher, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertDecryptError, ctx); - return errSSLDecryptionFail; + { + /* note: we no longer send a SSL_AlertDecryptError here; + * all subsequent failures result in SSL_AlertBadRecordMac + * being sent at the end of the function, to avoid leaking + * differences between padding and decryption failures. */ + decryption_failed_or_bad_record_mac = true; } /* Locate content within decrypted payload */ @@ -327,18 +332,16 @@ static OSStatus tls1DecryptRecord( * even size packets...beware... */ if(padSize > payload->length) { /* This is TLS 1.1 compliant - Do it for all protocols versions */ - SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx); sslErrorLog("tls1DecryptRecord: bad padding length (%d)\n", (unsigned)payload->data[payload->length - 1]); - return errSSLDecryptionFail; + decryption_failed_or_bad_record_mac = true; } padChars = payload->data + payload->length - padSize; while(padChars < (payload->data + payload->length)) { if(*padChars++ != padSize) { /* This is TLS 1.1 compliant - Do it for all protocols versions */ - SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx); sslErrorLog("tls1DecryptRecord: bad padding value\n"); - return errSSLDecryptionFail; + decryption_failed_or_bad_record_mac = true; } } /* Remove block size padding and its one-byte length */ @@ -350,10 +353,15 @@ static OSStatus tls1DecryptRecord( /* Optimize away MAC for null case */ if ((err = SSLVerifyMac(type, &content, content.data + content.length, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx); - return errSSLBadRecordMac; + { + decryption_failed_or_bad_record_mac = true; } + if (decryption_failed_or_bad_record_mac) { + SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx); + return errSSLDecryptionFail; + } + *payload = content; /* Modify payload buffer to indicate content length */ return noErr; diff --git a/libsecurity_utilities/lib/sqlite++.cpp b/libsecurity_utilities/lib/sqlite++.cpp index b807549e..9b3cba1a 100644 --- a/libsecurity_utilities/lib/sqlite++.cpp +++ b/libsecurity_utilities/lib/sqlite++.cpp @@ -360,8 +360,11 @@ void Statement::Binding::operator = (double value) void Statement::Binding::operator = (const char *value) { - statement.check(::sqlite3_bind_text(statement.sql(), index, - ::strdup(value), -1, ::free)); + if (value == NULL) + this->null(); + else + statement.check(::sqlite3_bind_text(statement.sql(), index, + ::strdup(value), -1, ::free)); } void Statement::Binding::operator = (const std::string &value) -- 2.47.2