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,