]>
git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/foreigndiskrep.cpp
89ac70fc55395a5c320d7812c5c331f3648e66e1
2 * Copyright (c) 2007 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 // foreigndiskrep - foreign executable disk representation
27 #include "foreigndiskrep.h"
32 namespace CodeSigning
{
34 using namespace UnixPlusPlus
;
38 // Everything's lazy in here
40 ForeignDiskRep::ForeignDiskRep(const char *path
)
41 : SingleDiskRep(path
), mTriedRead(false)
45 ForeignDiskRep::~ForeignDiskRep()
53 // Foreign filter heuristic
55 bool ForeignDiskRep::candidate(FileDesc
&fd
)
57 static const char magicMarker
[] = "MZ\0\0\0\0\0\0\0\0\0\0PE\0\0 \b";
58 static const size_t magicLength
= 18;
59 char marker
[magicLength
];
60 return fd
.read(marker
, magicLength
, 0) == magicLength
61 && !memcmp(marker
, magicMarker
, magicLength
);
66 // Extract and return a component by slot number.
67 // If we have a Mach-O binary, use embedded components.
68 // Otherwise, look for and return the extended attribute, if any.
70 CFDataRef
ForeignDiskRep::component(CodeDirectory::SpecialSlot slot
)
75 return mSigningData
->component(slot
);
82 // Default to system-paged signing
84 size_t ForeignDiskRep::pageSize()
86 return segmentedPageSize
;
91 // Various other aspects of our DiskRep personality.
93 string
ForeignDiskRep::format()
95 return "foreign binary";
100 // Discard cached information
102 void ForeignDiskRep::flush()
105 ::free(mSigningData
);
110 // Locate, read, and cache embedded signing data from the foreign binary.
112 void ForeignDiskRep::readSigningData()
114 if (!mTriedRead
) { // try it once
115 mSigningData
= NULL
; // preset failure
116 mTriedRead
= true; // we've tried (and perhaps failed)
118 AutoFileDesc
fd(cspath(), O_RDONLY
);
119 mSigningData
= EmbeddedSignatureBlob::readBlob(fd
);
121 secdebug("foreignrep", "%zd signing bytes in %d blob(s) from %s(foreign)",
122 mSigningData
->length(), mSigningData
->count(),
123 mainExecutablePath().c_str());
125 secdebug("foreignrep", "failed to read signing bytes from %s(foreign)",
126 mainExecutablePath().c_str());
132 // Generate the path to the (default) sidecar file
133 // This is generated as /path/to/.CS.execfilename.
134 // We're assuming that we're only dealing with absolute paths here.
136 string
ForeignDiskRep::cspath()
138 string p
= this->path();
139 string::size_type slash
= p
.rfind('/');
140 assert(slash
!= string::npos
);
141 return p
.substr(0, slash
+1) + ".CS." + p
.substr(slash
+1); // => /path/to/.CS.executable
146 // ForeignDiskRep::Writers
148 DiskRep::Writer
*ForeignDiskRep::writer()
150 return new Writer(this);
153 ForeignDiskRep::Writer::~Writer()
160 // Write a component.
161 // Note that this isn't concerned with Mach-O writing; this is handled at
162 // a much higher level. If we're called, it's extended attribute time.
164 void ForeignDiskRep::Writer::component(CodeDirectory::SpecialSlot slot
, CFDataRef data
)
166 EmbeddedSignatureBlob::Maker::component(slot
, data
);
171 // Append the superblob we built to the foreign binary.
172 // Note: Aligning the signing blob to a 16-byte boundary is not strictly necessary,
173 // but it's what the Mach-O case does, and it probably improves performance a bit.
175 void ForeignDiskRep::Writer::flush()
177 delete mSigningData
; // ditch previous blob just in case
178 mSigningData
= Maker::make(); // assemble new signature SuperBlob
179 AutoFileDesc
fd(rep
->cspath(), O_WRONLY
| O_CREAT
| O_TRUNC
, 0666);
180 fd
.writeAll(mSigningData
, mSigningData
->length());
184 } // end namespace CodeSigning
185 } // end namespace Security