]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_codesigning/lib/StaticCode.h
b9eac887de426f3b2e3256c5de7d06d9cb1fe229
[apple/security.git] / Security / libsecurity_codesigning / lib / StaticCode.h
1 /*
2 * Copyright (c) 2006-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 // 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
38 namespace Security {
39 namespace CodeSigning {
40
41
42 class 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 //
61 class SecStaticCode : public SecCFObject {
62 NOCOPY(SecStaticCode)
63
64 protected:
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 ValidationContext(SecStaticCode &c) : code(c) { }
72 virtual ~ValidationContext();
73 virtual void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value);
74
75 virtual OSStatus osStatus() { return noErr; }
76 virtual void throwMe() { }
77
78 SecStaticCode &code;
79 };
80
81 //
82 // A CollectingContext collects all error details and throws an annotated final error.
83 //
84 class CollectingContext : public ValidationContext {
85 public:
86 CollectingContext(SecStaticCode &c) : ValidationContext(c), mStatus(errSecSuccess) { }
87 void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value);
88
89 OSStatus osStatus() { return mStatus; }
90 operator OSStatus () const { return mStatus; }
91 void throwMe() __attribute__((noreturn));
92
93 private:
94 CFRef<CFMutableDictionaryRef> mCollection;
95 OSStatus mStatus;
96 };
97
98 public:
99 SECCFFUNCTIONS(SecStaticCode, SecStaticCodeRef,
100 errSecCSInvalidObjectRef, gCFObjects().StaticCode)
101
102 // implicitly convert SecCodeRefs to their SecStaticCodeRefs
103 static SecStaticCode *requiredStatic(SecStaticCodeRef ref); // convert SecCodeRef
104 static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL if static
105
106 SecStaticCode(DiskRep *rep);
107 virtual ~SecStaticCode() throw();
108
109 bool equal(SecCFObject &other);
110 CFHashCode hash();
111
112 void detachedSignature(CFDataRef sig); // attach an explicitly given detached signature
113 void checkForSystemSignature(); // check for and attach system-supplied detached signature
114
115 const CodeDirectory *codeDirectory(bool check = true);
116 CFDataRef cdHash();
117 CFDataRef signature();
118 CFAbsoluteTime signingTime();
119 CFAbsoluteTime signingTimestamp();
120 bool isSigned() { return codeDirectory(false) != NULL; }
121 DiskRep *diskRep() { return mRep; }
122 bool isDetached() const { return mRep->base() != mRep; }
123 std::string mainExecutablePath() { return mRep->mainExecutablePath(); }
124 CFURLRef copyCanonicalPath() const { return mRep->copyCanonicalPath(); }
125 std::string identifier() { return codeDirectory()->identifier(); }
126 const char *teamID() { return codeDirectory()->teamID(); }
127 std::string format() const { return mRep->format(); }
128 std::string signatureSource();
129 virtual CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed);
130 virtual CFDictionaryRef infoDictionary();
131
132 CFDictionaryRef entitlements();
133
134 CFDictionaryRef resourceDictionary(bool check = true);
135 CFURLRef resourceBase();
136 CFDataRef resource(std::string path);
137 CFDataRef resource(std::string path, ValidationContext &ctx);
138 void validateResource(CFDictionaryRef files, std::string path, bool isSymlink, ValidationContext &ctx, SecCSFlags flags, uint32_t version);
139
140 bool flag(uint32_t tested);
141
142 SecCodeCallback monitor() const { return mMonitor; }
143 void setMonitor(SecCodeCallback monitor) { mMonitor = monitor; }
144 CFTypeRef reportEvent(CFStringRef stage, CFDictionaryRef info);
145 void reportProgress(unsigned amount = 1);
146
147 void setValidationFlags(SecCSFlags flags) { mValidationFlags = flags; }
148 void setValidationModifiers(CFDictionaryRef modifiers);
149
150 void resetValidity(); // clear validation caches (if something may have changed)
151
152 bool validated() const { return mValidated; }
153 bool revocationChecked() const { return mRevocationChecked; }
154 bool valid() const
155 { assert(validated()); return mValidated && (mValidationResult == errSecSuccess); }
156 bool validatedExecutable() const { return mExecutableValidated; }
157 bool validatedResources() const { return mResourcesValidated; }
158
159 void prepareProgress(unsigned workload);
160 void cancelValidation();
161
162 void validateDirectory();
163 virtual void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed);
164 void validateNonResourceComponents();
165 unsigned estimateResourceWorkload();
166 void validateResources(SecCSFlags flags);
167 void validateExecutable();
168 void validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags, bool isFramework);
169
170 const Requirements *internalRequirements();
171 const Requirement *internalRequirement(SecRequirementType type);
172 const Requirement *designatedRequirement();
173 const Requirement *defaultDesignatedRequirement(); // newly allocated (caller owns)
174
175 void validateRequirements(SecRequirementType type, SecStaticCode *target,
176 OSStatus nullError = errSecSuccess); // target against my [type], throws
177 void validateRequirement(const Requirement *req, OSStatus failure); // me against [req], throws
178 bool satisfiesRequirement(const Requirement *req, OSStatus failure); // me against [req], returns on clean miss
179
180 // certificates are available after signature validation (they are stored in the CMS signature)
181 SecCertificateRef cert(int ix); // get a cert from the cert chain
182 CFArrayRef certificates(); // get the entire certificate chain
183
184 CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary)
185
186 static bool isAppleDeveloperCert(CFArrayRef certs); // determines if this is an apple developer certificate for libraray validation
187
188 public:
189 void staticValidate(SecCSFlags flags, const SecRequirement *req);
190 void staticValidateCore(SecCSFlags flags, const SecRequirement *req);
191
192 protected:
193 CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, bool check = true); // component value as a dictionary
194 bool verifySignature();
195 CFArrayRef verificationPolicies();
196
197 static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context);
198 bool hasWeakResourceRules(CFDictionaryRef rulesDict, uint32_t version, CFArrayRef allowedOmissions);
199
200 void handleOtherArchitectures(void (^handle)(SecStaticCode* other));
201
202 private:
203 void validateOtherVersions(CFURLRef path, SecCSFlags flags, SecRequirementRef req, SecStaticCode *code);
204
205 private:
206 RefPointer<DiskRep> mRep; // on-disk representation
207 CFRef<CFDataRef> mDetachedSig; // currently applied explicit detached signature
208
209 // private validation modifiers (only used by Gatekeeper checkfixes)
210 MacOSErrorSet mTolerateErrors; // soft error conditions to ignore
211 CFRef<CFArrayRef> mAllowOmissions; // additionally allowed resource omissions
212
213 // master validation state
214 bool mValidated; // core validation was attempted
215 bool mRevocationChecked; // the signature was checked for revocation
216 OSStatus mValidationResult; // outcome of core validation
217 bool mValidationExpired; // outcome had expired certificates
218
219 // static executable validation state (nested within mValidated/mValid)
220 bool mExecutableValidated; // tried to validate executable file
221 OSStatus mExecutableValidResult; // outcome if mExecutableValidated
222
223 // static resource validation state (nested within mValidated/mValid)
224 bool mResourcesValidated; // tried to validate resources
225 bool mResourcesDeep; // cached validation was deep
226 OSStatus mResourcesValidResult; // outcome if mResourceValidated or...
227 ValidationContext *mResourcesValidContext; // resource error reporting funnel
228
229 // validation progress state (set when static validation starts)
230 SecCSFlags mValidationFlags; // API flags passed to static validation
231 unsigned mTotalWork; // total expected work (arbitrary units)
232 unsigned mCurrentWork; // currently completed work
233 bool mCancelPending; // cancellation was requested
234 Mutex mCancelLock; // protects mCancelPending
235
236 // cached contents
237 CFRef<CFDataRef> mDir; // code directory data
238 CFRef<CFDataRef> mSignature; // CMS signature data
239 CFAbsoluteTime mSigningTime; // (signed) signing time
240 CFAbsoluteTime mSigningTimestamp; // Timestamp time (from timestamping authority)
241 CFRef<CFDataRef> mCache[cdSlotCount]; // NULL => not tried, kCFNull => absent, other => present
242
243 // alternative cache forms (storage may depend on cached contents above)
244 CFRef<CFDictionaryRef> mInfoDict; // derived from mCache slot
245 CFRef<CFDictionaryRef> mEntitlements; // derived from mCache slot
246 CFRef<CFDictionaryRef> mResourceDict; // derived from mCache slot
247 const Requirement *mDesignatedReq; // cached designated req if we made one up
248 CFRef<CFDataRef> mCDHash; // hash of CodeDirectory
249
250 bool mGotResourceBase; // asked mRep for resourceBasePath
251 CFRef<CFURLRef> mResourceBase; // URL form of resource base directory
252
253 SecCodeCallback mMonitor; // registered monitor callback
254
255 // signature verification outcome (mTrust == NULL => not done yet)
256 CFRef<SecTrustRef> mTrust; // outcome of crypto validation (valid or not)
257 CFRef<CFArrayRef> mCertChain;
258 CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails;
259 };
260
261
262 } // end namespace CodeSigning
263 } // end namespace Security
264
265 #endif // !_H_STATICCODE