]> git.saurik.com Git - apple/security.git/blame - libsecurity_codesigning/lib/slcrep.cpp
Security-55471.14.18.tar.gz
[apple/security.git] / libsecurity_codesigning / lib / slcrep.cpp
CommitLineData
b1ab9ed8
A
1/*
2 * Copyright (c) 2009 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
30namespace Security {
31namespace CodeSigning {
32
33using 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//
43DYLDCacheRep::DYLDCacheRep(const char *path)
44 : SingleDiskRep(path), mCache(path)
45{
46 this->setup();
47}
48
49DYLDCacheRep::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
56void DYLDCacheRep::setup()
57{
58 mSigningData = NULL;
59 if (mCache.totalSize() >= mCache.mapSize() + sizeof(BlobCore)) {
427c49bc 60 const EmbeddedSignatureBlob *blob = mCache.at<const EmbeddedSignatureBlob>((uint32_t)mCache.mapSize());
b1ab9ed8
A
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//
71bool 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//
80size_t DYLDCacheRep::pageSize(const SigningContext &)
81{
82 return segmentedPageSize;
83}
84
85
c2a06e24
A
86//
87// Signing limit is the start of the (trailing) signature
88//
89size_t DYLDCacheRep::signingLimit()
90{
91 return mCache.mapSize();
92}
93
94
b1ab9ed8
A
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//
100CFDataRef 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//
109string 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//
124DiskRep::Writer *DYLDCacheRep::writer()
125{
126 return new Writer(this);
127}
128
129
130//
131// Write a component.
132//
133void 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//
142void 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//
154void 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();
427c49bc 162 scatter->base = (uint32_t)(dmap.offset() / segmentedPageSize);
b1ab9ed8 163 assert(dmap.offset() % segmentedPageSize == 0);
427c49bc 164 scatter->count = (uint32_t)(dmap.size() / segmentedPageSize);
b1ab9ed8
A
165 assert(dmap.size() % segmentedPageSize == 0);
166 }
167}
168
169
170} // end namespace CodeSigning
171} // end namespace Security