]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/piddiskrep.cpp
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / piddiskrep.cpp
1 /*
2 * Copyright (c) 2012-2014 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 #include "piddiskrep.h"
24 #include "sigblob.h"
25 #include <sys/param.h>
26 #include <sys/utsname.h>
27 #include <System/sys/codesign.h>
28 #include <libproc.h>
29 #include <xpc/xpc.h>
30
31 namespace Security {
32 namespace CodeSigning {
33
34 using namespace UnixPlusPlus;
35
36
37 void
38 PidDiskRep::setCredentials(const Security::CodeSigning::CodeDirectory *cd)
39 {
40 // save the Info.plist slot
41 if (cd->slotIsPresent(cdInfoSlot)) {
42 mInfoPlistHash.take(makeCFData(cd->getSlot(cdInfoSlot, false), cd->hashSize));
43 }
44 }
45
46 void
47 PidDiskRep::fetchData(void)
48 {
49 if (mDataFetched) // once
50 return;
51
52 xpc_connection_t conn = xpc_connection_create("com.apple.CodeSigningHelper",
53 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
54 xpc_connection_set_event_handler(conn, ^(xpc_object_t object){ });
55 xpc_connection_resume(conn);
56
57 xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
58 assert(request != NULL);
59 xpc_dictionary_set_string(request, "command", "fetchData");
60 xpc_dictionary_set_int64(request, "pid", mPid);
61
62 if (mAudit) {
63 xpc_dictionary_set_data(request, "audit", mAudit.get(), sizeof(audit_token_t));
64 }
65 xpc_dictionary_set_data(request, "infohash", CFDataGetBytePtr(mInfoPlistHash), CFDataGetLength(mInfoPlistHash));
66
67 xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, request);
68 if (reply && xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
69 const void *data;
70 size_t size;
71
72 if (!mInfoPlist) {
73 data = xpc_dictionary_get_data(reply, "infoPlist", &size);
74 if (data && size > 0 && size < 50 * 1024)
75 mInfoPlist.take(CFDataCreate(NULL, (const UInt8 *)data, (CFIndex)size));
76 }
77 if (!mBundleURL) {
78 data = xpc_dictionary_get_data(reply, "bundleURL", &size);
79 if (data && size > 0 && size < 50 * 1024)
80 mBundleURL.take(CFURLCreateWithBytes(NULL, (const UInt8 *)data, (CFIndex)size, kCFStringEncodingUTF8, NULL));
81 }
82 }
83 if (reply)
84 xpc_release(reply);
85
86 xpc_release(request);
87 xpc_release(conn);
88
89 if (!mBundleURL) {
90 MacOSError::throwMe(errSecCSNoSuchCode);
91 }
92
93 mDataFetched = true;
94 }
95
96
97 PidDiskRep::PidDiskRep(pid_t pid, audit_token_t *audit, CFDataRef infoPlist)
98 : mDataFetched(false)
99 {
100 BlobCore header;
101
102 mPid = pid;
103 mInfoPlist = infoPlist;
104
105 if (audit != NULL) {
106 mAudit.reset(new audit_token_t);
107 memcpy(mAudit.get(), audit, sizeof(audit_token_t));
108 }
109
110 // fetchData();
111
112 int rcent = EINVAL;
113
114 if (audit != NULL) {
115 rcent = ::csops_audittoken(pid, CS_OPS_BLOB, &header, sizeof(header), mAudit.get());
116 } else {
117 rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header));
118 }
119 if (rcent == 0)
120 MacOSError::throwMe(errSecCSNoSuchCode);
121
122 if (errno != ERANGE)
123 UnixError::throwMe(errno);
124
125 if (header.length() > 1024 * 1024)
126 MacOSError::throwMe(errSecCSNoSuchCode);
127
128 uint32_t bufferLen = (uint32_t)header.length();
129 mBuffer = new uint8_t [bufferLen];
130
131 if (audit != NULL) {
132 UnixError::check(::csops_audittoken(pid, CS_OPS_BLOB, mBuffer, bufferLen, mAudit.get()));
133 } else {
134 UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen));
135 }
136
137 const EmbeddedSignatureBlob *b = (const EmbeddedSignatureBlob *)mBuffer;
138 if (!b->validateBlob(bufferLen))
139 MacOSError::throwMe(errSecCSSignatureInvalid);
140 }
141
142 PidDiskRep::~PidDiskRep()
143 {
144 if (mBuffer)
145 delete [] mBuffer;
146 }
147
148
149 bool PidDiskRep::supportInfoPlist()
150 {
151 fetchData();
152 return mInfoPlist;
153 }
154
155
156 CFDataRef PidDiskRep::component(CodeDirectory::SpecialSlot slot)
157 {
158 if (slot == cdInfoSlot) {
159 fetchData();
160 return mInfoPlist.retain();
161 }
162
163 EmbeddedSignatureBlob *b = (EmbeddedSignatureBlob *)this->blob();
164 return b->component(slot);
165 }
166
167 CFDataRef PidDiskRep::identification()
168 {
169 return NULL;
170 }
171
172
173 CFURLRef PidDiskRep::copyCanonicalPath()
174 {
175 fetchData();
176 return mBundleURL.retain();
177 }
178
179 string PidDiskRep::recommendedIdentifier(const SigningContext &)
180 {
181 return string("pid") + to_string(mPid);
182 }
183
184 size_t PidDiskRep::signingLimit()
185 {
186 return 0;
187 }
188
189 size_t PidDiskRep::execSegLimit(const Architecture *)
190 {
191 return 0;
192 }
193
194 string PidDiskRep::format()
195 {
196 return "pid diskrep";
197 }
198
199 UnixPlusPlus::FileDesc &PidDiskRep::fd()
200 {
201 UnixError::throwMe(EINVAL);
202 }
203
204 string PidDiskRep::mainExecutablePath()
205 {
206 char path[MAXPATHLEN * 2];
207 // This is unsafe by pid only, but so is using that path in general.
208 if(::proc_pidpath(mPid, path, sizeof(path)) == 0)
209 UnixError::throwMe(errno);
210
211 return path;
212 }
213
214 bool PidDiskRep::appleInternalForcePlatform() const
215 {
216 uint32_t flags = 0;
217 int rcent = EINVAL;
218
219 if (mAudit != NULL) {
220 rcent = ::csops_audittoken(mPid, CS_OPS_STATUS, &flags, sizeof(flags),
221 mAudit.get());
222 } else {
223 rcent = ::csops(mPid, CS_OPS_STATUS, &flags, sizeof(flags));
224 }
225
226 if (rcent != 0) {
227 MacOSError::throwMe(errSecCSNoSuchCode);
228 }
229
230 return (flags & CS_PLATFORM_BINARY) == CS_PLATFORM_BINARY;
231 }
232
233 } // end namespace CodeSigning
234 } // end namespace Security