]> git.saurik.com Git - apple/security.git/commitdiff
Security-55179.1.tar.gz mac-os-x-1082 v55179.1
authorApple <opensource@apple.com>
Mon, 10 Sep 2012 21:05:25 +0000 (21:05 +0000)
committerApple <opensource@apple.com>
Mon, 10 Sep 2012 21:05:25 +0000 (21:05 +0000)
40 files changed:
Security.xcodeproj/project.pbxproj
lib/Info-Security.plist
lib/plugins/csparser-Info.plist
libsecurity_cdsa_client/lib/cryptoclient.cpp
libsecurity_cdsa_client/lib/cryptoclient.h
libsecurity_cdsa_client/lib/cspclient.cpp
libsecurity_cdsa_client/lib/cspclient.h
libsecurity_cdsa_client/lib/cssmclient.cpp
libsecurity_cdsa_client/lib/cssmclient.h
libsecurity_cdsa_client/lib/dlclient.cpp
libsecurity_cdsa_client/lib/dlclient.h
libsecurity_cdsa_client/lib/genkey.cpp
libsecurity_cdsa_client/lib/keyclient.cpp
libsecurity_cdsa_client/lib/macclient.cpp
libsecurity_cdsa_client/lib/multidldb.cpp
libsecurity_cdsa_client/lib/signclient.cpp
libsecurity_codesigning/dtrace/sp-watch.d
libsecurity_codesigning/gke/com.apple.gkreport.plist [new file with mode: 0644]
libsecurity_codesigning/gke/gkgenerate
libsecurity_codesigning/gke/gkreport [new file with mode: 0755]
libsecurity_codesigning/gke/gkunpack.cpp [new file with mode: 0644]
libsecurity_codesigning/lib/CSCommon.h
libsecurity_codesigning/lib/SecAssessment.cpp
libsecurity_codesigning/lib/StaticCode.cpp
libsecurity_codesigning/lib/codedirectory.cpp
libsecurity_codesigning/lib/codedirectory.h
libsecurity_codesigning/lib/csutilities.cpp
libsecurity_codesigning/lib/csutilities.h
libsecurity_codesigning/lib/drmaker.cpp
libsecurity_codesigning/lib/policydb.cpp
libsecurity_codesigning/lib/policyengine.cpp
libsecurity_codesigning/lib/policyengine.h
libsecurity_codesigning/lib/reqinterp.cpp
libsecurity_codesigning/lib/requirement.cpp
libsecurity_codesigning/lib/requirement.h
libsecurity_codesigning/lib/syspolicy.sql
libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj
libsecurity_ssl/lib/cipherSpecs.c
libsecurity_ssl/lib/tls1Callouts.c
libsecurity_utilities/lib/sqlite++.cpp

index 29b940f86e3269b2093d8780e582f77932c122b5..a6d6c969031ddd3347f82b692927f40ca4f4a60f 100644 (file)
@@ -39,6 +39,7 @@
                        );
                        dependencies = (
                                186F779114E5A00F00434E1F /* PBXTargetDependency */,
+                               C2432A2515C726B50096DB5B /* PBXTargetDependency */,
                        );
                        name = Security_executables;
                        productName = Other;
                        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 */
                                1879B666146DE757007E536C /* libsecurity_codesigning.a */,
                                1879B66A146DE757007E536C /* libintegrity.a */,
                                1879B66C146DE757007E536C /* libcodehost.a */,
+                               C2432A0815C7112A0096DB5B /* gkunpack */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                        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 */
                        name = XPCTimeStampingService;
                        targetProxy = 529FF21F1523BD7F0029D842 /* PBXContainerItemProxy */;
                };
+               C2432A2515C726B50096DB5B /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       name = gkunpack;
+                       targetProxy = C2432A2415C726B50096DB5B /* PBXContainerItemProxy */;
+               };
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
index 99d3cebab2e737bc09d46d7c47b4f79e57a1bb68..e8eda2ec1c3adc34f27ad3c01879c19ebcaadcd8 100644 (file)
@@ -19,6 +19,6 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>55178.0.1</string>
+       <string>55179.1</string>
 </dict>
 </plist>
index a17c62bcf2ffe328d7b6de9d859a4869256a98d4..8636a5fc1455adb3e60c069aa38424451b78a683 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>55178.0.1</string>
+       <string>55179.1</string>
        <key>CFBundleShortVersionString</key>
        <string>3.0</string>
 </dict>
index e271f3111a4e7a4280c8ad8a864cbfc03992ee62..3a4bb7e730b5467a76b0186c00b217b179146355 100644 (file)
@@ -40,6 +40,7 @@ void Crypt::key(const Key &key)
 void
 Crypt::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
         // Key is required unless we have a NULL algorithm (cleartext wrap/unwrap),
index 18ab4b7930dc7ed731f9fb301495675a4d80a796..707bcd32fa05ae684a1317b6bc6e761804783a8c 100644 (file)
@@ -56,6 +56,7 @@ protected:
        Key mKey;
        const CssmData *mInitVector;
        CSSM_PADDING mPadding;
+    RecursiveMutex mActivateMutex;
 };
 
 
index 8e4a313f810288a34edecf56bbf23fdda1f53553..8f18933603d369f9d9de26cf1c56ccb809ee111d 100644 (file)
@@ -73,6 +73,7 @@ void Context::init()
 
 void Context::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive = false;
@@ -175,6 +176,7 @@ PassThrough::operator() (uint32 passThroughId, const void *inData, void **outDat
 
 void PassThrough::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive) {
                check(CSSM_CSP_CreatePassThroughContext(attachment()->handle(), mKey, &mHandle));
                mActive = true;
@@ -187,6 +189,7 @@ void PassThrough::activate()
 //
 void Digest::activate()
 {
+    StLock<Mutex> _(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<Mutex> _(mActivateMutex);
        if (!mActive) {
                check(CSSM_CSP_CreateRandomGenContext(attachment()->handle(), mAlgorithm,
                        mSeed, mSize, &mHandle));
index 2ffe7210b91ef54861ffe3c1e63582a3b0947f44..add128b56db52c4c42185b0448bdcdda03cb0013 100644 (file)
@@ -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;
 };
 
 
index ec3fb44da7ff99b5e6e3179b95592f54ae28493f..a86f3bdec1d78a49e49863bbe742dcefe401fd25 100644 (file)
@@ -193,6 +193,7 @@ CssmImpl::standard()
 void
 CssmImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                // currently, no choices on PVC mode and key hierarchy
@@ -213,6 +214,7 @@ CssmImpl::activate()
 void
 CssmImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive = false;
@@ -396,6 +398,7 @@ ModuleImpl::appNotifyCallback(RawModuleEvents *handler)
 void
 ModuleImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                session()->init();
@@ -411,6 +414,7 @@ ModuleImpl::activate()
 void
 ModuleImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!isIdle())
                Error::throwMe(Error::objectBusy);
        if (mActive)
@@ -463,6 +467,7 @@ AttachmentImpl::make(CSSM_SERVICE_TYPE subserviceType)
 void
 AttachmentImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                module()->load();
@@ -483,6 +488,7 @@ AttachmentImpl::activate()
 void
 AttachmentImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive = false;
index b6b2f321ad21ebc172b8b4ac0addd1574eea1377..43fb3141c717617b82a94d1858ac8a9fa001289b 100644 (file)
@@ -100,6 +100,7 @@ public:
 
 protected:
        bool mActive;                                   // loaded, attached, etc.
+    RecursiveMutex mActivateMutex;
        mutable Allocator *mAllocator; // allocator hierarchy (NULL => TBD)
        
        template <class Obj> Obj parent() const
index 3f1d466c3328aa8c4e676a6d0299c2f8efafd73f..6fa631bf7495154abd48c66d472f1006c26657f8 100644 (file)
@@ -111,6 +111,8 @@ DbImpl::open()
                check(CSSM_DL_DbOpen(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(),
                                                                mAccessRequest, mAccessCredentials,
                                                                mOpenParameters, &mHandle.DBHandle));
+
+        StLock<Mutex> _(mActivateMutex);
                mActive = true;
                
                if (!mAccessCredentials && mDefaultCredentials)
@@ -150,6 +152,7 @@ DbImpl::createWithBlob(CssmData &blob)
 void
 DbImpl::create()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
                CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS);
 
@@ -176,6 +179,7 @@ DbImpl::create()
 void
 DbImpl::close()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                check(CSSM_DL_DbClose (mHandle));
@@ -186,6 +190,7 @@ DbImpl::close()
 void
 DbImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                if (mDbInfo)
@@ -198,6 +203,7 @@ DbImpl::activate()
 void
 DbImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive = false;
@@ -640,6 +646,8 @@ DbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniq
                                                                          attributes,
                                                                          data,
                                                                          unique);
+
+        StLock<Mutex> _(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<Mutex> _(mActivateMutex);
                mActive = false;
                return false;
        }
@@ -686,6 +695,7 @@ DbDbCursorImpl::activate()
 void
 DbDbCursorImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive = false;
@@ -836,12 +846,14 @@ DbUniqueRecordImpl::getWithoutEncryption(DbAttributes *attributes,
 void
 DbUniqueRecordImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        mActive = true;
 }
 
 void
 DbUniqueRecordImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive = false;
index ae8e07875aa4a76fa76ccca0d118e072c9bf3cb2..2579a42809343a1eb83d7fb9b086b801bfba37f6 100644 (file)
@@ -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
index 3e5d52d97e9360f4d7004898ca919621eea2e650..aabcb225b0e635e4361cfb42e9ce1091bd5fe2d0 100644 (file)
@@ -39,6 +39,7 @@ GenerateKey::database(const Db &inDb)
 
 void GenerateKey::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                check(CSSM_CSP_CreateKeyGenContext(attachment()->handle(), mAlgorithm,
index 00c738e039ae5bfcd8f7ab875912307dd46d4935..f179e432d1419ab125cd0c081295e30de98d7423 100644 (file)
@@ -57,6 +57,7 @@ KeyImpl::~KeyImpl()
 void
 KeyImpl::deleteKey(const CSSM_ACCESS_CREDENTIALS *cred)
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive=false;
@@ -104,11 +105,13 @@ KeyImpl::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner,
 
 void KeyImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        mActive=true;
 }
 
 void KeyImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive=false;
index 38c8b6a7f4dc24c4bf44aaa940342134f4a7a00a..1fdc177ab0130a88e9fcc89d4ecad5a2a447f209 100644 (file)
@@ -29,6 +29,7 @@ using namespace CssmClient;
 //
 void MacContext::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive) 
        {
                check(CSSM_CSP_CreateMacContext(attachment()->handle(), mAlgorithm,
index 713320790640997c6945bfbefc32aa5a98092d9c..03829193f45478c2e42318d043ccd2b5922d361b 100644 (file)
@@ -210,6 +210,7 @@ MultiDLDbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data,
 void
 MultiDLDbDbCursorImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                mListRef = multiDLDb()->listRef();
@@ -222,6 +223,7 @@ MultiDLDbDbCursorImpl::activate()
 void
 MultiDLDbDbCursorImpl::deactivate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (mActive)
        {
                mActive = false;
index 6b5e03772986f45b97ade71413262f956b3fdc11..39c7a02f564ca586e9a29462620d6bf1fe333022 100644 (file)
@@ -29,6 +29,7 @@ using namespace CssmClient;
 //
 void SigningContext::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                check(CSSM_CSP_CreateSignatureContext(attachment()->handle(), mAlgorithm,
index 194d5724cc112633d33d16bb826d7f175a4fca7b..988d938e0edc83e2d9c06c99a0ecb749336927ae 100755 (executable)
@@ -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 (file)
index 0000000..b55efe6
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Label</key>
+       <string>com.apple.gkreport</string>
+       <key>ProgramArguments</key>
+       <array>
+               <string>/usr/libexec/gkreport</string>
+       </array>
+       <key>StartCalendarInterval</key>
+       <dict>
+               <key>Minute</key><integer>52</integer>
+               <key>Hour</key><integer>3</integer> 
+               <key>WeekDay</key><integer>5</integer>
+       </dict>
+</dict>
+</plist>
index b62383f18fa043e1c23757d3b387afc85b11caad..127d9b0c0301270488a2599b12749ac54adcda9f 100755 (executable)
@@ -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 (executable)
index 0000000..8bf49fa
--- /dev/null
@@ -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 (file)
index 0000000..11e16ca
--- /dev/null
@@ -0,0 +1,31 @@
+//
+//  gkunpack - an ad-hoc tool for unpacking certain binary data from a detached code signature
+//
+//     gkunpack <detached_signature_data >prescreen_filter_data
+//
+#include <security_utilities/macho++.h>
+#include <security_codesigning/codedirectory.h>
+#include <security_codesigning/sigblob.h>
+
+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<const CodeDirectory>(cdCodeDirectorySlot)) {
+                               printf("%s\n", cd->screeningCode().c_str());
+                               exit(0);
+                       }
+       }
+       fprintf(stderr, "Invalid signature structure\n");
+       exit(1);
+}
index 883d57bc5d1f9b2ca3f13f6b6e96e561325298fe..3a3d17e838e1a5349e9a89991c7f9f21e8d7b8e7 100644 (file)
@@ -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 */
 };
 
 
index 7acc660a9723e9029d74206351b453d1b51b897d..954f4ae8b4756f90859c6bfb09a3eaa2e54ac0b9 100644 (file)
@@ -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<CFURLRef> path;
+       AuthorityType type;
        CFRef<CFDictionaryRef> 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<CFDictionaryRef> 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<CFDictionaryRef> 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);
index 9a12445831cd51cc03761a25825725b60209f450..7c51c792cce91acc10d62b98a5ac4107d68da317 100644 (file)
@@ -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<CFArrayRef> 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;
        }
 }
index 0bcb980192b6cc4a746533cdddd8c8094a1b220a..4b58413808d7523ef4e6999555dfe1f2ff2f8280 100644 (file)
@@ -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
 
index 1028fd7f7d86f3300715888de5fd713353300619..08c81c686ca898afca18da05b5a8d8df8143675c 100644 (file)
@@ -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;
 };
 
 
index 6ac5db8fe0a65c6bf642788ef66880fe05ab87a8..c3d3d9268a8b297befbbea497fcd9a0b8e66442d 100644 (file)
@@ -27,6 +27,7 @@
 #include "csutilities.h"
 #include <Security/SecCertificatePriv.h>
 #include <security_codesigning/requirement.h>
+#include <security_utilities/hashing.h>
 #include <security_utilities/debugging.h>
 #include <security_utilities/errors.h>
 
@@ -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.
index 10b33f8091175ef047c2ca3652273d501cfda184..ebe3590bea926a366ec943e555c41d25f72da81c 100644 (file)
@@ -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 <class _Hash>
-size_t hashFileData(const char *path, _Hash *hasher)
-{
-       UnixPlusPlus::AutoFileDesc fd(path);
-       return hashFileData(fd, hasher);
-}
-
 template <class _Hash>
 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 <class _Hash>
+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,
index 98f887d87f00b26d5ed88fe2a741a45c95f16e38..1d72f8d87646b1b5dc2450922c4be180c9b630ee 100644 (file)
@@ -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
index 63b3c9349d24df3b264e92946a63f0277e9c7501..9036fe15d1289fce1f432b18ca1ed765bb8e9aab 100644 (file)
@@ -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<CFStringRef>(CFSTR("type")));
                                insert.bind(":path") = cfString(info.get<CFStringRef>(CFSTR("path")));
                                insert.bind(":requirement") = "cdhash H\"" + cfString(info.get<CFStringRef>(CFSTR("cdhash"))) + "\"";
+                               insert.bind(":filter") = cfString(info.get<CFStringRef>(CFSTR("screen")));
                                insert.bind(":flags") = kAuthorityFlagWhitelist;
                                insert();
                        }
index 4cae2d96d25fd2dfd3bf3905c442307972205294..9c1398348798cabb017d16f233fa402a92bef6b4 100644 (file)
 #include <security_utilities/unix++.h>
 #include <notify.h>
 
+#include "diskrep.h"
+#include "codedirectory.h"
+#include "csutilities.h"
+#include "StaticCode.h"
+
 #include <CoreServices/CoreServicesPriv.h>
 #include "SecCodePriv.h"
 #undef check // Macro! Yech.
@@ -58,7 +63,7 @@ enum {
 
 
 static void authorizeUpdate(SecAssessmentFlags flags, CFDictionaryRef context);
-static void normalizeTarget(CFRef<CFTypeRef> &target, CFDictionary &context, bool signUnsigned = false);
+static void normalizeTarget(CFRef<CFTypeRef> &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<DiskRep> 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<CFDataRef> 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<SecStaticCodeRef> 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<SecRequirementRef> 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<CFDataRef> 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<CFDictionaryRef> 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<CFTypeRef> target = inTarget;
        CFRef<CFDataRef> 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<CFDataRef>(kSecAssessmentRuleKeyBookmark);
                break;
@@ -538,8 +636,8 @@ CFDictionaryRef PolicyEngine::add(CFTypeRef inTarget, AuthorityType type, SecAss
        MacOSError::check(SecRequirementCopyString(target.as<SecRequirementRef>(), 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<CFTypeRef> 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<CFStringRef>(kSecAssessmentUpdateKeyLabel))
@@ -804,7 +907,7 @@ static void authorizeUpdate(SecAssessmentFlags flags, CFDictionaryRef context)
 //
 // Perform common argument normalizations for update operations
 //
-static void normalizeTarget(CFRef<CFTypeRef> &target, CFDictionary &context, bool signUnsigned)
+static void normalizeTarget(CFRef<CFTypeRef> &target, CFDictionary &context, std::string *signUnsigned)
 {
        // turn CFURLs into (designated) SecRequirements
        if (target && CFGetTypeID(target) == CFURLGetTypeID()) {
@@ -828,6 +931,10 @@ static void normalizeTarget(CFRef<CFTypeRef> &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<CFDictionaryRef> 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);
index 7ae9bfc7c3a997649df712d11e17a41ffe2ff318..65ff6bf12f4bedbdd8b1fea28931e8cfbf4cbcef 100644 (file)
@@ -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);
        
index e3e823380fb79d56836a75b96e6605454978e886..cce6d48fbd0f0c8616dee0683931eb9a5cadf159 100644 (file)
@@ -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
index cc52729181b67dc20c76b627f0024092ab2ec602..a503a42dc1d9b02416b74b37e1166138a1414c7b 100644 (file)
@@ -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";
index dc59fa1026a055012ea5941bef849de34d5b5d19..c6e46bff423e9a51f38c495d48dc10da4e13f5f9 100644 (file)
@@ -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();
index 9e3eecee18a4a6f69509f0b7a3f770333ad546d8..be55133945932aa9e401732b2eee4a668de05868 100644 (file)
@@ -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');
 
 
 --
index e1a82958397e93d239b4947c65b6c453b4bb45c4..d2402b652246a706febd9776baefbeacaf44a8ad 100644 (file)
@@ -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;
                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 */; };
                        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 */;
                        );
                        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;
                184461A1146E9AD100B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = "<group>"; };
                184461A2146E9AD100B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = "<group>"; };
                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 = "<group>"; };
+               C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = ../../../usr/local/lib/libsecurity_utilities.a; sourceTree = "<group>"; };
                C2093AA60BB0948000EB8599 /* reqreader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqreader.cpp; sourceTree = "<group>"; };
                C2093AA70BB0948000EB8599 /* reqreader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqreader.h; sourceTree = "<group>"; };
-               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 = "<group>"; };
+               C209697215BF57EB0093035F /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; sourceTree = "<group>"; };
+               C2110704158BF5C8001D7F76 /* gkmerge */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gkmerge; sourceTree = "<group>"; };
                C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqdumper.cpp; sourceTree = "<group>"; };
                C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqdumper.h; sourceTree = "<group>"; };
                C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCodeSigner.cpp; sourceTree = "<group>"; };
                C24EABAC1421433700C16AA9 /* policydb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = policydb.cpp; sourceTree = "<group>"; };
                C250F6C20B5EF1910076098F /* SecIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrity.h; sourceTree = "<group>"; };
                C250F6C60B5EF5B50076098F /* SecIntegrity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIntegrity.cpp; sourceTree = "<group>"; };
-               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 = "<group>"; };
+               C2578CC315798D0F00D4FE48 /* gkgenerate */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkgenerate; sourceTree = "<group>"; };
+               C2578CC415798D0F00D4FE48 /* gkrecord */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkrecord; sourceTree = "<group>"; };
                C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sigblob.cpp; sourceTree = "<group>"; };
                C259DFD50AD6D9BA00C9ACC6 /* sigblob.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sigblob.h; sourceTree = "<group>"; };
+               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 = "<group>"; };
                C26763D614FD9EBE00A46EDF /* drmaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drmaker.h; sourceTree = "<group>"; };
                C26AC0F3143BD1B3001C98CE /* SystemPolicy */ = {isa = PBXFileReference; lastKnownFileType = text; name = SystemPolicy; path = cstemp/SystemPolicy; sourceTree = BUILT_PRODUCTS_DIR; };
                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 = "<group>"; };
                C273601D1432A60B00A9A5FF /* policyengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = policyengine.h; sourceTree = "<group>"; };
-               C27360201432A61900A9A5FF /* policyengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = policyengine.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
-               C273606C1433F09000A9A5FF /* SecAssessment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecAssessment.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
+               C27360201432A61900A9A5FF /* policyengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = policyengine.cpp; sourceTree = "<group>"; };
+               C273606C1433F09000A9A5FF /* SecAssessment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecAssessment.cpp; sourceTree = "<group>"; };
                C273606D1433F09000A9A5FF /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SecAssessment.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
-               C27360D41436866C00A9A5FF /* xpcengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = xpcengine.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
+               C27360D41436866C00A9A5FF /* xpcengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = xpcengine.cpp; sourceTree = "<group>"; };
                C27360D71436868600A9A5FF /* xpcengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xpcengine.h; sourceTree = "<group>"; };
-               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 = "<group>"; };
+               C278A19C158AB2C300FA6767 /* gklist */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gklist; sourceTree = "<group>"; };
                C28342E40E366E6800E54360 /* csdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = csdatabase.cpp; sourceTree = "<group>"; };
                C28342E50E366E6800E54360 /* csdatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = csdatabase.h; sourceTree = "<group>"; };
                C28342EB0E36719D00E54360 /* detachedrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detachedrep.cpp; sourceTree = "<group>"; };
                        );
                        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;
                4CA1FEA7052A3C3800F22E42 = {
                        isa = PBXGroup;
                        children = (
+                               C209697215BF57EB0093035F /* libsecurity_utilities.a */,
                                182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */,
                                4C308388053237100028A8C6 /* lib */,
                                1844619E146E9AD100B12992 /* config */,
                                4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */,
                                C2BC1F260B580D3A003EC9DC /* libintegrity.a */,
                                C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */,
+                               C209696015BF52040093035F /* gkunpack */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                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 */ = {
                C2CC30EF0B8519CF005FA59D /* Frameworks */ = {
                        isa = PBXGroup;
                        children = (
+                               C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */,
+                               C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */,
                                C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */,
                        );
                        name = Frameworks;
                        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" */;
                                C2BC1F2E0B580D4B003EC9DC /* libcodehost */,
                                C26AC7090DAEB3A7005BFB40 /* DTrace */,
                                C26AC0EB143BCF01001C98CE /* SystemPolicy */,
+                               C209695F15BF52040093035F /* gkunpack */,
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               C209695C15BF52040093035F /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               C209696415BF52040093035F /* gkunpack.cpp in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                C2BC1F230B580D3A003EC9DC /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        target = C26AC7090DAEB3A7005BFB40 /* DTrace */;
                        targetProxy = 1844617C146E9A5200B12992 /* PBXContainerItemProxy */;
                };
+               C209697015BF53330093035F /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = C209695F15BF52040093035F /* gkunpack */;
+                       targetProxy = C209696F15BF53330093035F /* PBXContainerItemProxy */;
+               };
                C250F6C50B5EF4E40076098F /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = C2BC1F250B580D3A003EC9DC /* libintegrity */;
 /* 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 */;
                        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;
                        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;
                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 = (
index 67c4e344e04dc6552712847a5ace657d65a783f0..f3394255ddea71506df8acbc97513d27aa436ce3 100644 (file)
@@ -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;
 }
index 6f26712dbabfc0f86c498bc979d17bcc7288df41..ca06db05a83c10094924b8261a06101b6c668070 100644 (file)
@@ -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;
index b807549e6e16e0a4bf0467235f3fed402ab54ba1..9b3cba1a992252227e5392b4fec45ee7eaa20a8e 100644 (file)
@@ -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)