namespace CodeSigning {
 
 
+static CFStringRef appleIntermediateCN = CFSTR("Apple Code Signing Certification Authority");
+static CFStringRef appleIntermediateO = CFSTR("Apple Inc.");
+
+
 //
 // Construct an interpreter given a Requirement and an evaluation context.
 //
        case opIdent:
                return getString() == mContext->directory->identifier();
        case opAppleAnchor:
-               if (SecCertificateRef cert = mContext->cert(anchorCert))
-                       return verifyAnchor(cert, appleAnchorHash())
-#if defined(TEST_APPLE_ANCHOR)
-                               || verifyAnchor(cert, testAppleAnchorHash())
-#endif
-                       ;
-       else
-                       return false;
+               return appleSigned();
        case opAnchorHash:
                {
                        SecCertificateRef cert = mContext->cert(get<int32_t>());
 }
 
 
+//
+// Check the Apple-signed condition
+//
+bool Requirement::Interpreter::appleSigned()
+{
+       if (SecCertificateRef cert = mContext->cert(anchorCert))
+               if (verifyAnchor(cert, appleAnchorHash())
+#if defined(TEST_APPLE_ANCHOR)
+                       || verifyAnchor(cert, testAppleAnchorHash())
+#endif
+               )
+                       if (SecCertificateRef intermed = mContext->cert(-2))    // first intermediate
+                               // first intermediate common name match (exact)
+                               if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed)
+                                       && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed))
+                                       return true;
+       return false;
+}
+
+
 //
 // Verify an anchor requirement against the context
 //
 
 #include <security_utilities/unixchild.h>
 #include <vector>
 
+// for helper validation
+#include "Code.h"
+#include "cfmunge.h"
+#include <sys/codesign.h>
+
+
 namespace Security {
 namespace CodeSigning {
 
 //
 static const char helperName[] = "codesign_allocate";
 static const char helperPath[] = "/usr/bin/codesign_allocate";
+static const char helperOverride[] = "CODESIGN_ALLOCATE";
 static const size_t csAlign = 16;
 
 
        : ArchEditor(code, w->attributes()), writer(w), sourcePath(srcPath), tempPath(srcPath + ".cstemp"),
          mNewCode(NULL), mTempMayExist(false)
 {
+       if (const char *path = getenv(helperOverride)) {
+               mHelperPath = path;
+               mHelperOverridden = true;
+       } else {
+               mHelperPath = helperPath;
+               mHelperOverridden = false;
+       }
 }
 
 MachOEditor::~MachOEditor()
        delete mNewCode;
        if (mTempMayExist)
                ::remove(tempPath.c_str());             // ignore error (can't do anything about it)
+
+       //@@@ this code should be in UnixChild::kill() -- migrate it there
+       if (state() == alive) {
+               this->kill(SIGTERM);            // shoot it once
+               checkChildren();                        // check for quick death
+               if (state() == alive) {
+                       usleep(500000);                 // give it some grace
+                       if (state() == alive) { // could have been reaped by another thread
+                               checkChildren();        // check again
+                               if (state() == alive) { // it... just... won't... die...
+                                       this->kill(SIGKILL); // take THAT!
+                                       checkChildren();
+                                       if (state() == alive) // stuck zombie
+                                               abandon();      // leave the body behind
+                               }
+                       }
+               }
+       }
 }
 
 
        mNewCode = new Universal(mFd);
 }
 
+static const unsigned char appleReq[] = {      // anchor apple
+       0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
+};
+
+void MachOEditor::parentAction()
+{
+       if (mHelperOverridden) {
+               secdebug("machoedit", "validating alternate codesign_allocate at %s (pid=%d)", mHelperPath, this->pid());
+               // check code identity of an overridden allocation helper
+               SecPointer<SecStaticCode> code = new SecStaticCode(DiskRep::bestGuess(mHelperPath));
+               code->validateDirectory();
+               code->validateExecutable();
+               code->validateResources();
+               code->validateRequirements((const Requirement *)appleReq, errSecCSReqFailed);
+       }
+}
+
 void MachOEditor::childAction()
 {
        vector<const char *> arguments;
                char *size;                             // we'll leak this (execv is coming soon)
                asprintf(&size, "%d", LowLevelMemoryUtilities::alignUp(it->second->blobSize, csAlign));
                secdebug("machoedit", "preparing %s size=%s", it->first.name(), size);
-               arguments.push_back("-a");
-               arguments.push_back(it->first.name());
+
+               if (const char *arch = it->first.name()) {
+                       arguments.push_back("-a");
+                       arguments.push_back(arch);
+               } else {
+                       arguments.push_back("-A");
+                       char *anum;
+                       asprintf(&anum, "%d", it->first.cpuType());
+                       arguments.push_back(anum);
+                       asprintf(&anum, "%d", it->first.cpuSubtype());
+                       arguments.push_back(anum);
+               }
                arguments.push_back(size);
        }
        arguments.push_back(NULL);
+       
+       if (mHelperOverridden)
+               ::csops(0, CS_EXEC_SET_KILL, NULL, 0);          // force code integrity
        ::seteuid(0);   // activate privilege if caller has it; ignore error if not
-       execv(helperPath, (char * const *)&arguments[0]);
+       execv(mHelperPath, (char * const *)&arguments[0]);
 }
 
 void MachOEditor::reset(Arch &arch)
 
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                BUILD_VARIANTS = debug;
-                               CURRENT_PROJECT_VERSION = 32568;
+                               CURRENT_PROJECT_VERSION = 32953;
                                FRAMEWORK_SEARCH_PATHS = (
                                        /usr/local/SecurityPieces/Frameworks,
                                        /usr/local/SecurityPieces/Components/Security,
                                        normal,
                                        debug,
                                );
-                               CURRENT_PROJECT_VERSION = 32568;
+                               CURRENT_PROJECT_VERSION = 32953;
                                FRAMEWORK_SEARCH_PATHS = (
                                        /usr/local/SecurityPieces/Frameworks,
                                        /usr/local/SecurityPieces/Components/Security,
                                        normal,
                                        debug,
                                );
-                               CURRENT_PROJECT_VERSION = 32568;
+                               CURRENT_PROJECT_VERSION = 32953;
                                FRAMEWORK_SEARCH_PATHS = (
                                        /usr/local/SecurityPieces/Frameworks,
                                        /usr/local/SecurityPieces/Components/Security,