1/* 2 * Copyright (c) 2006-2012 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// StaticCode - SecStaticCode API objects 26// 27#ifndef _H_STATICCODE 28#define _H_STATICCODE 29 30#include "cs.h" 31#include "Requirements.h" 32#include "requirement.h" 33#include "diskrep.h" 34#include "codedirectory.h" 35#include <Security/SecTrust.h> 36#include <CoreFoundation/CFData.h> 37 38namespace Security { 39namespace CodeSigning { 40 41 42class SecCode; 43 44 45// 46// A SecStaticCode object represents the file system version of some code. 47// There's a lot of pieces to this, and we'll bring them all into 48// memory here (lazily) and let you fondle them with ease. 49// 50// Note that concrete knowledge of where stuff is stored resides in the DiskRep 51// object we hold. DiskReps allocate, retrieve, and return data to us. We are 52// responsible for interpreting, caching, and validating them. (In other words, 53// DiskReps know where stuff is and how it is stored, but we know what it means.) 54// 55// Data accessors (returning CFDataRef, CFDictionaryRef, various pointers, etc.) 56// cache those values internally and return unretained(!) references ("Get" style) 57// that are valid as long as the SecStaticCode object's lifetime, or until 58// resetValidity() is called, whichever is sooner. If you need to keep them longer, 59// retain or copy them as needed. 60// 61class SecStaticCode : public SecCFObject { 62 NOCOPY(SecStaticCode) 63 64protected: 65 // 66 // A context for resource validation operations, to tailor error response. 67 // The base class throws an exception immediately and ignores detail data. 68 // 69 class ValidationContext { 70 public: 71 virtual ~ValidationContext(); 72 virtual void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value); 73 }; 74 75 // 76 // A CollectingContext collects all error details and throws an annotated final error. 77 // 78 class CollectingContext : public ValidationContext { 79 public: 80 CollectingContext(SecStaticCode &c) : code(c), mStatus(errSecSuccess) { } 81 void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value); 82 83 OSStatus osStatus() { return mStatus; } 84 operator OSStatus () const { return mStatus; } 85 void throwMe() __attribute__((noreturn)); 86 87 SecStaticCode &code; 88 89 private: 90 CFRef<CFMutableDictionaryRef> mCollection; 91 OSStatus mStatus; 92 }; 93 94public: 95 SECCFFUNCTIONS(SecStaticCode, SecStaticCodeRef, 96 errSecCSInvalidObjectRef, gCFObjects().StaticCode) 97 98 // implicitly convert SecCodeRefs to their SecStaticCodeRefs 99 static SecStaticCode *requiredStatic(SecStaticCodeRef ref); // convert SecCodeRef 100 static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL if static 101 102 SecStaticCode(DiskRep *rep); 103 virtual ~SecStaticCode() throw(); 104 105 bool equal(SecCFObject &other); 106 CFHashCode hash(); 107 108 void detachedSignature(CFDataRef sig); // attach an explicitly given detached signature 109 void checkForSystemSignature(); // check for and attach system-supplied detached signature 110 111 const CodeDirectory *codeDirectory(bool check = true); 112 CFDataRef cdHash(); 113 CFDataRef signature(); 114 CFAbsoluteTime signingTime(); 115 CFAbsoluteTime signingTimestamp(); 116 bool isSigned() { return codeDirectory(false) != NULL; } 117 DiskRep *diskRep() { return mRep; } 118 bool isDetached() const { return mRep->base() != mRep; } 119 std::string mainExecutablePath() { return mRep->mainExecutablePath(); } 120 CFURLRef copyCanonicalPath() const { return mRep->copyCanonicalPath(); } 121 std::string identifier() { return codeDirectory()->identifier(); } 122 const char *teamID() { return codeDirectory()->teamID(); } 123 std::string format() const { return mRep->format(); } 124 std::string signatureSource(); 125 virtual CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); 126 virtual CFDictionaryRef infoDictionary(); 127 128 CFDictionaryRef entitlements(); 129 130 CFDictionaryRef resourceDictionary(bool check = true); 131 CFURLRef resourceBase(); 132 CFDataRef resource(std::string path); 133 CFDataRef resource(std::string path, ValidationContext &ctx); 134 void validateResource(CFDictionaryRef files, std::string path, bool isSymlink, ValidationContext &ctx, SecCSFlags flags, uint32_t version); 135 136 bool flag(uint32_t tested); 137 138 SecCodeCallback monitor() const { return mMonitor; } 139 void setMonitor(SecCodeCallback monitor) { mMonitor = monitor; } 140 CFTypeRef reportEvent(CFStringRef stage, CFDictionaryRef info); 141 142 void setValidationModifiers(CFDictionaryRef modifiers); 143 144 void resetValidity(); // clear validation caches (if something may have changed) 145 146 bool validated() const { return mValidated; } 147 bool valid() const 148 { assert(validated()); return mValidated && (mValidationResult == errSecSuccess); } 149 bool validatedExecutable() const { return mExecutableValidated; } 150 bool validatedResources() const { return mResourcesValidated; } 151 152 void validateDirectory(); 153 virtual void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); 154 void validateNonResourceComponents(); 155 void validateResources(SecCSFlags flags); 156 void validateExecutable(); 157 void validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags, bool isFramework); 158 159 const Requirements *internalRequirements(); 160 const Requirement *internalRequirement(SecRequirementType type); 161 const Requirement *designatedRequirement(); 162 const Requirement *defaultDesignatedRequirement(); // newly allocated (caller owns) 163 164 void validateRequirements(SecRequirementType type, SecStaticCode *target, 165 OSStatus nullError = errSecSuccess); // target against my [type], throws 166 void validateRequirement(const Requirement *req, OSStatus failure); // me against [req], throws 167 bool satisfiesRequirement(const Requirement *req, OSStatus failure); // me against [req], returns on clean miss 168 169 // certificates are available after signature validation (they are stored in the CMS signature) 170 SecCertificateRef cert(int ix); // get a cert from the cert chain 171 CFArrayRef certificates(); // get the entire certificate chain 172 173 CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary) 174 175 static bool isAppleDeveloperCert(CFArrayRef certs); // determines if this is an apple developer certificate for libraray validation 176 177public: 178 void staticValidate(SecCSFlags flags, const SecRequirement *req); 179 void staticValidateCore(SecCSFlags flags, const SecRequirement *req); 180 181protected: 182 CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, bool check = true); // component value as a dictionary 183 bool verifySignature(); 184 CFTypeRef verificationPolicy(SecCSFlags flags); 185 186 static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context); 187 bool hasWeakResourceRules(CFDictionaryRef rulesDict, CFArrayRef allowedOmissions); 188 189 void handleOtherArchitectures(void (^handle)(SecStaticCode* other)); 190 191private: 192 void validateOtherVersions(CFURLRef path, SecCSFlags flags, SecRequirementRef req, SecStaticCode *code); 193 194private: 195 RefPointer<DiskRep> mRep; // on-disk representation 196 CFRef<CFDataRef> mDetachedSig; // currently applied explicit detached signature 197 198 // private validation modifiers (only used by Gatekeeper checkfixes) 199 MacOSErrorSet mTolerateErrors; // soft error conditions to ignore 200 CFRef<CFArrayRef> mAllowOmissions; // additionally allowed resource omissions 201 202 // master validation state 203 bool mValidated; // core validation was attempted 204 OSStatus mValidationResult; // outcome of core validation 205 bool mValidationExpired; // outcome had expired certificates 206 207 // static executable validation state (nested within mValidated/mValid) 208 bool mExecutableValidated; // tried to validate executable file 209 OSStatus mExecutableValidResult; // outcome if mExecutableValidated 210 211 // static resource validation state (nested within mValidated/mValid) 212 bool mResourcesValidated; // tried to validate resources 213 bool mResourcesDeep; // cached validation was deep 214 OSStatus mResourcesValidResult; // outcome if mResourceValidated or... 215 CollectingContext *mResourcesValidContext; // 216 217 // cached contents 218 CFRef<CFDataRef> mDir; // code directory data 219 CFRef<CFDataRef> mSignature; // CMS signature data 220 CFAbsoluteTime mSigningTime; // (signed) signing time 221 CFAbsoluteTime mSigningTimestamp; // Timestamp time (from timestamping authority) 222 CFRef<CFDataRef> mCache[cdSlotCount]; // NULL => not tried, kCFNull => absent, other => present 223 224 // alternative cache forms (storage may depend on cached contents above) 225 CFRef<CFDictionaryRef> mInfoDict; // derived from mCache slot 226 CFRef<CFDictionaryRef> mEntitlements; // derived from mCache slot 227 CFRef<CFDictionaryRef> mResourceDict; // derived from mCache slot 228 const Requirement *mDesignatedReq; // cached designated req if we made one up 229 CFRef<CFDataRef> mCDHash; // hash of CodeDirectory 230 231 bool mGotResourceBase; // asked mRep for resourceBasePath 232 CFRef<CFURLRef> mResourceBase; // URL form of resource base directory 233 234 SecCodeCallback mMonitor; // registered monitor callback 235 236 // signature verification outcome (mTrust == NULL => not done yet) 237 CFRef<SecTrustRef> mTrust; // outcome of crypto validation (valid or not) 238 CFRef<CFArrayRef> mCertChain; 239 CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails; 240}; 241 242 243} // end namespace CodeSigning 244} // end namespace Security 245 246#endif // !_H_STATICCODE 247