]> git.saurik.com Git - apple/security.git/blob - libsecurity_codesigning/lib/diskrep.h
Security-55471.14.4.tar.gz
[apple/security.git] / libsecurity_codesigning / lib / diskrep.h
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 class ResourceBuilder;
44
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;
121 virtual SecCSFlags signingFlags() const = 0;
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