]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_codesigning/lib/signerutils.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_codesigning / lib / signerutils.cpp
diff --git a/libsecurity_codesigning/lib/signerutils.cpp b/libsecurity_codesigning/lib/signerutils.cpp
deleted file mode 100644 (file)
index 74dd23c..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-//
-// signerutils - utilities for signature generation
-//
-#include "signerutils.h"
-#include "signer.h"
-#include "SecCodeSigner.h"
-#include <Security/SecIdentity.h>
-#include <Security/CMSEncoder.h>
-#include "resources.h"
-#include "csutilities.h"
-#include "drmaker.h"
-#include <security_utilities/unix++.h>
-#include <security_utilities/unixchild.h>
-#include <vector>
-
-// for helper validation
-#include "Code.h"
-#include <security_utilities/cfmunge.h>
-#include <sys/codesign.h>
-
-
-namespace Security {
-namespace CodeSigning {
-
-
-//
-// About the Mach-O allocation helper
-//
-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;
-
-
-//
-// BlobWriters
-//
-void BlobWriter::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
-{
-       return EmbeddedSignatureBlob::Maker::component(slot, data);
-}
-
-
-void DetachedBlobWriter::flush()
-{
-       EmbeddedSignatureBlob *blob = this->make();
-       signer.code->detachedSignature(CFTempData(*blob));
-       signer.state.returnDetachedSignature(blob, signer);
-       ::free(blob);
-}
-
-
-//
-// ArchEditor
-//
-ArchEditor::ArchEditor(Universal &code, CodeDirectory::HashAlgorithm hashType, uint32_t attrs)
-       : DiskRep::Writer(attrs)
-{
-       Universal::Architectures archList;
-       code.architectures(archList);
-       for (Universal::Architectures::const_iterator it = archList.begin();
-                       it != archList.end(); ++it)
-               architecture[*it] = new Arch(*it, hashType);
-}
-
-
-ArchEditor::~ArchEditor()
-{
-       for (ArchMap::iterator it = begin(); it != end(); ++it)
-               delete it->second;
-}
-
-
-//
-// BlobEditor
-//
-BlobEditor::BlobEditor(Universal &fat, SecCodeSigner::Signer &s)
-       : ArchEditor(fat, s.digestAlgorithm(), 0), signer(s)
-{ }
-
-
-void BlobEditor::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
-{
-       mGlobal.component(slot, data);
-}
-
-void BlobEditor::write(Arch &arch, EmbeddedSignatureBlob *blob)
-{
-       mMaker.add(arch.architecture.cpuType(), blob);
-}
-
-
-void BlobEditor::commit()
-{
-       // create the architecture-global blob and store it into the superblob
-       mMaker.add(0, mGlobal.make());  // takes ownership of blob
-
-       // finish up the superblob and deliver it
-       DetachedSignatureBlob *blob = mMaker.make();
-       signer.state.returnDetachedSignature(blob, signer);
-       ::free(blob);
-}
-
-
-//
-// MachOEditor's allocate() method spawns the codesign_allocate helper tool to
-// "drill up" the Mach-O binary for insertion of Code Signing signature data.
-// After the tool succeeds, we open the new file and are ready to write it.
-//
-MachOEditor::MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath)
-       : ArchEditor(code, hashType, 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->kill();
-}
-
-
-void MachOEditor::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
-{
-       writer->component(slot, data);
-}
-
-
-void MachOEditor::allocate()
-{
-       // note that we may have a temporary file from now on (for cleanup in the error case)
-       mTempMayExist = true;
-
-       // run codesign_allocate to make room in the executable file
-       fork();
-       wait();
-       if (!Child::succeeded())
-               MacOSError::throwMe(errSecCSHelperFailed);
-       
-       // open the new (temporary) Universal file
-       {
-               UidGuard guard(0);
-               mFd.open(tempPath, O_RDWR);
-       }
-       mNewCode = new Universal(mFd);
-}
-
-static const unsigned char appleReq[] = {
-       // anchor apple and info["Application-Group"] = "com.apple.tool.codesign_allocate"
-       0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06,
-       0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x11, 0x41, 0x70, 0x70, 0x6c,
-       0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c,
-       0x65, 0x2e, 0x74, 0x6f, 0x6f, 0x6c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x5f,
-       0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65,
-};
-
-void MachOEditor::parentAction()
-{
-       if (mHelperOverridden) {
-               CODESIGN_ALLOCATE_VALIDATE((char*)mHelperPath, this->pid());
-               // check code identity of an overridden allocation helper
-               SecPointer<SecStaticCode> code = new SecStaticCode(DiskRep::bestGuess(mHelperPath));
-               code->staticValidate(kSecCSDefaultFlags, NULL);
-               code->validateRequirement((const Requirement *)appleReq, errSecCSReqFailed);
-       }
-}
-
-void MachOEditor::childAction()
-{
-       vector<const char *> arguments;
-       arguments.push_back(helperName);
-       arguments.push_back("-i");
-       arguments.push_back(sourcePath.c_str());
-       arguments.push_back("-o");
-       arguments.push_back(tempPath.c_str());
-       
-       for (Iterator it = architecture.begin(); it != architecture.end(); ++it) {
-               size_t size = LowLevelMemoryUtilities::alignUp(it->second->blobSize, csAlign);
-               char *ssize;                    // we'll leak this (execv is coming soon)
-               asprintf(&ssize, "%zd", size);
-
-               if (const char *arch = it->first.name()) {
-                       CODESIGN_ALLOCATE_ARCH((char*)arch, (unsigned int)size);
-                       arguments.push_back("-a");
-                       arguments.push_back(arch);
-               } else {
-                       CODESIGN_ALLOCATE_ARCHN(it->first.cpuType(), it->first.cpuSubtype(), (unsigned int)size);
-                       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(ssize);
-       }
-       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(mHelperPath, (char * const *)&arguments[0]);
-}
-
-void MachOEditor::reset(Arch &arch)
-{
-       arch.source.reset(mNewCode->architecture(arch.architecture));
-       arch.cdbuilder.reopen(tempPath,
-               arch.source->offset(), arch.source->signingOffset());
-}
-
-
-//
-// MachOEditor's write() method actually writes the blob into the CODESIGNING section
-// of the executable image file.
-//
-void MachOEditor::write(Arch &arch, EmbeddedSignatureBlob *blob)
-{
-       if (size_t offset = arch.source->signingOffset()) {
-               size_t signingLength = arch.source->signingLength();
-               CODESIGN_ALLOCATE_WRITE((char*)arch.architecture.name(), offset, (unsigned)blob->length(), (unsigned)signingLength);
-               if (signingLength < blob->length())
-                       MacOSError::throwMe(errSecCSCMSTooLarge);
-               arch.source->seek(offset);
-               arch.source->writeAll(*blob);
-               ::free(blob);           // done with it
-       } else {
-               secdebug("signer", "%p cannot find CODESIGNING section", this);
-               MacOSError::throwMe(errSecCSInternalError);
-       }
-}
-
-
-//
-// Commit the edit.
-// This moves the temporary editor copy over the source image file.
-// Note that the Universal object returned by allocate() is still open
-// and valid; the caller owns it.
-//
-void MachOEditor::commit()
-{
-       // if the file's owned by someone else *and* we can become root...
-       struct stat st;
-       UnixError::check(::stat(sourcePath.c_str(), &st));
-
-       // copy over all the *other* stuff
-       Copyfile copy;
-       int fd = mFd;
-       copy.set(COPYFILE_STATE_DST_FD, &fd);
-       {
-               // perform copy under root or file-owner privileges if available
-               UidGuard guard;
-               if (!guard.seteuid(0))
-                       guard.seteuid(st.st_uid);
-               
-               // copy metadata from original file...
-               copy(sourcePath.c_str(), NULL, COPYFILE_SECURITY | COPYFILE_METADATA);
-               
-               // ... but explicitly update the timestamps since we did change the file
-               char buf;
-               mFd.read(&buf, sizeof(buf), 0);
-               mFd.write(&buf, sizeof(buf), 0);
-
-               // move the new file into place
-               UnixError::check(::rename(tempPath.c_str(), sourcePath.c_str()));
-               mTempMayExist = false;          // we renamed it away
-       }
-}
-
-
-//
-// InternalRequirements
-//
-void InternalRequirements::operator () (const Requirements *given, const Requirements *defaulted, const Requirement::Context &context)
-{
-       // first add the default internal requirements
-       if (defaulted) {
-               this->add(defaulted);
-               ::free((void *)defaulted);              // was malloc(3)ed by DiskRep
-       }
-       
-       // now override them with any requirements explicitly given by the signer
-       if (given)
-               this->add(given);
-
-       // now add the Designated Requirement, if we can make it and it's not been provided
-       if (!this->contains(kSecDesignatedRequirementType)) {
-               DRMaker maker(context);
-               if (Requirement *dr = maker.make()) {
-                       this->add(kSecDesignatedRequirementType, dr);           // takes ownership of dr
-               }
-       }
-       
-       // return the result
-       mReqs = this->make();
-}
-
-
-//
-// Pre-Signing contexts
-//
-PreSigningContext::PreSigningContext(const SecCodeSigner::Signer &signer)
-{
-       // construct a cert chain
-       if (signer.signingIdentity() != SecIdentityRef(kCFNull)) {
-               CFRef<SecCertificateRef> signingCert;
-               MacOSError::check(SecIdentityCopyCertificate(signer.signingIdentity(), &signingCert.aref()));
-               CFRef<SecPolicyRef> policy = SecPolicyCreateWithOID(kSecPolicyAppleCodeSigning);
-               CFRef<SecTrustRef> trust;
-               MacOSError::check(SecTrustCreateWithCertificates(CFArrayRef(signingCert.get()), policy, &trust.aref()));
-               SecTrustResultType result;
-               MacOSError::check(SecTrustEvaluate(trust, &result));
-               CSSM_TP_APPLE_EVIDENCE_INFO *info;
-               MacOSError::check(SecTrustGetResult(trust, &result, &mCerts.aref(), &info));
-               this->certs = mCerts;
-       }
-       
-       // other stuff
-       this->identifier = signer.signingIdentifier();
-}
-
-
-} // end namespace CodeSigning
-} // end namespace Security