]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/diskrep.h
2 * Copyright (c) 2006-2007,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 // diskrep - disk representations of code
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>
41 namespace CodeSigning
{
43 class ResourceBuilder
;
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.
53 class DiskRep
: public RefCount
{
57 typedef std::set
<OSStatus
> ToleratedErrors
;
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
66 virtual CFURLRef
copyCanonicalPath() = 0; // path to whole code
67 virtual std::string
resourcesRootPath(); // resource directory if any [none]
68 virtual void adjustResources(ResourceBuilder
&builder
); // adjust resource rule set [no change]
69 virtual void prepareForSigning(SigningContext
& context
); // pre-adjust signing defaults before argument preparation [none]
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
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
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)
83 virtual CFDictionaryRef
diskRepInformation(); // information from diskrep
85 virtual void registerStapledTicket();
87 // default values for signing operations
88 virtual std::string
recommendedIdentifier(const SigningContext
&ctx
) = 0; // default identifier
89 virtual CFDictionaryRef
defaultResourceRules(const SigningContext
&ctx
); // default resource rules [none]
90 virtual const Requirements
*defaultRequirements(const Architecture
*arch
,
91 const SigningContext
&ctx
); // default internal requirements [none]
92 virtual size_t pageSize(const SigningContext
&ctx
); // default main executable page size [infinite, i.e. no paging]
94 virtual void strictValidate(const CodeDirectory
* cd
, const ToleratedErrors
& tolerated
, SecCSFlags flags
); // perform strict validation
95 virtual void strictValidateStructure(const CodeDirectory
* cd
, const ToleratedErrors
& tolerated
, SecCSFlags flags
) { }; // perform structural strict validation
96 virtual CFArrayRef
allowedResourceOmissions(); // allowed (default) resource omission rules
98 virtual bool appleInternalForcePlatform() const {return false;};
100 bool mainExecutableIsMachO() { return mainExecutableImage() != NULL
; }
103 CFDataRef
signature() { return component(cdSignatureSlot
); }
107 virtual Writer
*writer(); // Writer factory
110 // optional information that might be used to create a suitable DiskRep. All optional
112 Context() : arch(Architecture::none
), version(NULL
), offset(0), fileOnly(false), inMemory(NULL
), size(0) { }
113 Architecture arch
; // explicit architecture (choose amongst universal variants)
114 const char *version
; // bundle version (string)
115 off_t offset
; // explicit file offset
116 bool fileOnly
; // only consider single-file representations (no bundles etc.)
117 const void *inMemory
; // consider using in-memory copy at this address
118 size_t size
; // size of this mach-o slice
121 static DiskRep
*bestGuess(const char *path
, const Context
*ctx
= NULL
); // canonical heuristic, any path
122 static DiskRep
*bestFileGuess(const char *path
, const Context
*ctx
= NULL
); // ctx (if any) + fileOnly
123 static DiskRep
*bestGuess(const char *path
, size_t archOffset
); // Mach-O at given file offset only
125 // versions using std::string paths (merely a convenience)
126 static DiskRep
*bestGuess(const std::string
&path
, const Context
*ctx
= NULL
)
127 { return bestGuess(path
.c_str(), ctx
); }
128 static DiskRep
*bestGuess(const std::string
&path
, size_t archOffset
) { return bestGuess(path
.c_str(), archOffset
); }
129 static DiskRep
*bestFileGuess(const std::string
&path
, const Context
*ctx
= NULL
) { return bestFileGuess(path
.c_str(), ctx
); }
132 // see DiskRep::Writer docs for why this is here
133 class SigningContext
{
138 virtual std::string
sdkPath(const std::string
&path
) const = 0;
139 virtual bool isAdhoc() const = 0;
140 virtual SecCSFlags
signingFlags() const = 0;
142 virtual const CodeDirectory::HashAlgorithms
&digestAlgorithms() const = 0;
143 virtual void setDigestAlgorithms(CodeDirectory::HashAlgorithms types
) = 0;
145 void setDigestAlgorithm(CodeDirectory::HashAlgorithm type
)
147 CodeDirectory::HashAlgorithms types
;
149 setDigestAlgorithms(types
);
154 // canonically derive a suggested signing identifier from some string
155 static std::string
canonicalIdentifier(const std::string
&name
);
158 static const size_t segmentedPageSize
= 4096; // default page size for system-paged signatures
159 static const size_t monolithicPageSize
= 0; // default page size for non-Mach-O executables
163 * Editable Disk Reps allow editing of their existing code signature.
164 * Specifically, they allow for individual components to be replaced,
165 * while preserving all other components.
166 * Lots of restrictions apply, e.g. machO signatures' superblobs may
167 * not change in size, and components covered by the code directory
168 * cannot be replaced without adjusting the code directory.
169 * Replacing or adding CMS blobs (having reserved enough size in the
170 * superblob beforehand) is the original reason this trait exists.
172 class EditableDiskRep
{
174 typedef std::map
<CodeDirectory::Slot
, CFCopyRef
<CFDataRef
>> RawComponentMap
;
176 /* Return all components in raw form.
177 * Signature editing will add all the components obtained hereby
178 * back to their specific slots, though some of them may have
179 * been replaced in the map.
181 virtual RawComponentMap
createRawComponents() = 0;
185 // Write-access objects.
186 // At this layer they are quite abstract, carrying just the functionality needed
187 // for the signing machinery to place data wherever it should go. Each DiskRep subclass
188 // that supports writing signing data to a place inside the code needs to implement
189 // a subclass of Writer and return an instance in the DiskRep::writer() method when asked.
191 // The Writer class is subclassed interestingly by the Mach-O multi-architecture signing code,
192 // which is handled as a special case. This means that not all Writer subclass objects were made
193 // by DiskRep::writer, and it is unwise to assume so.
195 // Note that the methods that provide defaults for signing operations are in DiskRep rather
196 // than here. That's because writers abstract data *sending*, and are virtual on management
197 // of stored data, while DiskRep is virtual on the existing code object, which is where
198 // we get our defaults from.
200 class DiskRep::Writer
: public RefCount
{
202 Writer(uint32_t attrs
= 0);
204 virtual void component(CodeDirectory::SpecialSlot slot
, CFDataRef data
) = 0;
205 virtual uint32_t attributes() const;
206 virtual void addDiscretionary(CodeDirectory::Builder
&builder
);
207 virtual void remove();
208 virtual void flush();
210 bool attribute(uint32_t attr
) const { return mAttributes
& attr
; }
212 void signature(CFDataRef data
) { component(cdSignatureSlot
, data
); }
213 void codeDirectory(const CodeDirectory
*cd
, CodeDirectory::SpecialSlot slot
)
214 { component(slot
, CFTempData(cd
->data(), cd
->length())); }
217 bool getPreserveAFSC() { return mPreserveAFSC
; }
218 void setPreserveAFSC(bool flag
) { mPreserveAFSC
= flag
; }
223 uint32_t mAttributes
;
225 bool mPreserveAFSC
= false; // preserve AFSC compression
230 // Writer attributes. Defaults should be off-bits.
233 writerLastResort
= 0x0001, // prefers not to store attributes itself
234 writerNoGlobal
= 0x0002, // has only per-architecture storage
239 // A prefix DiskRep that filters (only) signature-dependent behavior and passes
240 // all code-dependent behavior off to an underlying (different) DiskRep.
241 // FilterRep subclasses are typically "stacked" on top of their base DiskRep, and
242 // then used in their place.
244 class FilterRep
: public DiskRep
{
246 FilterRep(DiskRep
*orig
) : mOriginal(orig
) { }
248 DiskRep
*base() { return mOriginal
; }
250 // things that look at signature components are filtered
251 CFDataRef
component(CodeDirectory::SpecialSlot slot
) = 0;
253 // the rest of the virtual behavior devolves on the original DiskRep
254 CFDataRef
identification() { return mOriginal
->identification(); }
255 std::string
mainExecutablePath() { return mOriginal
->mainExecutablePath(); }
256 CFURLRef
copyCanonicalPath() { return mOriginal
->copyCanonicalPath(); }
257 std::string
resourcesRootPath() { return mOriginal
->resourcesRootPath(); }
258 void adjustResources(ResourceBuilder
&builder
) { return mOriginal
->adjustResources(builder
); }
259 Universal
*mainExecutableImage() { return mOriginal
->mainExecutableImage(); }
260 size_t signingBase() { return mOriginal
->signingBase(); }
261 size_t signingLimit() { return mOriginal
->signingLimit(); }
262 size_t execSegBase(const Architecture
*arch
) { return mOriginal
->execSegBase(arch
); }
263 size_t execSegLimit(const Architecture
*arch
) { return mOriginal
->execSegLimit(arch
); }
264 std::string
format() { return mOriginal
->format(); }
265 CFArrayRef
modifiedFiles() { return mOriginal
->modifiedFiles(); }
266 UnixPlusPlus::FileDesc
&fd() { return mOriginal
->fd(); }
267 void flush() { return mOriginal
->flush(); }
269 std::string
recommendedIdentifier(const SigningContext
&ctx
)
270 { return mOriginal
->recommendedIdentifier(ctx
); }
271 CFDictionaryRef
defaultResourceRules(const SigningContext
&ctx
)
272 { return mOriginal
->defaultResourceRules(ctx
); }
273 const Requirements
*defaultRequirements(const Architecture
*arch
, const SigningContext
&ctx
)
274 { return mOriginal
->defaultRequirements(arch
, ctx
); }
275 size_t pageSize(const SigningContext
&ctx
) { return mOriginal
->pageSize(ctx
); }
277 void strictValidate(const CodeDirectory
* cd
, const ToleratedErrors
& tolerated
, SecCSFlags flags
) { mOriginal
->strictValidate(cd
, tolerated
, flags
); }
278 void strictValidateStructure(const CodeDirectory
* cd
, const ToleratedErrors
& tolerated
, SecCSFlags flags
) { mOriginal
->strictValidateStructure(cd
, tolerated
, flags
); }
279 CFArrayRef
allowedResourceOmissions() { return mOriginal
->allowedResourceOmissions(); }
282 RefPointer
<DiskRep
> mOriginal
; // underlying representation
286 } // end namespace CodeSigning
287 } // end namespace Security
289 #endif // !_H_DISKREP