X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_keychain/Security/TrustedApplication.cpp diff --git a/OSX/libsecurity_keychain/Security/TrustedApplication.cpp b/OSX/libsecurity_keychain/Security/TrustedApplication.cpp new file mode 100644 index 00000000..977eba37 --- /dev/null +++ b/OSX/libsecurity_keychain/Security/TrustedApplication.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2002-2004,2011-2014 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@ + */ + +// +// TrustedApplication.cpp +// +#include +#include +#include +#include +#include +#include +#include + +using namespace KeychainCore; + + +// +// Create a TrustedApplication from a code-signing ACL subject. +// Throws ACL::ParseError if the subject is unexpected. +// +TrustedApplication::TrustedApplication(const TypedList &subject) +{ + try { + CodeSignatureAclSubject::Maker maker; + mForm = maker.make(subject); + secdebug("trustedapp", "%p created from list form", this); + IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from list")); + } catch (...) { + throw ACL::ParseError(); + } +} + + +// +// Create a TrustedApplication from a path-to-object-on-disk +// +TrustedApplication::TrustedApplication(const std::string &path) +{ + RefPointer code(OSXCode::at(path)); + mForm = new CodeSignatureAclSubject(OSXVerifier(code)); + secdebug("trustedapp", "%p created from path %s", this, path.c_str()); + IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from path")); +} + + +// +// Create a TrustedApplication for the calling process +// +TrustedApplication::TrustedApplication() +{ + //@@@@ should use CS's idea of "self" + RefPointer me(OSXCode::main()); + mForm = new CodeSignatureAclSubject(OSXVerifier(me)); + secdebug("trustedapp", "%p created from self", this); + IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from self")); +} + + +// +// Create a TrustedApplication from a SecRequirementRef. +// Note that the path argument is only stored for documentation; +// it is NOT used to denote anything on disk. +// +TrustedApplication::TrustedApplication(const std::string &path, SecRequirementRef reqRef) +{ + CFRef reqData; + MacOSError::check(SecRequirementCopyData(reqRef, kSecCSDefaultFlags, &reqData.aref())); + mForm = new CodeSignatureAclSubject(NULL, path); + mForm->add((const BlobCore *)CFDataGetBytePtr(reqData)); + secdebug("trustedapp", "%p created from path %s and requirement %p", + this, path.c_str(), reqRef); + IFDUMPING("codesign", mForm->debugDump()); +} + + +TrustedApplication::~TrustedApplication() +{ /* virtual */ } + + +// +// Convert from/to external data form. +// +// Since a TrustedApplication's data is essentially a CodeSignatureAclSubject, +// we just use the subject's externalizer to produce the data. That requires us +// to use the somewhat idiosyncratic linearizer used by CSSM ACL subjects, but +// that's a small price to pay for consistency. +// +TrustedApplication::TrustedApplication(CFDataRef external) +{ + AclSubject::Reader pubReader(CFDataGetBytePtr(external)), privReader; + mForm = CodeSignatureAclSubject::Maker().make(0, pubReader, privReader); +} + +CFDataRef TrustedApplication::externalForm() const +{ + AclSubject::Writer::Counter pubCounter, privCounter; + mForm->exportBlob(pubCounter, privCounter); + if (privCounter > 0) // private exported data - format violation + CssmError::throwMe(CSSMERR_CSSM_INTERNAL_ERROR); + CFRef data = CFDataCreateMutable(NULL, pubCounter); + CFDataSetLength(data, pubCounter); + if (CFDataGetLength(data) < CFIndex(pubCounter)) + CFError::throwMe(); + AclSubject::Writer pubWriter(CFDataGetMutableBytePtr(data)), privWriter; + mForm->exportBlob(pubWriter, privWriter); + return data.yield(); +} + +void TrustedApplication::data(CFDataRef data) +{ + const char *p = (const char *)CFDataGetBytePtr(data); + const std::string path(p, p + CFDataGetLength(data)); + RefPointer code(OSXCode::at(path)); + mForm = new CodeSignatureAclSubject(OSXVerifier(code)); +} + +// +// Direct verification interface. +// If path == NULL, we verify against the running code itself. +// +bool TrustedApplication::verifyToDisk(const char *path) +{ + if (SecRequirementRef requirement = mForm->requirement()) { + secdebug("trustedapp", "%p validating requirement against path %s", this, path); + CFRef ondisk; + if (path) + MacOSError::check(SecStaticCodeCreateWithPath(CFTempURL(path), + kSecCSDefaultFlags, &ondisk.aref())); + else + MacOSError::check(SecCodeCopySelf(kSecCSDefaultFlags, (SecCodeRef *)&ondisk.aref())); + return SecStaticCodeCheckValidity(ondisk, kSecCSDefaultFlags, requirement) == errSecSuccess; + } else { + secdebug("trustedapp", "%p validating hash against path %s", this, path); + RefPointer code = path ? OSXCode::at(path) : OSXCode::main(); + SHA1::Digest ondiskDigest; + OSXVerifier::makeLegacyHash(code, ondiskDigest); + return memcmp(ondiskDigest, mForm->legacyHash(), sizeof(ondiskDigest)) == 0; + } +} + + +// +// Produce a TypedList representing a code-signing ACL subject +// for this application. +// Memory is allocated from the allocator given, and belongs to +// the caller. +// +CssmList TrustedApplication::makeSubject(Allocator &allocator) +{ + return mForm->toList(allocator); +} + +