]>
Commit | Line | Data |
---|---|---|
7d31e928 | 1 | /* |
62e4ed3d | 2 | * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. |
7d31e928 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" | |
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 | |
f60086fc A |
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, | |
59 | // retain or copy them as needed. | |
7d31e928 A |
60 | // |
61 | class SecStaticCode : public SecCFObject { | |
62 | NOCOPY(SecStaticCode) | |
63 | ||
64 | protected: | |
d1c1ab47 A |
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 | // | |
7d31e928 A |
69 | class ValidationContext { |
70 | public: | |
71 | virtual ~ValidationContext(); | |
72 | virtual void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value); | |
73 | }; | |
74 | ||
d1c1ab47 A |
75 | // |
76 | // A CollectingContext collects all error details and throws an annotated final error. | |
77 | // | |
7d31e928 A |
78 | class CollectingContext : public ValidationContext { |
79 | public: | |
80 | CollectingContext(SecStaticCode &c) : code(c), mStatus(noErr) { } | |
81 | void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value); | |
82 | ||
935e6928 | 83 | OSStatus osStatus() { return mStatus; } |
7d31e928 A |
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 | |
100 | static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL | |
101 | ||
102 | SecStaticCode(DiskRep *rep); | |
103 | virtual ~SecStaticCode() throw(); | |
104 | ||
d1c1ab47 A |
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 | |
7d31e928 A |
110 | |
111 | const CodeDirectory *codeDirectory(bool check = true); | |
d1c1ab47 | 112 | CFDataRef cdHash(); |
7d31e928 A |
113 | CFDataRef signature(); |
114 | CFAbsoluteTime signingTime(); | |
62e4ed3d | 115 | CFAbsoluteTime signingTimestamp(); |
7d31e928 A |
116 | bool isSigned() { return codeDirectory(false) != NULL; } |
117 | DiskRep *diskRep() { return mRep; } | |
118 | std::string mainExecutablePath() { return mRep->mainExecutablePath(); } | |
119 | CFURLRef canonicalPath() const { return mRep->canonicalPath(); } | |
120 | std::string identifier() { return codeDirectory()->identifier(); } | |
121 | std::string format() const { return mRep->format(); } | |
d1c1ab47 | 122 | std::string signatureSource(); |
f60086fc | 123 | CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); |
7d31e928 | 124 | CFDictionaryRef infoDictionary(); |
516ae477 | 125 | CFDictionaryRef entitlements(); |
7d31e928 A |
126 | |
127 | CFDictionaryRef resourceDictionary(); | |
128 | CFURLRef resourceBase(); | |
129 | CFDataRef resource(std::string path); | |
130 | CFDataRef resource(std::string path, ValidationContext &ctx); | |
f60086fc | 131 | void validateResource(std::string path, ValidationContext &ctx); |
7d31e928 A |
132 | |
133 | bool flag(uint32_t tested); | |
134 | ||
f60086fc | 135 | void resetValidity(); // clear validation caches (if something may have changed) |
7d31e928 A |
136 | |
137 | bool validated() const { return mValidated; } | |
138 | bool valid() const | |
139 | { assert(validated()); return mValidated && (mValidationResult == noErr); } | |
935e6928 A |
140 | bool validatedExecutable() const { return mExecutableValidated; } |
141 | bool validatedResources() const { return mResourcesValidated; } | |
142 | ||
7d31e928 | 143 | void validateDirectory(); |
f60086fc | 144 | void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); |
935e6928 | 145 | void validateNonResourceComponents(); |
7d31e928 A |
146 | void validateResources(); |
147 | void validateExecutable(); | |
148 | ||
149 | const Requirements *internalRequirements(); | |
150 | const Requirement *internalRequirement(SecRequirementType type); | |
151 | const Requirement *designatedRequirement(); | |
d1c1ab47 | 152 | const Requirement *defaultDesignatedRequirement(); // newly allocated (caller owns) |
7d31e928 A |
153 | |
154 | void validateRequirements(SecRequirementType type, SecStaticCode *target, | |
f60086fc A |
155 | OSStatus nullError = noErr); // target against my [type], throws |
156 | void validateRequirement(const Requirement *req, OSStatus failure); // me against [req], throws | |
157 | bool satisfiesRequirement(const Requirement *req, OSStatus failure); // me against [req], returns on clean miss | |
7d31e928 | 158 | |
f60086fc | 159 | // certificates are available after signature validation (they are stored in the CMS signature) |
7d31e928 A |
160 | SecCertificateRef cert(int ix); // get a cert from the cert chain |
161 | CFArrayRef certificates(); // get the entire certificate chain | |
162 | ||
f60086fc A |
163 | CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary) |
164 | ||
165 | public: | |
166 | class AllArchitectures; | |
7d31e928 A |
167 | |
168 | protected: | |
f60086fc | 169 | CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, OSStatus fail); // component value as a dictionary |
7d31e928 | 170 | bool verifySignature(); |
935e6928 | 171 | CFTypeRef verificationPolicy(SecCSFlags flags); |
7d31e928 A |
172 | |
173 | static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context); | |
174 | ||
175 | private: | |
176 | RefPointer<DiskRep> mRep; // on-disk representation | |
177 | ||
178 | // master validation state | |
179 | bool mValidated; // core validation was attempted | |
180 | OSStatus mValidationResult; // outcome of core validation | |
181 | bool mValidationExpired; // outcome had expired certificates | |
182 | ||
183 | // static executable validation state (nested within mValidated/mValid) | |
184 | bool mExecutableValidated; // tried to validate executable file | |
935e6928 A |
185 | OSStatus mExecutableValidResult; // outcome if mExecutableValidated |
186 | ||
187 | // static resource validation state (nested within mValidated/mValid) | |
188 | bool mResourcesValidated; // tried to validate resources | |
189 | OSStatus mResourcesValidResult; // outcome if mResourceValidated or.. | |
190 | CollectingContext *mResourcesValidContext; // other outcome | |
7d31e928 A |
191 | |
192 | // cached contents | |
193 | CFRef<CFDataRef> mDir; // code directory data | |
194 | CFRef<CFDataRef> mSignature; // CMS signature data | |
195 | CFAbsoluteTime mSigningTime; // (signed) signing time | |
62e4ed3d | 196 | CFAbsoluteTime mSigningTimestamp; // Timestamp time (from timestamping authority) |
7d31e928 A |
197 | CFRef<CFDataRef> mCache[cdSlotCount]; // NULL => not tried, kCFNull => absent, other => present |
198 | ||
199 | // alternative cache forms (storage may depend on cached contents above) | |
200 | CFRef<CFDictionaryRef> mInfoDict; // derived from mCache slot | |
516ae477 | 201 | CFRef<CFDictionaryRef> mEntitlements; // derived from mCache slot |
7d31e928 A |
202 | CFRef<CFDictionaryRef> mResourceDict; // derived from mCache slot |
203 | const Requirement *mDesignatedReq; // cached designated req if we made one up | |
d1c1ab47 | 204 | CFRef<CFDataRef> mCDHash; // hash of CodeDirectory |
7d31e928 A |
205 | |
206 | bool mGotResourceBase; // asked mRep for resourceBasePath | |
207 | CFRef<CFURLRef> mResourceBase; // URL form of resource base directory | |
208 | ||
209 | // signature verification outcome (mTrust == NULL => not done yet) | |
210 | CFRef<SecTrustRef> mTrust; // outcome of crypto validation (valid or not) | |
211 | CFRef<CFArrayRef> mCertChain; | |
212 | CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails; | |
7d31e928 A |
213 | }; |
214 | ||
215 | ||
f60086fc A |
216 | // |
217 | // Given a SecStaticCode, create an iterator that produces SecStaticCodes | |
218 | // for all architectures encompassed by this static code reference. | |
219 | // | |
220 | class SecStaticCode::AllArchitectures : public SecPointer<SecStaticCode> { | |
221 | public: | |
222 | AllArchitectures(SecStaticCode *code); | |
223 | ||
224 | SecStaticCode *operator () (); | |
225 | ||
226 | private: | |
227 | SecPointer<SecStaticCode> mBase; | |
228 | enum { fatBinary, firstNonFat, atEnd } mState; | |
229 | Universal::Architectures mArchitectures; | |
230 | Universal::Architectures::const_iterator mCurrent; | |
231 | }; | |
232 | ||
233 | ||
7d31e928 A |
234 | } // end namespace CodeSigning |
235 | } // end namespace Security | |
236 | ||
237 | #endif // !_H_STATICCODE |