]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2006-2007,2011-2012,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 | // diskrep - disk representations of code | |
26 | // | |
27 | #ifndef _H_DISKREP | |
28 | #define _H_DISKREP | |
29 | ||
30 | #include "cs.h" | |
31 | #include "codedirectory.h" | |
32 | #include "cdbuilder.h" | |
33 | #include "requirement.h" | |
34 | #include "resources.h" | |
35 | #include <security_utilities/macho++.h> // for class Architecture | |
36 | #include <security_utilities/refcount.h> | |
37 | #include <security_utilities/superblob.h> | |
38 | #include <CoreFoundation/CFData.h> | |
39 | ||
40 | namespace Security { | |
41 | namespace CodeSigning { | |
42 | ||
427c49bc | 43 | class ResourceBuilder; |
e3d460c9 | 44 | class SecCodeSigner; |
427c49bc | 45 | |
b1ab9ed8 A |
46 | |
47 | // | |
48 | // DiskRep is an abstract interface to code somewhere located by | |
49 | // a file system path. It presents the ability to read and write | |
50 | // Code Signing-related information about such code without exposing | |
51 | // the details of the storage locations or formats. | |
52 | // | |
53 | class DiskRep : public RefCount { | |
54 | public: | |
55 | class SigningContext; | |
56 | ||
80e23899 A |
57 | typedef std::set<OSStatus> ToleratedErrors; |
58 | ||
b1ab9ed8 A |
59 | public: |
60 | DiskRep(); | |
61 | virtual ~DiskRep(); | |
62 | virtual DiskRep *base(); | |
63 | virtual CFDataRef component(CodeDirectory::SpecialSlot slot) = 0; // fetch component | |
64 | virtual CFDataRef identification() = 0; // binary lookup identifier | |
65 | virtual std::string mainExecutablePath() = 0; // path to main executable | |
80e23899 | 66 | virtual CFURLRef copyCanonicalPath() = 0; // path to whole code |
b1ab9ed8 A |
67 | virtual std::string resourcesRootPath(); // resource directory if any [none] |
68 | virtual void adjustResources(ResourceBuilder &builder); // adjust resource rule set [no change] | |
e3d460c9 | 69 | virtual void prepareForSigning(SigningContext& context); // pre-adjust signing defaults before argument preparation [none] |
b1ab9ed8 A |
70 | virtual Universal *mainExecutableImage(); // Mach-O image if Mach-O based [null] |
71 | virtual size_t signingBase(); // start offset of signed area in main executable [zero] | |
72 | virtual size_t signingLimit() = 0; // size of signed area in main executable | |
866f8763 A |
73 | |
74 | // The executable segment, if present, denotes which part of the image can be mapped | |
75 | // into a virtual address space as executable. Not all platforms check this. | |
76 | virtual size_t execSegBase(const Architecture *arch); // start offset of executable segment in main executable [zero] | |
77 | virtual size_t execSegLimit(const Architecture *arch) = 0; // size of executable segment in main executable | |
78 | ||
b1ab9ed8 A |
79 | virtual std::string format() = 0; // human-readable type string |
80 | virtual CFArrayRef modifiedFiles(); // list of files modified by signing [main execcutable only] | |
81 | virtual UnixPlusPlus::FileDesc &fd() = 0; // a cached file descriptor for main executable file | |
82 | virtual void flush(); // flush caches (refetch as needed) | |
fa7225c8 | 83 | virtual CFDictionaryRef diskRepInformation(); // information from diskrep |
b1ab9ed8 A |
84 | |
85 | // default values for signing operations | |
86 | virtual std::string recommendedIdentifier(const SigningContext &ctx) = 0; // default identifier | |
87 | virtual CFDictionaryRef defaultResourceRules(const SigningContext &ctx); // default resource rules [none] | |
88 | virtual const Requirements *defaultRequirements(const Architecture *arch, | |
89 | const SigningContext &ctx); // default internal requirements [none] | |
90 | virtual size_t pageSize(const SigningContext &ctx); // default main executable page size [infinite, i.e. no paging] | |
80e23899 | 91 | |
e3d460c9 | 92 | virtual void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); // perform strict validation |
80e23899 A |
93 | virtual CFArrayRef allowedResourceOmissions(); // allowed (default) resource omission rules |
94 | ||
b1ab9ed8 | 95 | bool mainExecutableIsMachO() { return mainExecutableImage() != NULL; } |
d8f41ccd | 96 | |
b1ab9ed8 | 97 | // shorthands |
b1ab9ed8 A |
98 | CFDataRef signature() { return component(cdSignatureSlot); } |
99 | ||
100 | public: | |
101 | class Writer; | |
102 | virtual Writer *writer(); // Writer factory | |
103 | ||
104 | public: | |
105 | // optional information that might be used to create a suitable DiskRep. All optional | |
106 | struct Context { | |
80e23899 | 107 | Context() : arch(Architecture::none), version(NULL), offset(0), fileOnly(false), inMemory(NULL), size(0) { } |
b1ab9ed8 A |
108 | Architecture arch; // explicit architecture (choose amongst universal variants) |
109 | const char *version; // bundle version (string) | |
110 | off_t offset; // explicit file offset | |
111 | bool fileOnly; // only consider single-file representations (no bundles etc.) | |
112 | const void *inMemory; // consider using in-memory copy at this address | |
80e23899 | 113 | size_t size; // size of this mach-o slice |
b1ab9ed8 A |
114 | }; |
115 | ||
116 | static DiskRep *bestGuess(const char *path, const Context *ctx = NULL); // canonical heuristic, any path | |
117 | static DiskRep *bestFileGuess(const char *path, const Context *ctx = NULL); // ctx (if any) + fileOnly | |
118 | static DiskRep *bestGuess(const char *path, size_t archOffset); // Mach-O at given file offset only | |
119 | ||
120 | // versions using std::string paths (merely a convenience) | |
121 | static DiskRep *bestGuess(const std::string &path, const Context *ctx = NULL) | |
122 | { return bestGuess(path.c_str(), ctx); } | |
123 | static DiskRep *bestGuess(const std::string &path, size_t archOffset) { return bestGuess(path.c_str(), archOffset); } | |
124 | static DiskRep *bestFileGuess(const std::string &path, const Context *ctx = NULL) { return bestFileGuess(path.c_str(), ctx); } | |
125 | ||
126 | public: | |
127 | // see DiskRep::Writer docs for why this is here | |
128 | class SigningContext { | |
129 | protected: | |
130 | SigningContext() { } | |
131 | ||
132 | public: | |
133 | virtual std::string sdkPath(const std::string &path) const = 0; | |
134 | virtual bool isAdhoc() const = 0; | |
427c49bc | 135 | virtual SecCSFlags signingFlags() const = 0; |
e3d460c9 A |
136 | |
137 | virtual const CodeDirectory::HashAlgorithms &digestAlgorithms() const = 0; | |
138 | virtual void setDigestAlgorithms(CodeDirectory::HashAlgorithms types) = 0; | |
139 | ||
140 | void setDigestAlgorithm(CodeDirectory::HashAlgorithm type) | |
141 | { | |
142 | CodeDirectory::HashAlgorithms types; | |
143 | types.insert(type); | |
144 | setDigestAlgorithms(types); | |
145 | } | |
b1ab9ed8 A |
146 | }; |
147 | ||
148 | protected: | |
149 | // canonically derive a suggested signing identifier from some string | |
150 | static std::string canonicalIdentifier(const std::string &name); | |
151 | ||
152 | public: | |
153 | static const size_t segmentedPageSize = 4096; // default page size for system-paged signatures | |
154 | static const size_t monolithicPageSize = 0; // default page size for non-Mach-O executables | |
155 | }; | |
156 | ||
157 | ||
158 | // | |
159 | // Write-access objects. | |
160 | // At this layer they are quite abstract, carrying just the functionality needed | |
161 | // for the signing machinery to place data wherever it should go. Each DiskRep subclass | |
162 | // that supports writing signing data to a place inside the code needs to implement | |
163 | // a subclass of Writer and return an instance in the DiskRep::writer() method when asked. | |
164 | // | |
165 | // The Writer class is subclassed interestingly by the Mach-O multi-architecture signing code, | |
166 | // which is handled as a special case. This means that not all Writer subclass objects were made | |
167 | // by DiskRep::writer, and it is unwise to assume so. | |
168 | // | |
169 | // Note that the methods that provide defaults for signing operations are in DiskRep rather | |
170 | // than here. That's because writers abstract data *sending*, and are virtual on management | |
171 | // of stored data, while DiskRep is virtual on the existing code object, which is where | |
172 | // we get our defaults from. | |
173 | // | |
174 | class DiskRep::Writer : public RefCount { | |
175 | public: | |
176 | Writer(uint32_t attrs = 0); | |
177 | virtual ~Writer(); | |
178 | virtual void component(CodeDirectory::SpecialSlot slot, CFDataRef data) = 0; | |
179 | virtual uint32_t attributes() const; | |
180 | virtual void addDiscretionary(CodeDirectory::Builder &builder); | |
181 | virtual void remove(); | |
182 | virtual void flush(); | |
183 | ||
184 | bool attribute(uint32_t attr) const { return mAttributes & attr; } | |
185 | ||
186 | void signature(CFDataRef data) { component(cdSignatureSlot, data); } | |
e3d460c9 A |
187 | void codeDirectory(const CodeDirectory *cd, CodeDirectory::SpecialSlot slot) |
188 | { component(slot, CFTempData(cd->data(), cd->length())); } | |
b1ab9ed8 A |
189 | |
190 | private: | |
191 | Architecture mArch; | |
192 | uint32_t mAttributes; | |
193 | }; | |
194 | ||
195 | // | |
196 | // Writer attributes. Defaults should be off-bits. | |
197 | // | |
198 | enum { | |
199 | writerLastResort = 0x0001, // prefers not to store attributes itself | |
200 | writerNoGlobal = 0x0002, // has only per-architecture storage | |
201 | }; | |
202 | ||
203 | ||
204 | // | |
205 | // A prefix DiskRep that filters (only) signature-dependent behavior and passes | |
206 | // all code-dependent behavior off to an underlying (different) DiskRep. | |
207 | // FilterRep subclasses are typically "stacked" on top of their base DiskRep, and | |
208 | // then used in their place. | |
209 | // | |
210 | class FilterRep : public DiskRep { | |
211 | public: | |
212 | FilterRep(DiskRep *orig) : mOriginal(orig) { } | |
213 | ||
214 | DiskRep *base() { return mOriginal; } | |
215 | ||
216 | // things that look at signature components are filtered | |
217 | CFDataRef component(CodeDirectory::SpecialSlot slot) = 0; | |
218 | ||
219 | // the rest of the virtual behavior devolves on the original DiskRep | |
220 | CFDataRef identification() { return mOriginal->identification(); } | |
221 | std::string mainExecutablePath() { return mOriginal->mainExecutablePath(); } | |
80e23899 | 222 | CFURLRef copyCanonicalPath() { return mOriginal->copyCanonicalPath(); } |
b1ab9ed8 A |
223 | std::string resourcesRootPath() { return mOriginal->resourcesRootPath(); } |
224 | void adjustResources(ResourceBuilder &builder) { return mOriginal->adjustResources(builder); } | |
225 | Universal *mainExecutableImage() { return mOriginal->mainExecutableImage(); } | |
226 | size_t signingBase() { return mOriginal->signingBase(); } | |
227 | size_t signingLimit() { return mOriginal->signingLimit(); } | |
866f8763 A |
228 | size_t execSegBase(const Architecture *arch) { return mOriginal->execSegBase(arch); } |
229 | size_t execSegLimit(const Architecture *arch) { return mOriginal->execSegLimit(arch); } | |
b1ab9ed8 A |
230 | std::string format() { return mOriginal->format(); } |
231 | CFArrayRef modifiedFiles() { return mOriginal->modifiedFiles(); } | |
232 | UnixPlusPlus::FileDesc &fd() { return mOriginal->fd(); } | |
233 | void flush() { return mOriginal->flush(); } | |
234 | ||
235 | std::string recommendedIdentifier(const SigningContext &ctx) | |
236 | { return mOriginal->recommendedIdentifier(ctx); } | |
237 | CFDictionaryRef defaultResourceRules(const SigningContext &ctx) | |
238 | { return mOriginal->defaultResourceRules(ctx); } | |
d8f41ccd A |
239 | const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx) |
240 | { return mOriginal->defaultRequirements(arch, ctx); } | |
241 | size_t pageSize(const SigningContext &ctx) { return mOriginal->pageSize(ctx); } | |
242 | ||
e3d460c9 | 243 | void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { mOriginal->strictValidate(cd, tolerated, flags); } |
d8f41ccd | 244 | CFArrayRef allowedResourceOmissions() { return mOriginal->allowedResourceOmissions(); } |
b1ab9ed8 A |
245 | |
246 | private: | |
247 | RefPointer<DiskRep> mOriginal; // underlying representation | |
248 | }; | |
249 | ||
250 | ||
251 | } // end namespace CodeSigning | |
252 | } // end namespace Security | |
253 | ||
254 | #endif // !_H_DISKREP |