]> git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/signerutils.h
2c0f958c7299348f5b0bca457499a3e65e2e599d
[apple/libsecurity_codesigning.git] / lib / signerutils.h
1 /*
2 * Copyright (c) 2006-2007 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 // signerutils - utilities for signature generation
26 //
27 #ifndef _H_SIGNERUTILS
28 #define _H_SIGNERUTILS
29
30 #include "CodeSigner.h"
31 #include "sigblob.h"
32 #include "cdbuilder.h"
33 #include <security_utilities/utilities.h>
34 #include <security_utilities/blob.h>
35 #include <security_utilities/unix++.h>
36 #include <security_utilities/unixchild.h>
37
38 extern "C" {
39 #include <copyfile.h>
40 }
41
42 namespace Security {
43 namespace CodeSigning {
44
45
46 //
47 // A helper to deal with the magic merger logic of internal requirements
48 //
49 class InternalRequirements : public Requirements::Maker {
50 public:
51 InternalRequirements() : mReqs(NULL) { }
52 ~InternalRequirements() { ::free((void *)mReqs); }
53 void operator () (const Requirements *given, const Requirements *defaulted);
54 operator const Requirements * () const { return mReqs; }
55
56 private:
57 const Requirements *mReqs;
58 };
59
60
61 //
62 // A DiskRep::Writer that assembles data in a SuperBlob (in memory)
63 //
64 class BlobWriter : public DiskRep::Writer, public EmbeddedSignatureBlob::Maker {
65 public:
66 void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
67 };
68
69
70 class DetachedBlobWriter : public BlobWriter {
71 public:
72 DetachedBlobWriter(SecCodeSigner::Signer &s) : signer(s) { }
73
74 SecCodeSigner::Signer &signer;
75
76 void flush();
77 };
78
79
80 //
81 // A multi-architecture editing assistant.
82 // ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture
83 // data structures. It must be subclassed to express a particular way to handle the signing
84 // data.
85 //
86 class ArchEditor : public DiskRep::Writer {
87 public:
88 ArchEditor(Universal &fat, uint32_t attrs = 0);
89 virtual ~ArchEditor();
90
91 public:
92 //
93 // One architecture's signing construction element.
94 // This also implements DispRep::Writer so generic writing code
95 // can work with both Mach-O and other files.
96 //
97 struct Arch : public BlobWriter {
98 Architecture architecture; // our architecture
99 auto_ptr<MachO> source; // Mach-O object to be signed
100 CodeDirectory::Builder cdbuilder; // builder for CodeDirectory
101 InternalRequirements ireqs; // consolidated internal requirements
102 size_t blobSize; // calculated SuperBlob size
103
104 Arch(const Architecture &arch) : architecture(arch) { }
105 };
106
107 //
108 // Our callers access the architectural universe through a map
109 // from Architectures to Arch objects.
110 //
111 typedef std::map<Architecture, Arch *> ArchMap;
112 typedef ArchMap::iterator Iterator;
113 ArchMap::iterator begin() { return architecture.begin(); }
114 ArchMap::iterator end() { return architecture.end(); }
115 unsigned count() const { return architecture.size(); }
116
117 // methods needed for an actual implementation
118 virtual void allocate() = 0; // interpass allocations
119 virtual void reset(Arch &arch) = 0; // pass 2 prep
120 virtual void write(Arch &arch, EmbeddedSignatureBlob *blob) = 0; // takes ownership of blob
121 virtual void commit() = 0; // write/flush result
122
123 protected:
124 ArchMap architecture;
125 };
126
127
128 //
129 // An ArchEditor that collects all architectures into a single SuperBlob,
130 // usually for writing a detached multi-architecture signature.
131 //
132 class BlobEditor : public ArchEditor {
133 public:
134 BlobEditor(Universal &fat, SecCodeSigner::Signer &s) : ArchEditor(fat), signer(s) { }
135 ~BlobEditor() { }
136
137 SecCodeSigner::Signer &signer;
138
139 void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
140 void allocate() { }
141 void reset(Arch &arch) { }
142 void write(Arch &arch, EmbeddedSignatureBlob *blob);
143 void commit();
144
145 private:
146 DetachedSignatureBlob::Maker mMaker;
147 EmbeddedSignatureBlob::Maker mGlobal;
148 };
149
150
151 //
152 // An ArchEditor that writes its signatures into a (fat) binary file.
153 //
154 class MachOEditor : public ArchEditor, private UnixPlusPlus::Child {
155 public:
156 MachOEditor(DiskRep::Writer *w, Universal &code, std::string srcPath);
157 ~MachOEditor();
158
159 const RefPointer<DiskRep::Writer> writer;
160 const std::string sourcePath;
161 const std::string tempPath;
162
163 void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
164 void allocate();
165 void reset(Arch &arch);
166 void write(Arch &arch, EmbeddedSignatureBlob *blob);
167 void commit();
168
169 private:
170 void childAction();
171 void parentAction();
172
173 Universal *mNewCode;
174 UnixPlusPlus::AutoFileDesc mFd;
175 bool mTempMayExist;
176
177 const char *mHelperPath;
178 bool mHelperOverridden;
179 };
180
181
182 //
183 // Encapsulation of the copyfile(3) API.
184 // This is slated to go into utilities once stable.
185 //
186 class Copyfile {
187 public:
188 Copyfile();
189 ~Copyfile() { copyfile_state_free(mState); }
190
191 operator copyfile_state_t () const { return mState; }
192
193 void set(uint32_t flag, const void *value);
194 void get(uint32_t flag, void *value);
195
196 void operator () (const char *src, const char *dst, copyfile_flags_t flags);
197
198 private:
199 void check(int rc);
200
201 private:
202 copyfile_state_t mState;
203 };
204
205
206 //
207 // A reliable uid set/reset bracket
208 //
209 class UidGuard {
210 public:
211 UidGuard() : mPrevious(-1) { }
212 UidGuard(uid_t uid) : mPrevious(-1) { seteuid(uid); }
213 ~UidGuard()
214 {
215 if (active())
216 UnixError::check(::seteuid(mPrevious));
217 }
218
219 bool seteuid(uid_t uid)
220 {
221 if (uid == geteuid())
222 return true; // no change, don't bother the kernel
223 if (!active())
224 mPrevious = ::geteuid();
225 return ::seteuid(uid) == 0;
226 }
227
228 bool active() const { return mPrevious != uid_t(-1); }
229 operator bool () const { return active(); }
230 uid_t saved() const { assert(active()); return mPrevious; }
231
232 private:
233 uid_t mPrevious;
234 };
235
236
237 } // end namespace CodeSigning
238 } // end namespace Security
239
240 #endif // !_H_SIGNERUTILS