]> git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/signerutils.h
827c11ed2fb3509ba247b39d98a9b9cc38b2f8ff
[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 Universal *mNewCode;
172 UnixPlusPlus::AutoFileDesc mFd;
173 bool mTempMayExist;
174 };
175
176
177 //
178 // Encapsulation of the copyfile(3) API.
179 // This is slated to go into utilities once stable.
180 //
181 class Copyfile {
182 public:
183 Copyfile();
184 ~Copyfile() { copyfile_state_free(mState); }
185
186 operator copyfile_state_t () const { return mState; }
187
188 void set(uint32_t flag, const void *value);
189 void get(uint32_t flag, void *value);
190
191 void operator () (const char *src, const char *dst, copyfile_flags_t flags);
192
193 private:
194 void check(int rc);
195
196 private:
197 copyfile_state_t mState;
198 };
199
200
201 //
202 // A reliable uid set/reset bracket
203 //
204 class UidGuard {
205 public:
206 UidGuard() : mPrevious(-1) { }
207 UidGuard(uid_t uid) : mPrevious(-1) { seteuid(uid); }
208 ~UidGuard()
209 {
210 if (active())
211 UnixError::check(::seteuid(mPrevious));
212 }
213
214 bool seteuid(uid_t uid)
215 {
216 if (uid == geteuid())
217 return true; // no change, don't bother the kernel
218 if (!active())
219 mPrevious = ::geteuid();
220 return ::seteuid(uid) == 0;
221 }
222
223 bool active() const { return mPrevious != uid_t(-1); }
224 operator bool () const { return active(); }
225 uid_t saved() const { assert(active()); return mPrevious; }
226
227 private:
228 uid_t mPrevious;
229 };
230
231
232 } // end namespace CodeSigning
233 } // end namespace Security
234
235 #endif // !_H_SIGNERUTILS