]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/piddiskrep.cpp
Security-58286.200.222.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 xpc_dictionary_set_data(request, "infohash", CFDataGetBytePtr(mInfoPlistHash), CFDataGetLength(mInfoPlistHash));
62
63 xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, request);
64 if (reply && xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
65 const void *data;
66 size_t size;
67
68 if (!mInfoPlist) {
69 data = xpc_dictionary_get_data(reply, "infoPlist", &size);
70 if (data && size > 0 && size < 50 * 1024)
71 mInfoPlist.take(CFDataCreate(NULL, (const UInt8 *)data, (CFIndex)size));
72 }
73 if (!mBundleURL) {
74 data = xpc_dictionary_get_data(reply, "bundleURL", &size);
75 if (data && size > 0 && size < 50 * 1024)
76 mBundleURL.take(CFURLCreateWithBytes(NULL, (const UInt8 *)data, (CFIndex)size, kCFStringEncodingUTF8, NULL));
77 }
78 }
79 if (reply)
80 xpc_release(reply);
81
82 xpc_release(request);
83 xpc_release(conn);
84
85 if (!mBundleURL)
86 MacOSError::throwMe(errSecCSNoSuchCode);
87
88 mDataFetched = true;
89 }
90
91
92 PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist)
93 : mDataFetched(false)
94 {
95 BlobCore header;
96 CODESIGN_DISKREP_CREATE_KERNEL(this);
97
98 mPid = pid;
99 mInfoPlist = infoPlist;
100
101 // fetchData();
102
103 int rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header));
104 if (rcent == 0)
105 MacOSError::throwMe(errSecCSNoSuchCode);
106
107 if (errno != ERANGE)
108 UnixError::throwMe(errno);
109
110 if (header.length() > 1024 * 1024)
111 MacOSError::throwMe(errSecCSNoSuchCode);
112
113 uint32_t bufferLen = (uint32_t)header.length();
114 mBuffer = new uint8_t [bufferLen];
115
116 UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen));
117
118 const EmbeddedSignatureBlob *b = (const EmbeddedSignatureBlob *)mBuffer;
119 if (!b->validateBlob(bufferLen))
120 MacOSError::throwMe(errSecCSSignatureInvalid);
121 }
122
123 PidDiskRep::~PidDiskRep()
124 {
125 if (mBuffer)
126 delete [] mBuffer;
127 }
128
129
130 bool PidDiskRep::supportInfoPlist()
131 {
132 fetchData();
133 return mInfoPlist;
134 }
135
136
137 CFDataRef PidDiskRep::component(CodeDirectory::SpecialSlot slot)
138 {
139 if (slot == cdInfoSlot) {
140 fetchData();
141 return mInfoPlist.retain();
142 }
143
144 EmbeddedSignatureBlob *b = (EmbeddedSignatureBlob *)this->blob();
145 return b->component(slot);
146 }
147
148 CFDataRef PidDiskRep::identification()
149 {
150 return NULL;
151 }
152
153
154 CFURLRef PidDiskRep::copyCanonicalPath()
155 {
156 fetchData();
157 return mBundleURL.retain();
158 }
159
160 string PidDiskRep::recommendedIdentifier(const SigningContext &)
161 {
162 return string("pid") + to_string(mPid);
163 }
164
165 size_t PidDiskRep::signingLimit()
166 {
167 return 0;
168 }
169
170 size_t PidDiskRep::execSegLimit(const Architecture *)
171 {
172 return 0;
173 }
174
175 string PidDiskRep::format()
176 {
177 return "pid diskrep";
178 }
179
180 UnixPlusPlus::FileDesc &PidDiskRep::fd()
181 {
182 UnixError::throwMe(EINVAL);
183 }
184
185 string PidDiskRep::mainExecutablePath()
186 {
187 char path[MAXPATHLEN * 2];
188 if(::proc_pidpath(mPid, path, sizeof(path)) == 0)
189 UnixError::throwMe(errno);
190
191 return path;
192 }
193
194 bool PidDiskRep::appleInternalForcePlatform() const
195 {
196 uint32_t flags = 0;
197 int rcent = ::csops(mPid, CS_OPS_STATUS, &flags, sizeof(flags));
198
199 if (rcent != 0) {
200 MacOSError::throwMe(errSecCSNoSuchCode);
201 }
202
203 return (flags & CS_PLATFORM_BINARY) == CS_PLATFORM_BINARY;
204 }
205
206 } // end namespace CodeSigning
207 } // end namespace Security