]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/piddiskrep.cpp
Security-58286.260.20.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 mDataFetched = true;
93 }
94
95
96 PidDiskRep::PidDiskRep(pid_t pid, audit_token_t *audit, CFDataRef infoPlist)
97 : mDataFetched(false)
98 {
99 BlobCore header;
100
101 mPid = pid;
102 mInfoPlist = infoPlist;
103
104 if (audit != NULL) {
105 mAudit.reset(new audit_token_t);
106 memcpy(mAudit.get(), audit, sizeof(audit_token_t));
107 }
108
109 // fetchData();
110
111 int rcent = EINVAL;
112
113 if (audit != NULL) {
114 rcent = ::csops_audittoken(pid, CS_OPS_BLOB, &header, sizeof(header), mAudit.get());
115 } else {
116 rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header));
117 }
118 if (rcent == 0)
119 MacOSError::throwMe(errSecCSNoSuchCode);
120
121 if (errno != ERANGE)
122 UnixError::throwMe(errno);
123
124 if (header.length() > 1024 * 1024)
125 MacOSError::throwMe(errSecCSNoSuchCode);
126
127 uint32_t bufferLen = (uint32_t)header.length();
128 mBuffer = new uint8_t [bufferLen];
129
130 if (audit != NULL) {
131 UnixError::check(::csops_audittoken(pid, CS_OPS_BLOB, mBuffer, bufferLen, mAudit.get()));
132 } else {
133 UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen));
134 }
135
136 const EmbeddedSignatureBlob *b = (const EmbeddedSignatureBlob *)mBuffer;
137 if (!b->validateBlob(bufferLen))
138 MacOSError::throwMe(errSecCSSignatureInvalid);
139 }
140
141 PidDiskRep::~PidDiskRep()
142 {
143 if (mBuffer)
144 delete [] mBuffer;
145 }
146
147
148 bool PidDiskRep::supportInfoPlist()
149 {
150 fetchData();
151 return mInfoPlist;
152 }
153
154
155 CFDataRef PidDiskRep::component(CodeDirectory::SpecialSlot slot)
156 {
157 if (slot == cdInfoSlot) {
158 fetchData();
159 return mInfoPlist.retain();
160 }
161
162 EmbeddedSignatureBlob *b = (EmbeddedSignatureBlob *)this->blob();
163 return b->component(slot);
164 }
165
166 CFDataRef PidDiskRep::identification()
167 {
168 return NULL;
169 }
170
171
172 CFURLRef PidDiskRep::copyCanonicalPath()
173 {
174 fetchData();
175 return mBundleURL.retain();
176 }
177
178 string PidDiskRep::recommendedIdentifier(const SigningContext &)
179 {
180 return string("pid") + to_string(mPid);
181 }
182
183 size_t PidDiskRep::signingLimit()
184 {
185 return 0;
186 }
187
188 size_t PidDiskRep::execSegLimit(const Architecture *)
189 {
190 return 0;
191 }
192
193 string PidDiskRep::format()
194 {
195 return "pid diskrep";
196 }
197
198 UnixPlusPlus::FileDesc &PidDiskRep::fd()
199 {
200 UnixError::throwMe(EINVAL);
201 }
202
203 string PidDiskRep::mainExecutablePath()
204 {
205 char path[MAXPATHLEN * 2];
206 // This is unsafe by pid only, but so is using that path in general.
207 if(::proc_pidpath(mPid, path, sizeof(path)) == 0)
208 UnixError::throwMe(errno);
209
210 return path;
211 }
212
213 bool PidDiskRep::appleInternalForcePlatform() const
214 {
215 uint32_t flags = 0;
216 int rcent = EINVAL;
217
218 if (mAudit != NULL) {
219 rcent = ::csops_audittoken(mPid, CS_OPS_STATUS, &flags, sizeof(flags),
220 mAudit.get());
221 } else {
222 rcent = ::csops(mPid, CS_OPS_STATUS, &flags, sizeof(flags));
223 }
224
225 if (rcent != 0) {
226 MacOSError::throwMe(errSecCSNoSuchCode);
227 }
228
229 return (flags & CS_PLATFORM_BINARY) == CS_PLATFORM_BINARY;
230 }
231
232 } // end namespace CodeSigning
233 } // end namespace Security