]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_codesigning/lib/StaticCode.h
Security-58286.240.4.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / StaticCode.h
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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"
d87e1158 31#include "csutilities.h"
b1ab9ed8
A
32#include "Requirements.h"
33#include "requirement.h"
34#include "diskrep.h"
35#include "codedirectory.h"
36#include <Security/SecTrust.h>
37#include <CoreFoundation/CFData.h>
d87e1158 38#include <security_utilities/dispatch.h>
b1ab9ed8
A
39
40namespace Security {
41namespace CodeSigning {
42
43
44class SecCode;
45
46
47//
48// A SecStaticCode object represents the file system version of some code.
49// There's a lot of pieces to this, and we'll bring them all into
50// memory here (lazily) and let you fondle them with ease.
51//
52// Note that concrete knowledge of where stuff is stored resides in the DiskRep
53// object we hold. DiskReps allocate, retrieve, and return data to us. We are
54// responsible for interpreting, caching, and validating them. (In other words,
55// DiskReps know where stuff is and how it is stored, but we know what it means.)
56//
57// Data accessors (returning CFDataRef, CFDictionaryRef, various pointers, etc.)
58// cache those values internally and return unretained(!) references ("Get" style)
59// that are valid as long as the SecStaticCode object's lifetime, or until
427c49bc 60// resetValidity() is called, whichever is sooner. If you need to keep them longer,
b1ab9ed8
A
61// retain or copy them as needed.
62//
63class SecStaticCode : public SecCFObject {
64 NOCOPY(SecStaticCode)
65
66protected:
67 //
68 // A context for resource validation operations, to tailor error response.
69 // The base class throws an exception immediately and ignores detail data.
70 //
71 class ValidationContext {
72 public:
d8f41ccd 73 ValidationContext(SecStaticCode &c) : code(c) { }
b1ab9ed8
A
74 virtual ~ValidationContext();
75 virtual void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value);
d8f41ccd
A
76
77 virtual OSStatus osStatus() { return noErr; }
78 virtual void throwMe() { }
79
80 SecStaticCode &code;
b1ab9ed8
A
81 };
82
83 //
84 // A CollectingContext collects all error details and throws an annotated final error.
85 //
86 class CollectingContext : public ValidationContext {
87 public:
d8f41ccd 88 CollectingContext(SecStaticCode &c) : ValidationContext(c), mStatus(errSecSuccess) { }
b1ab9ed8
A
89 void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value);
90
91 OSStatus osStatus() { return mStatus; }
92 operator OSStatus () const { return mStatus; }
93 void throwMe() __attribute__((noreturn));
b1ab9ed8
A
94
95 private:
96 CFRef<CFMutableDictionaryRef> mCollection;
97 OSStatus mStatus;
d87e1158 98 Mutex mLock;
b1ab9ed8 99 };
d87e1158 100
b1ab9ed8
A
101public:
102 SECCFFUNCTIONS(SecStaticCode, SecStaticCodeRef,
103 errSecCSInvalidObjectRef, gCFObjects().StaticCode)
104
105 // implicitly convert SecCodeRefs to their SecStaticCodeRefs
106 static SecStaticCode *requiredStatic(SecStaticCodeRef ref); // convert SecCodeRef
427c49bc 107 static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL if static
b1ab9ed8 108
79b9da22 109 SecStaticCode(DiskRep *rep, uint32_t flags = 0);
b1ab9ed8 110 virtual ~SecStaticCode() throw();
d87e1158
A
111
112 void initializeFromParent(const SecStaticCode& parent);
113
b1ab9ed8
A
114 bool equal(SecCFObject &other);
115 CFHashCode hash();
116
117 void detachedSignature(CFDataRef sig); // attach an explicitly given detached signature
118 void checkForSystemSignature(); // check for and attach system-supplied detached signature
119
90dc47c2
A
120 typedef std::map<CodeDirectory::HashAlgorithm, CFCopyRef<CFDataRef> > CodeDirectoryMap;
121
e3d460c9 122 const CodeDirectory *codeDirectory(bool check = true) const;
90dc47c2 123 const CodeDirectoryMap *codeDirectories(bool check = true) const;
e3d460c9
A
124 CodeDirectory::HashAlgorithm hashAlgorithm() const { return codeDirectory()->hashType; }
125 CodeDirectory::HashAlgorithms hashAlgorithms() const { return mHashAlgorithms; }
b1ab9ed8 126 CFDataRef cdHash();
e3d460c9 127 CFArrayRef cdHashes();
b1ab9ed8
A
128 CFDataRef signature();
129 CFAbsoluteTime signingTime();
130 CFAbsoluteTime signingTimestamp();
131 bool isSigned() { return codeDirectory(false) != NULL; }
e3d460c9 132 DiskRep *diskRep() const { return mRep; }
427c49bc 133 bool isDetached() const { return mRep->base() != mRep; }
b1ab9ed8 134 std::string mainExecutablePath() { return mRep->mainExecutablePath(); }
80e23899 135 CFURLRef copyCanonicalPath() const { return mRep->copyCanonicalPath(); }
b1ab9ed8 136 std::string identifier() { return codeDirectory()->identifier(); }
420ff9d9 137 const char *teamID() { return codeDirectory()->teamID(); }
b1ab9ed8
A
138 std::string format() const { return mRep->format(); }
139 std::string signatureSource();
427c49bc
A
140 virtual CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed);
141 virtual CFDictionaryRef infoDictionary();
fa7225c8 142 CFDictionaryRef diskRepInformation();
427c49bc 143
b1ab9ed8 144 CFDictionaryRef entitlements();
fa7225c8 145 CFDataRef copyComponent(CodeDirectory::SpecialSlot slot, CFDataRef hash);
b1ab9ed8 146
427c49bc 147 CFDictionaryRef resourceDictionary(bool check = true);
b1ab9ed8 148 CFURLRef resourceBase();
80e23899 149 void validateResource(CFDictionaryRef files, std::string path, bool isSymlink, ValidationContext &ctx, SecCSFlags flags, uint32_t version);
5c19dc3a 150 void validateSymlinkResource(std::string fullpath, std::string seal, ValidationContext &ctx, SecCSFlags flags);
e3d460c9 151
b1ab9ed8 152 bool flag(uint32_t tested);
427c49bc
A
153
154 SecCodeCallback monitor() const { return mMonitor; }
155 void setMonitor(SecCodeCallback monitor) { mMonitor = monitor; }
156 CFTypeRef reportEvent(CFStringRef stage, CFDictionaryRef info);
d8f41ccd 157 void reportProgress(unsigned amount = 1);
b1ab9ed8 158
d8f41ccd 159 void setValidationFlags(SecCSFlags flags) { mValidationFlags = flags; }
80e23899
A
160 void setValidationModifiers(CFDictionaryRef modifiers);
161
b1ab9ed8
A
162 void resetValidity(); // clear validation caches (if something may have changed)
163
164 bool validated() const { return mValidated; }
949d2ff0 165 bool revocationChecked() const { return mRevocationChecked; }
b1ab9ed8 166 bool valid() const
427c49bc 167 { assert(validated()); return mValidated && (mValidationResult == errSecSuccess); }
b1ab9ed8
A
168 bool validatedExecutable() const { return mExecutableValidated; }
169 bool validatedResources() const { return mResourcesValidated; }
e3d460c9 170
d8f41ccd
A
171 void prepareProgress(unsigned workload);
172 void cancelValidation();
b1ab9ed8
A
173
174 void validateDirectory();
427c49bc 175 virtual void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed);
b1ab9ed8 176 void validateNonResourceComponents();
e3d460c9 177 void validateTopDirectory();
d8f41ccd 178 unsigned estimateResourceWorkload();
427c49bc 179 void validateResources(SecCSFlags flags);
b1ab9ed8 180 void validateExecutable();
80e23899 181 void validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags, bool isFramework);
b1ab9ed8 182
fa7225c8
A
183 void validatePlainMemoryResource(string path, CFDataRef fileData, SecCSFlags flags);
184
b1ab9ed8
A
185 const Requirements *internalRequirements();
186 const Requirement *internalRequirement(SecRequirementType type);
187 const Requirement *designatedRequirement();
188 const Requirement *defaultDesignatedRequirement(); // newly allocated (caller owns)
189
190 void validateRequirements(SecRequirementType type, SecStaticCode *target,
427c49bc 191 OSStatus nullError = errSecSuccess); // target against my [type], throws
b1ab9ed8
A
192 void validateRequirement(const Requirement *req, OSStatus failure); // me against [req], throws
193 bool satisfiesRequirement(const Requirement *req, OSStatus failure); // me against [req], returns on clean miss
194
195 // certificates are available after signature validation (they are stored in the CMS signature)
196 SecCertificateRef cert(int ix); // get a cert from the cert chain
197 CFArrayRef certificates(); // get the entire certificate chain
198
199 CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary)
427c49bc 200
fa7225c8 201 static bool isAppleDeveloperCert(CFArrayRef certs); // determines if this is an apple developer certificate for library validation
866f8763
A
202#if !TARGET_OS_OSX
203 bool trustedSigningCertChain() { return mTrustedSigningCertChain; }
204#endif
420ff9d9 205
90dc47c2
A
206 void handleOtherArchitectures(void (^handle)(SecStaticCode* other));
207
b1ab9ed8 208public:
427c49bc
A
209 void staticValidate(SecCSFlags flags, const SecRequirement *req);
210 void staticValidateCore(SecCSFlags flags, const SecRequirement *req);
d8f41ccd 211
e3d460c9 212protected:
e3d460c9
A
213 bool loadCodeDirectories(CodeDirectoryMap& cdMap) const;
214
b1ab9ed8 215protected:
427c49bc 216 CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, bool check = true); // component value as a dictionary
b1ab9ed8 217 bool verifySignature();
866f8763
A
218 CFArrayRef createVerificationPolicies();
219 CFArrayRef createTimeStampingAndRevocationPolicies();
fa7225c8
A
220
221 // load preferred rules/files dictionaries (cached therein)
222 bool loadResources(CFDictionaryRef& rules, CFDictionaryRef& files, uint32_t& version);
b1ab9ed8
A
223
224 static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context);
d8f41ccd 225 bool hasWeakResourceRules(CFDictionaryRef rulesDict, uint32_t version, CFArrayRef allowedOmissions);
b1ab9ed8 226
80e23899
A
227private:
228 void validateOtherVersions(CFURLRef path, SecCSFlags flags, SecRequirementRef req, SecStaticCode *code);
866f8763 229 bool checkfix30814861(string path, bool addition);
79b9da22 230 bool checkfix41082220(OSStatus result);
80e23899 231
866f8763
A
232 ResourceBuilder *mCheckfix30814861builder1;
233 dispatch_once_t mCheckfix30814861builder1_once;
234
b1ab9ed8
A
235private:
236 RefPointer<DiskRep> mRep; // on-disk representation
e3d460c9
A
237 mutable CodeDirectoryMap mCodeDirectories; // available CodeDirectory blobs by digest type
238 mutable CFRef<CFDataRef> mBaseDir; // the primary CodeDirectory blob (whether it's chosen or not)
427c49bc 239 CFRef<CFDataRef> mDetachedSig; // currently applied explicit detached signature
b1ab9ed8 240
80e23899
A
241 // private validation modifiers (only used by Gatekeeper checkfixes)
242 MacOSErrorSet mTolerateErrors; // soft error conditions to ignore
243 CFRef<CFArrayRef> mAllowOmissions; // additionally allowed resource omissions
244
b1ab9ed8
A
245 // master validation state
246 bool mValidated; // core validation was attempted
949d2ff0 247 bool mRevocationChecked; // the signature was checked for revocation
b1ab9ed8
A
248 OSStatus mValidationResult; // outcome of core validation
249 bool mValidationExpired; // outcome had expired certificates
250
251 // static executable validation state (nested within mValidated/mValid)
252 bool mExecutableValidated; // tried to validate executable file
253 OSStatus mExecutableValidResult; // outcome if mExecutableValidated
254
255 // static resource validation state (nested within mValidated/mValid)
256 bool mResourcesValidated; // tried to validate resources
427c49bc
A
257 bool mResourcesDeep; // cached validation was deep
258 OSStatus mResourcesValidResult; // outcome if mResourceValidated or...
d8f41ccd
A
259 ValidationContext *mResourcesValidContext; // resource error reporting funnel
260
261 // validation progress state (set when static validation starts)
262 SecCSFlags mValidationFlags; // API flags passed to static validation
263 unsigned mTotalWork; // total expected work (arbitrary units)
264 unsigned mCurrentWork; // currently completed work
265 bool mCancelPending; // cancellation was requested
d87e1158 266 Dispatch::Queue mProgressQueue; // progress reporting queue
b1ab9ed8 267
5c19dc3a
A
268 // nested validation support
269 const SecStaticCode *mOuterScope; // containing code (if this is a nested validation; weak)
270 ResourceBuilder *mResourceScope; // current Resource validation stack (while validating; weak)
271
b1ab9ed8 272 // cached contents
e3d460c9
A
273 mutable CFRef<CFDataRef> mDir; // code directory data
274 mutable CodeDirectory::HashAlgorithms mHashAlgorithms; // available hash algorithms
b1ab9ed8
A
275 CFRef<CFDataRef> mSignature; // CMS signature data
276 CFAbsoluteTime mSigningTime; // (signed) signing time
277 CFAbsoluteTime mSigningTimestamp; // Timestamp time (from timestamping authority)
278 CFRef<CFDataRef> mCache[cdSlotCount]; // NULL => not tried, kCFNull => absent, other => present
279
280 // alternative cache forms (storage may depend on cached contents above)
281 CFRef<CFDictionaryRef> mInfoDict; // derived from mCache slot
282 CFRef<CFDictionaryRef> mEntitlements; // derived from mCache slot
283 CFRef<CFDictionaryRef> mResourceDict; // derived from mCache slot
284 const Requirement *mDesignatedReq; // cached designated req if we made one up
e3d460c9
A
285 CFRef<CFDataRef> mCDHash; // hash of chosen CodeDirectory
286 CFRef<CFArrayRef> mCDHashes; // hashes of all CodeDirectories (in digest type code order)
b1ab9ed8
A
287
288 bool mGotResourceBase; // asked mRep for resourceBasePath
289 CFRef<CFURLRef> mResourceBase; // URL form of resource base directory
427c49bc
A
290
291 SecCodeCallback mMonitor; // registered monitor callback
d87e1158
A
292
293 LimitedAsync *mLimitedAsync; // limited async workers for verification
294
79b9da22
A
295 uint32_t mFlags; // flags from creation
296 bool mNotarizationChecked; // ensure notarization check only performed once
297 bool mStaplingChecked; // ensure stapling check only performed once
298 double mNotarizationDate; // the notarization ticket's date, if online check failed
299
b1ab9ed8
A
300 // signature verification outcome (mTrust == NULL => not done yet)
301 CFRef<SecTrustRef> mTrust; // outcome of crypto validation (valid or not)
302 CFRef<CFArrayRef> mCertChain;
866f8763
A
303#if TARGET_OS_OSX
304 CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails;
305#else
306 bool mTrustedSigningCertChain;
307#endif
308
b1ab9ed8
A
309};
310
311
b1ab9ed8
A
312} // end namespace CodeSigning
313} // end namespace Security
314
315#endif // !_H_STATICCODE