TrustedApplication.cpp
1 /* 2 * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 // 25 // TrustedApplication.cpp 26 // 27 #include <security_keychain/TrustedApplication.h> 28 #include <security_keychain/ACL.h> 29 #include <security_utilities/osxcode.h> 30 #include <security_utilities/trackingallocator.h> 31 #include <security_cdsa_utilities/acl_codesigning.h> 32 #include <sys/syslimits.h> 33 #include <memory> 34 35 using namespace KeychainCore; 36 37 38 // 39 // Create a TrustedApplication from a code-signing ACL subject. 40 // Throws ACL::ParseError if the subject is unexpected. 41 // 42 TrustedApplication::TrustedApplication(const TypedList &subject) 43 { 44 try { 45 CodeSignatureAclSubject::Maker maker; 46 mForm = maker.make(subject); 47 secinfo("trustedapp", "%p created from list form", this); 48 IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from list")); 49 } catch (...) { 50 throw ACL::ParseError(); 51 } 52 } 53 54 55 // 56 // Create a TrustedApplication from a path-to-object-on-disk 57 // 58 TrustedApplication::TrustedApplication(const std::string &path) 59 { 60 RefPointer<OSXCode> code(OSXCode::at(path)); 61 mForm = new CodeSignatureAclSubject(OSXVerifier(code)); 62 secinfo("trustedapp", "%p created from path %s", this, path.c_str()); 63 IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from path")); 64 } 65 66 67 // 68 // Create a TrustedApplication for the calling process 69 // 70 TrustedApplication::TrustedApplication() 71 { 72 //@@@@ should use CS's idea of "self" 73 RefPointer<OSXCode> me(OSXCode::main()); 74 mForm = new CodeSignatureAclSubject(OSXVerifier(me)); 75 secinfo("trustedapp", "%p created from self", this); 76 IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from self")); 77 } 78 79 80 // 81 // Create a TrustedApplication from a SecRequirementRef. 82 // Note that the path argument is only stored for documentation; 83 // it is NOT used to denote anything on disk. 84 // 85 TrustedApplication::TrustedApplication(const std::string &path, SecRequirementRef reqRef) 86 { 87 CFRef<CFDataRef> reqData; 88 MacOSError::check(SecRequirementCopyData(reqRef, kSecCSDefaultFlags, &reqData.aref())); 89 mForm = new CodeSignatureAclSubject(NULL, path); 90 mForm->add((const BlobCore *)CFDataGetBytePtr(reqData)); 91 secinfo("trustedapp", "%p created from path %s and requirement %p", 92 this, path.c_str(), reqRef); 93 IFDUMPING("codesign", mForm->debugDump()); 94 } 95 96 97 TrustedApplication::~TrustedApplication() 98 { /* virtual */ } 99 100 101 // 102 // Convert from/to external data form. 103 // 104 // Since a TrustedApplication's data is essentially a CodeSignatureAclSubject, 105 // we just use the subject's externalizer to produce the data. That requires us 106 // to use the somewhat idiosyncratic linearizer used by CSSM ACL subjects, but 107 // that's a small price to pay for consistency. 108 // 109 TrustedApplication::TrustedApplication(CFDataRef external) 110 { 111 AclSubject::Reader pubReader(CFDataGetBytePtr(external)), privReader; 112 mForm = CodeSignatureAclSubject::Maker().make(0, pubReader, privReader); 113 } 114 115 CFDataRef TrustedApplication::externalForm() const 116 { 117 AclSubject::Writer::Counter pubCounter, privCounter; 118 mForm->exportBlob(pubCounter, privCounter); 119 if (privCounter > 0) // private exported data - format violation 120 CssmError::throwMe(CSSMERR_CSSM_INTERNAL_ERROR); 121 CFRef<CFMutableDataRef> data = CFDataCreateMutable(NULL, pubCounter); 122 CFDataSetLength(data, pubCounter); 123 if (CFDataGetLength(data) < CFIndex(pubCounter)) 124 CFError::throwMe(); 125 AclSubject::Writer pubWriter(CFDataGetMutableBytePtr(data)), privWriter; 126 mForm->exportBlob(pubWriter, privWriter); 127 return data.yield(); 128 } 129 130 void TrustedApplication::data(CFDataRef data) 131 { 132 const char *p = (const char *)CFDataGetBytePtr(data); 133 const std::string path(p, p + CFDataGetLength(data)); 134 RefPointer<OSXCode> code(OSXCode::at(path)); 135 mForm = new CodeSignatureAclSubject(OSXVerifier(code)); 136 } 137 138 // 139 // Direct verification interface. 140 // If path == NULL, we verify against the running code itself. 141 // 142 bool TrustedApplication::verifyToDisk(const char *path) 143 { 144 if (SecRequirementRef requirement = mForm->requirement()) { 145 secinfo("trustedapp", "%p validating requirement against path %s", this, path); 146 CFRef<SecStaticCodeRef> ondisk; 147 if (path) 148 MacOSError::check(SecStaticCodeCreateWithPath(CFTempURL(path), 149 kSecCSDefaultFlags, &ondisk.aref())); 150 else 151 MacOSError::check(SecCodeCopySelf(kSecCSDefaultFlags, (SecCodeRef *)&ondisk.aref())); 152 return SecStaticCodeCheckValidity(ondisk, kSecCSDefaultFlags, requirement) == errSecSuccess; 153 } else { 154 secinfo("trustedapp", "%p validating hash against path %s", this, path); 155 RefPointer<OSXCode> code = path ? OSXCode::at(path) : OSXCode::main(); 156 SHA1::Digest ondiskDigest; 157 OSXVerifier::makeLegacyHash(code, ondiskDigest); 158 return memcmp(ondiskDigest, mForm->legacyHash(), sizeof(ondiskDigest)) == 0; 159 } 160 } 161 162 163 // 164 // Produce a TypedList representing a code-signing ACL subject 165 // for this application. 166 // Memory is allocated from the allocator given, and belongs to 167 // the caller. 168 // 169 CssmList TrustedApplication::makeSubject(Allocator &allocator) 170 { 171 return mForm->toList(allocator); 172 } 173 174