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