]> git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/slcrep.cpp
1ba4c49f3dd69ec704afcf5583186a5d1cf0cf38
[apple/libsecurity_codesigning.git] / lib / slcrep.cpp
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
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>(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()
81 {
82 return segmentedPageSize;
83 }
84
85
86 //
87 // Retrieve a component from the executable.
88 // Our mCache has mapped the entire file, so we just fish the contents out of
89 // the mapped area as needed.
90 //
91 CFDataRef DYLDCacheRep::component(CodeDirectory::SpecialSlot slot)
92 {
93 return mSigningData ? mSigningData->component(slot) : NULL;
94 }
95
96
97 //
98 // Provide a (vaguely) human readable characterization of this code
99 //
100 string DYLDCacheRep::format()
101 {
102 if (const char *name = mCache.architecture().name()) {
103 char result[100];
104 snprintf(result, sizeof(result), "OS X Shared Library Cache (%s @ 0x%llx)",
105 name, mCache.baseAddress());
106 return result;
107 } else
108 return "OS X Shared Library Cache (unknown type)";
109 }
110
111
112 //
113 // DYLDCacheRep::Writers
114 //
115 DiskRep::Writer *DYLDCacheRep::writer()
116 {
117 return new Writer(this);
118 }
119
120
121 //
122 // Write a component.
123 //
124 void DYLDCacheRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data)
125 {
126 EmbeddedSignatureBlob::Maker::component(slot, data);
127 }
128
129
130 //
131 // Append the superblob we built to the cache file.
132 //
133 void DYLDCacheRep::Writer::flush()
134 {
135 delete mSigningData; // ditch previous blob just in case
136 mSigningData = Maker::make(); // assemble new signature SuperBlob
137 fd().seek(rep->mCache.mapSize()); // end of impage proper
138 fd().writeAll(*mSigningData);
139 }
140
141
142 //
143 // The discretionary additions insert a Scatter vector describing the file's mapping table.
144 //
145 void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder &builder)
146 {
147 unsigned count = rep->mCache.mappingCount();
148 builder.scatter(count);
149 for (unsigned n = 0; n < count; n++) {
150 const DYLDCache::Mapping dmap = rep->mCache.mapping(n);
151 CodeDirectory::Scatter *scatter = builder.scatter() + n;
152 scatter->targetOffset = dmap.address();
153 scatter->base = dmap.offset() / segmentedPageSize;
154 assert(dmap.offset() % segmentedPageSize == 0);
155 scatter->count = dmap.size() / segmentedPageSize;
156 assert(dmap.size() % segmentedPageSize == 0);
157 }
158 }
159
160
161 } // end namespace CodeSigning
162 } // end namespace Security