]> git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/diskrep.h
b7746ae8f5098d8f6164a4a3401e29fac8777774
[apple/libsecurity_codesigning.git] / 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
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 DiskRep();
53 virtual ~DiskRep();
54 virtual DiskRep *base();
55 virtual CFDataRef component(CodeDirectory::SpecialSlot slot) = 0; // fetch component
56 virtual CFDataRef identification() = 0; // binary lookup identifier
57 virtual std::string mainExecutablePath() = 0; // path to main executable
58 virtual CFURLRef canonicalPath() = 0; // path to whole code
59 virtual std::string recommendedIdentifier() = 0; // default identifier
60 virtual std::string resourcesRootPath(); // resource directory if any
61 virtual CFDictionaryRef defaultResourceRules(); // default resource rules
62 virtual void adjustResources(ResourceBuilder &builder); // adjust resource rule set
63 virtual const Requirements *defaultRequirements(const Architecture *arch); // default internal requirements
64 virtual Universal *mainExecutableImage(); // binary if Mach-O/Universal
65 virtual size_t pageSize(); // default main executable page size
66 virtual size_t signingBase(); // start offset of signed area in main executable
67 virtual size_t signingLimit() = 0; // size of signed area in main executable
68 virtual std::string format() = 0; // human-readable type string
69 virtual CFArrayRef modifiedFiles(); // list of files modified by signing
70 virtual UnixPlusPlus::FileDesc &fd() = 0; // a cached fd for main executable file
71 virtual void flush(); // flush caches (refetch as needed)
72
73 bool mainExecutableIsMachO() { return mainExecutableImage() != NULL; }
74
75 // shorthands
76 CFDataRef codeDirectory() { return component(cdCodeDirectorySlot); }
77 CFDataRef signature() { return component(cdSignatureSlot); }
78
79 public:
80 class Writer;
81 virtual Writer *writer();
82
83 public:
84 struct Context {
85 Context() : arch(Architecture::none), offset(0), fileOnly(false) { }
86 Architecture arch; // explicit architecture
87 off_t offset; // explicit file offset
88 bool fileOnly; // only consider single-file representations
89 };
90
91 static DiskRep *bestGuess(const char *path, const Context *ctx = NULL); // canonical heuristic, any path
92 static DiskRep *bestFileGuess(const char *path, const Context *ctx = NULL); // ctx (if any) + fileOnly
93 static DiskRep *bestGuess(const char *path, size_t archOffset); // Mach-O at given file offset only
94
95 static DiskRep *bestGuess(const std::string &path, const Context *ctx = NULL)
96 { return bestGuess(path.c_str(), ctx); }
97 static DiskRep *bestGuess(const std::string &path, size_t archOffset) { return bestGuess(path.c_str(), archOffset); }
98 static DiskRep *bestFileGuess(const std::string &path, const Context *ctx = NULL) { return bestFileGuess(path.c_str(), ctx); }
99
100 public:
101 static const size_t segmentedPageSize = 4096; // default page size for system-paged signatures
102 static const size_t monolithicPageSize = 0; // default page size for non-Mach-O executables
103 };
104
105
106 //
107 // Write-access objects.
108 // At this layer they are quite abstract, carrying just the functionality needed
109 // for the signing machinery to place data wherever it should go. Each DiskRep subclass
110 // that supports writing signing data to a place inside the code needs to implement
111 // a subclass of Writer and return an instance in the DiskRep::writer() method when asked.
112 //
113 class DiskRep::Writer : public RefCount {
114 public:
115 Writer(uint32_t attrs = 0);
116 virtual ~Writer();
117 virtual void component(CodeDirectory::SpecialSlot slot, CFDataRef data) = 0;
118 virtual uint32_t attributes() const;
119 virtual void addDiscretionary(CodeDirectory::Builder &builder);
120 virtual void remove();
121 virtual void flush();
122
123 bool attribute(uint32_t attr) const { return mAttributes & attr; }
124
125 void signature(CFDataRef data) { component(cdSignatureSlot, data); }
126 void codeDirectory(const CodeDirectory *cd)
127 { component(cdCodeDirectorySlot, CFTempData(cd->data(), cd->length())); }
128
129 private:
130 Architecture mArch;
131 uint32_t mAttributes;
132 };
133
134 //
135 // Writer attributes. Defaults should be off-bits.
136 //
137 enum {
138 writerLastResort = 0x0001, // prefers not to store attributes itself
139 writerNoGlobal = 0x0002, // has only per-architecture storage
140 };
141
142
143 //
144 // A prefix DiskRep that filters (only) signature-dependent behavior and passes
145 // all code-dependent behavior off to an underlying (different) DiskRep.
146 // FilterRep subclasses are typically "stacked" on top of their base DiskRep, and
147 // then used in their place.
148 //
149 class FilterRep : public DiskRep {
150 public:
151 FilterRep(DiskRep *orig) : mOriginal(orig) { }
152
153 DiskRep *base() { return mOriginal; }
154
155 // things that look at signature components are filtered
156 CFDataRef component(CodeDirectory::SpecialSlot slot) = 0;
157
158 // the rest of the virtual behavior devolves on the original DiskRep
159 CFDataRef identification() { return mOriginal->identification(); }
160 std::string mainExecutablePath() { return mOriginal->mainExecutablePath(); }
161 CFURLRef canonicalPath() { return mOriginal->canonicalPath(); }
162 std::string recommendedIdentifier() { return mOriginal->recommendedIdentifier(); }
163 std::string resourcesRootPath() { return mOriginal->resourcesRootPath(); }
164 CFDictionaryRef defaultResourceRules() { return mOriginal->defaultResourceRules(); }
165 Universal *mainExecutableImage() { return mOriginal->mainExecutableImage(); }
166 size_t signingBase() { return mOriginal->signingBase(); }
167 size_t signingLimit() { return mOriginal->signingLimit(); }
168 std::string format() { return mOriginal->format(); }
169 UnixPlusPlus::FileDesc &fd() { return mOriginal->fd(); }
170 void flush() { return mOriginal->flush(); }
171
172 private:
173 RefPointer<DiskRep> mOriginal; // underlying representation
174 };
175
176
177 } // end namespace CodeSigning
178 } // end namespace Security
179
180 #endif // !_H_DISKREP