2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * A simple XPCService that returns the Info.plist for a specific pid,
26 * the use-case is is for service that is not running as the user or
27 * in a sandbox and can't access the file directly.
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <CoreFoundation/CFBundlePriv.h>
32 #include <sys/param.h>
35 #include <security_utilities/simulatecrash_assert.h>
41 CopyDataFromURL(CFURLRef url
)
43 CFReadStreamRef stream
= CFReadStreamCreateWithFile(NULL
, url
);
47 if (!CFReadStreamOpen(stream
)) {
52 CFMutableDataRef data
= CFDataCreateMutable(NULL
, 0);
62 if (CFDataGetLength(data
) > 100 * 1024) {
63 syslog(LOG_ERR
, "refusing to handle back Info.plist that is more then 100K");
68 CFIndex readBytes
= CFReadStreamRead(stream
, buf
, sizeof(buf
));
71 } else if (readBytes
<= 0) {
77 assert(readBytes
<= sizeof(buf
));
78 CFDataAppendBytes(data
, (void *)buf
, readBytes
);
81 CFReadStreamClose(stream
);
88 fetchData(xpc_connection_t peer
, xpc_object_t event
)
90 CFBundleRef bundle
= NULL
;
91 char path
[MAXPATHLEN
];
94 pid
= (pid_t
)xpc_dictionary_get_int64(event
, "pid");
99 const void* iphash
= xpc_dictionary_get_data(event
, "infohash", &iphLength
);
101 xpc_object_t reply
= xpc_dictionary_create_reply(event
);
105 if (proc_pidpath(pid
, path
, sizeof(path
)) == 0) {
106 xpc_dictionary_set_string(reply
, "error", "no process for that pid");
109 path
[sizeof(path
) - 1] = '\0';
111 CFURLRef url
= CFURLCreateFromFileSystemRepresentation(NULL
, (const uint8_t *)path
, strlen(path
), 0);
113 xpc_dictionary_set_string(reply
, "error", "failed to create URL");
117 bundle
= _CFBundleCreateWithExecutableURLIfMightBeBundle(NULL
, url
);
119 if (bundle
== NULL
) {
120 xpc_dictionary_set_string(reply
, "error", "Failed to create a bundle");
124 CFURLRef infoPlistURL
= _CFBundleCopyInfoPlistURL(bundle
);
125 if (infoPlistURL
== NULL
) {
126 xpc_dictionary_set_string(reply
, "error", "Info.plist missing");
130 CFDataRef data
= CopyDataFromURL(infoPlistURL
);
131 CFRelease(infoPlistURL
);
133 xpc_dictionary_set_string(reply
, "error", "can't get content of Info.plist");
137 ... check the
"right" hash against iphash
/iphLength
139 xpc_dictionary_set_data(reply
, "infoPlist", CFDataGetBytePtr(data
), CFDataGetLength(data
));
142 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
);
143 if (bundleURL
== NULL
)
146 data
= CFURLCreateData(NULL
, bundleURL
, kCFStringEncodingUTF8
, true);
147 CFRelease(bundleURL
);
151 xpc_dictionary_set_data(reply
, "bundleURL", CFDataGetBytePtr(data
), CFDataGetLength(data
));
157 xpc_connection_send_message(peer
, reply
);
162 static void CodeSigningHelper_peer_event_handler(xpc_connection_t peer
, xpc_object_t event
)
164 xpc_type_t type
= xpc_get_type(event
);
165 if (type
== XPC_TYPE_ERROR
)
168 assert(type
== XPC_TYPE_DICTIONARY
);
170 const char *cmd
= xpc_dictionary_get_string(event
, "command");
172 xpc_connection_cancel(peer
);
173 } else if (strcmp(cmd
, "fetchData") == 0)
174 fetchData(peer
, event
);
176 syslog(LOG_ERR
, "peer sent invalid command %s", cmd
);
177 xpc_connection_cancel(peer
);
181 static void CodeSigningHelper_event_handler(xpc_connection_t peer
)
183 xpc_connection_set_event_handler(peer
, ^(xpc_object_t event
) {
184 CodeSigningHelper_peer_event_handler(peer
, event
);
186 xpc_connection_resume(peer
);
189 int main(int argc
, const char *argv
[])
192 if (sandbox_init("com.apple.CodeSigningHelper", SANDBOX_NAMED
, &error
)) {
193 syslog(LOG_ERR
, "failed to enter sandbox: %s", error
);
196 xpc_main(CodeSigningHelper_event_handler
);