/ OSX / libsecurity_codesigning / lib / singlediskrep.cpp
singlediskrep.cpp
  1  /*
  2   * Copyright (c) 2006-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  // singlediskrep - semi-abstract diskrep for a single file of some kind
 26  //
 27  #include "singlediskrep.h"
 28  #include "csutilities.h"
 29  #include <security_utilities/cfutilities.h>
 30  #include <sys/stat.h>
 31  
 32  namespace Security {
 33  namespace CodeSigning {
 34  
 35  using namespace UnixPlusPlus;
 36  
 37  
 38  //
 39  // Construct a SingleDiskRep
 40  //
 41  SingleDiskRep::SingleDiskRep(const std::string &path)
 42  	: mPath(path)
 43  {
 44  }
 45  
 46  
 47  //
 48  // The default binary identification of a SingleDiskRep is the (SHA-1) hash
 49  // of the entire file itself.
 50  //
 51  CFDataRef SingleDiskRep::identification()
 52  {
 53  	SHA1 hash;
 54  	this->fd().seek(0);
 55  	hashFileData(this->fd(), &hash);
 56  	SHA1::Digest digest;
 57  	hash.finish(digest);
 58  	return makeCFData(digest, sizeof(digest));
 59  }
 60  
 61  
 62  //
 63  // Both the canonical and main executable path of a SingleDiskRep is, well, its path.
 64  //
 65  CFURLRef SingleDiskRep::copyCanonicalPath()
 66  {
 67  	return makeCFURL(mPath);
 68  }
 69  
 70  string SingleDiskRep::mainExecutablePath()
 71  {
 72  	return mPath;
 73  }
 74  
 75  
 76  //
 77  // The default signing limit is the size of the file.
 78  // This will do unless the signing data gets creatively stuck in there somewhere.
 79  //
 80  size_t SingleDiskRep::signingLimit()
 81  {
 82  	return fd().fileSize();
 83  }
 84  
 85  //
 86  // No executable segment in non-machO files.
 87  //
 88  size_t SingleDiskRep::execSegLimit(const Architecture *)
 89  {
 90  	return 0;
 91  }
 92  
 93  //
 94  // A lazily opened read-only file descriptor for the path.
 95  //
 96  FileDesc &SingleDiskRep::fd()
 97  {
 98  	if (!mFd)
 99  		mFd.open(mPath, O_RDONLY);
100  	return mFd;
101  }
102  
103  //
104  // Flush cached state
105  //
106  void SingleDiskRep::flush()
107  {
108  	mFd.close();
109  }
110  
111  //Check the magic darwinup xattr
112  bool SingleDiskRep::appleInternalForcePlatform() const
113  {
114  	return mFd.hasExtendedAttribute("com.apple.root.installed");
115  }
116  
117  //
118  // The recommended identifier of a SingleDiskRep is, absent any better clue,
119  // the basename of its path.
120  //
121  string SingleDiskRep::recommendedIdentifier(const SigningContext &)
122  {
123  	return canonicalIdentifier(mPath);
124  }
125  	
126  	
127  //
128  // Paranoid validation
129  //
130  void SingleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags)
131  {
132  	DiskRep::strictValidate(cd, tolerated, flags);
133  
134  	if (flags & kSecCSRestrictSidebandData)
135  		if (fd().hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd().hasExtendedAttribute(XATTR_FINDERINFO_NAME))
136  			if (tolerated.find(errSecCSInvalidAssociatedFileData) == tolerated.end())
137  				MacOSError::throwMe(errSecCSInvalidAssociatedFileData);
138  	
139  	// code limit must cover (exactly) the entire file
140  	if (cd && cd->signingLimit() != signingLimit())
141  		MacOSError::throwMe(errSecCSSignatureInvalid);
142  }
143  
144  
145  
146  //
147  // Prototype Writers
148  //
149  FileDesc &SingleDiskRep::Writer::fd()
150  {
151  	if (!mFd)
152  		mFd.open(rep->path(), O_RDWR);
153  	return mFd;
154  }
155  
156  
157  } // end namespace CodeSigning
158  } // end namespace Security