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