/ OSX / libsecurity_keychain / lib / TrustedApplication.cpp
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