]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
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 | ||
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 | |
427c49bc | 58 | // resetValidity() is called, whichever is sooner. If you need to keep them longer, |
b1ab9ed8 A |
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 | 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: | |
427c49bc | 80 | CollectingContext(SecStaticCode &c) : code(c), mStatus(errSecSuccess) { } |
b1ab9ed8 A |
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 | ||
94 | public: | |
95 | SECCFFUNCTIONS(SecStaticCode, SecStaticCodeRef, | |
96 | errSecCSInvalidObjectRef, gCFObjects().StaticCode) | |
97 | ||
98 | // implicitly convert SecCodeRefs to their SecStaticCodeRefs | |
99 | static SecStaticCode *requiredStatic(SecStaticCodeRef ref); // convert SecCodeRef | |
427c49bc | 100 | static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL if static |
b1ab9ed8 A |
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; } | |
427c49bc | 118 | bool isDetached() const { return mRep->base() != mRep; } |
b1ab9ed8 A |
119 | std::string mainExecutablePath() { return mRep->mainExecutablePath(); } |
120 | CFURLRef canonicalPath() const { return mRep->canonicalPath(); } | |
121 | std::string identifier() { return codeDirectory()->identifier(); } | |
420ff9d9 | 122 | const char *teamID() { return codeDirectory()->teamID(); } |
b1ab9ed8 A |
123 | std::string format() const { return mRep->format(); } |
124 | std::string signatureSource(); | |
427c49bc A |
125 | virtual CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); |
126 | virtual CFDictionaryRef infoDictionary(); | |
127 | ||
b1ab9ed8 A |
128 | CFDictionaryRef entitlements(); |
129 | ||
427c49bc | 130 | CFDictionaryRef resourceDictionary(bool check = true); |
b1ab9ed8 A |
131 | CFURLRef resourceBase(); |
132 | CFDataRef resource(std::string path); | |
133 | CFDataRef resource(std::string path, ValidationContext &ctx); | |
427c49bc | 134 | void validateResource(CFDictionaryRef files, std::string path, ValidationContext &ctx, SecCSFlags flags, uint32_t version); |
b1ab9ed8 A |
135 | |
136 | bool flag(uint32_t tested); | |
427c49bc A |
137 | |
138 | SecCodeCallback monitor() const { return mMonitor; } | |
139 | void setMonitor(SecCodeCallback monitor) { mMonitor = monitor; } | |
140 | CFTypeRef reportEvent(CFStringRef stage, CFDictionaryRef info); | |
b1ab9ed8 A |
141 | |
142 | void resetValidity(); // clear validation caches (if something may have changed) | |
143 | ||
144 | bool validated() const { return mValidated; } | |
145 | bool valid() const | |
427c49bc | 146 | { assert(validated()); return mValidated && (mValidationResult == errSecSuccess); } |
b1ab9ed8 A |
147 | bool validatedExecutable() const { return mExecutableValidated; } |
148 | bool validatedResources() const { return mResourcesValidated; } | |
149 | ||
150 | void validateDirectory(); | |
427c49bc | 151 | virtual void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); |
b1ab9ed8 | 152 | void validateNonResourceComponents(); |
427c49bc | 153 | void validateResources(SecCSFlags flags); |
b1ab9ed8 | 154 | void validateExecutable(); |
427c49bc | 155 | void validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags); |
b1ab9ed8 A |
156 | |
157 | const Requirements *internalRequirements(); | |
158 | const Requirement *internalRequirement(SecRequirementType type); | |
159 | const Requirement *designatedRequirement(); | |
160 | const Requirement *defaultDesignatedRequirement(); // newly allocated (caller owns) | |
161 | ||
162 | void validateRequirements(SecRequirementType type, SecStaticCode *target, | |
427c49bc | 163 | OSStatus nullError = errSecSuccess); // target against my [type], throws |
b1ab9ed8 A |
164 | void validateRequirement(const Requirement *req, OSStatus failure); // me against [req], throws |
165 | bool satisfiesRequirement(const Requirement *req, OSStatus failure); // me against [req], returns on clean miss | |
166 | ||
167 | // certificates are available after signature validation (they are stored in the CMS signature) | |
168 | SecCertificateRef cert(int ix); // get a cert from the cert chain | |
169 | CFArrayRef certificates(); // get the entire certificate chain | |
170 | ||
171 | CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary) | |
427c49bc | 172 | |
420ff9d9 A |
173 | static bool isAppleDeveloperCert(CFArrayRef certs); // determines if this is an apple developer certificate for libraray validation |
174 | ||
b1ab9ed8 | 175 | public: |
427c49bc A |
176 | void staticValidate(SecCSFlags flags, const SecRequirement *req); |
177 | void staticValidateCore(SecCSFlags flags, const SecRequirement *req); | |
420ff9d9 | 178 | |
b1ab9ed8 | 179 | protected: |
427c49bc | 180 | CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, bool check = true); // component value as a dictionary |
b1ab9ed8 A |
181 | bool verifySignature(); |
182 | CFTypeRef verificationPolicy(SecCSFlags flags); | |
183 | ||
184 | static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context); | |
185 | ||
427c49bc A |
186 | void handleOtherArchitectures(void (^handle)(SecStaticCode* other)); |
187 | ||
b1ab9ed8 A |
188 | private: |
189 | RefPointer<DiskRep> mRep; // on-disk representation | |
427c49bc | 190 | CFRef<CFDataRef> mDetachedSig; // currently applied explicit detached signature |
b1ab9ed8 A |
191 | |
192 | // master validation state | |
193 | bool mValidated; // core validation was attempted | |
194 | OSStatus mValidationResult; // outcome of core validation | |
195 | bool mValidationExpired; // outcome had expired certificates | |
196 | ||
197 | // static executable validation state (nested within mValidated/mValid) | |
198 | bool mExecutableValidated; // tried to validate executable file | |
199 | OSStatus mExecutableValidResult; // outcome if mExecutableValidated | |
200 | ||
201 | // static resource validation state (nested within mValidated/mValid) | |
202 | bool mResourcesValidated; // tried to validate resources | |
427c49bc A |
203 | bool mResourcesDeep; // cached validation was deep |
204 | OSStatus mResourcesValidResult; // outcome if mResourceValidated or... | |
205 | CollectingContext *mResourcesValidContext; // | |
b1ab9ed8 A |
206 | |
207 | // cached contents | |
208 | CFRef<CFDataRef> mDir; // code directory data | |
209 | CFRef<CFDataRef> mSignature; // CMS signature data | |
210 | CFAbsoluteTime mSigningTime; // (signed) signing time | |
211 | CFAbsoluteTime mSigningTimestamp; // Timestamp time (from timestamping authority) | |
212 | CFRef<CFDataRef> mCache[cdSlotCount]; // NULL => not tried, kCFNull => absent, other => present | |
213 | ||
214 | // alternative cache forms (storage may depend on cached contents above) | |
215 | CFRef<CFDictionaryRef> mInfoDict; // derived from mCache slot | |
216 | CFRef<CFDictionaryRef> mEntitlements; // derived from mCache slot | |
217 | CFRef<CFDictionaryRef> mResourceDict; // derived from mCache slot | |
218 | const Requirement *mDesignatedReq; // cached designated req if we made one up | |
219 | CFRef<CFDataRef> mCDHash; // hash of CodeDirectory | |
220 | ||
221 | bool mGotResourceBase; // asked mRep for resourceBasePath | |
222 | CFRef<CFURLRef> mResourceBase; // URL form of resource base directory | |
427c49bc A |
223 | |
224 | SecCodeCallback mMonitor; // registered monitor callback | |
b1ab9ed8 A |
225 | |
226 | // signature verification outcome (mTrust == NULL => not done yet) | |
227 | CFRef<SecTrustRef> mTrust; // outcome of crypto validation (valid or not) | |
228 | CFRef<CFArrayRef> mCertChain; | |
229 | CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails; | |
230 | }; | |
231 | ||
232 | ||
b1ab9ed8 A |
233 | } // end namespace CodeSigning |
234 | } // end namespace Security | |
235 | ||
236 | #endif // !_H_STATICCODE |