]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/slcrep.cpp
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / slcrep.cpp
1 /*
2 * Copyright (c) 2009,2011-2012 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 // slcrep - DiskRep representing the Mac OS Shared Library Cache
26 //
27 #include "slcrep.h"
28
29
30 namespace Security {
31 namespace CodeSigning {
32
33 using namespace UnixPlusPlus;
34
35
36 //
37 // Object management.
38 // We open the file lazily, so nothing much happens on constructions.
39 // We can construct directly from a file path, or from an architecture
40 // (represented by Context), which will find the file in its usual
41 // location on disk.
42 //
43 DYLDCacheRep::DYLDCacheRep(const char *path)
44 : SingleDiskRep(path), mCache(path)
45 {
46 this->setup();
47 }
48
49 DYLDCacheRep::DYLDCacheRep(const Context *ctx)
50 : SingleDiskRep(DYLDCache::pathFor(((ctx && ctx->arch) ? ctx->arch : Architecture::local()))),
51 mCache(this->path())
52 {
53 this->setup();
54 }
55
56 void DYLDCacheRep::setup()
57 {
58 mSigningData = NULL;
59 if (mCache.totalSize() >= mCache.mapSize() + sizeof(BlobCore)) {
60 const EmbeddedSignatureBlob *blob = mCache.at<const EmbeddedSignatureBlob>((uint32_t)mCache.mapSize());
61 if (mCache.totalSize() >= mCache.mapSize() + blob->length()) // entire blob fits in file
62 mSigningData = blob;
63 }
64 CODESIGN_DISKREP_CREATE_SLC(this, (char*)this->mainExecutablePath().c_str());
65 }
66
67
68 //
69 // Sniffer function for "plausible shared library cache file".
70 //
71 bool DYLDCacheRep::candidate(FileDesc &fd)
72 {
73 return DYLDCache::validate(fd);
74 }
75
76
77 //
78 // Default to system page size for segmented (paged) signatures
79 //
80 size_t DYLDCacheRep::pageSize(const SigningContext &)
81 {
82 return segmentedPageSize;
83 }
84
85
86 //
87 // Signing limit is the start of the (trailing) signature
88 //
89 size_t DYLDCacheRep::signingLimit()
90 {
91 return mCache.mapSize();
92 }
93
94
95 //
96 // Retrieve a component from the executable.
97 // Our mCache has mapped the entire file, so we just fish the contents out of
98 // the mapped area as needed.
99 //
100 CFDataRef DYLDCacheRep::component(CodeDirectory::SpecialSlot slot)
101 {
102 return mSigningData ? mSigningData->component(slot) : NULL;
103 }
104
105
106 //
107 // Provide a (vaguely) human readable characterization of this code
108 //
109 string DYLDCacheRep::format()
110 {
111 if (const char *name = mCache.architecture().name()) {
112 char result[100];
113 snprintf(result, sizeof(result), "OS X Shared Library Cache (%s @ 0x%llx)",
114 name, mCache.baseAddress());
115 return result;
116 } else
117 return "OS X Shared Library Cache (unknown type)";
118 }
119
120
121 //
122 // DYLDCacheRep::Writers
123 //
124 DiskRep::Writer *DYLDCacheRep::writer()
125 {
126 return new Writer(this);
127 }
128
129
130 //
131 // Write a component.
132 //
133 void DYLDCacheRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
134 {
135 EmbeddedSignatureBlob::Maker::component(slot, data);
136 }
137
138
139 //
140 // Append the superblob we built to the cache file.
141 //
142 void DYLDCacheRep::Writer::flush()
143 {
144 delete mSigningData; // ditch previous blob just in case
145 mSigningData = Maker::make(); // assemble new signature SuperBlob
146 fd().seek(rep->mCache.mapSize()); // end of impage proper
147 fd().writeAll(*mSigningData);
148 }
149
150
151 //
152 // The discretionary additions insert a Scatter vector describing the file's mapping table.
153 //
154 void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder &builder)
155 {
156 unsigned count = rep->mCache.mappingCount();
157 builder.scatter(count);
158 for (unsigned n = 0; n < count; n++) {
159 const DYLDCache::Mapping dmap = rep->mCache.mapping(n);
160 CodeDirectory::Scatter *scatter = builder.scatter() + n;
161 scatter->targetOffset = dmap.address();
162 scatter->base = (uint32_t)(dmap.offset() / segmentedPageSize);
163 assert(dmap.offset() % segmentedPageSize == 0);
164 scatter->count = (uint32_t)(dmap.size() / segmentedPageSize);
165 assert(dmap.size() % segmentedPageSize == 0);
166 }
167 }
168
169
170 } // end namespace CodeSigning
171 } // end namespace Security