2 * Copyright (c) 2012 Apple Computer, 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>
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");
98 xpc_object_t reply
= xpc_dictionary_create_reply(event
);
102 if (proc_pidpath(pid
, path
, sizeof(path
)) == 0) {
103 xpc_dictionary_set_string(reply
, "error", "no process for that pid");
106 path
[sizeof(path
) - 1] = '\0';
108 CFURLRef url
= CFURLCreateFromFileSystemRepresentation(NULL
, (const uint8_t *)path
, strlen(path
), 0);
110 xpc_dictionary_set_string(reply
, "error", "failed to create URL");
114 bundle
= _CFBundleCreateWithExecutableURLIfMightBeBundle(NULL
, url
);
116 if (bundle
== NULL
) {
117 xpc_dictionary_set_string(reply
, "error", "Failed to create a bundle");
121 CFURLRef infoPlistURL
= _CFBundleCopyInfoPlistURL(bundle
);
122 if (infoPlistURL
== NULL
) {
123 xpc_dictionary_set_string(reply
, "error", "Info.plist missing");
127 CFDataRef data
= CopyDataFromURL(infoPlistURL
);
128 CFRelease(infoPlistURL
);
130 xpc_dictionary_set_string(reply
, "error", "can't get content of Info.plist");
134 xpc_dictionary_set_data(reply
, "infoPlist", CFDataGetBytePtr(data
), CFDataGetLength(data
));
137 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
);
138 if (bundleURL
== NULL
)
141 data
= CFURLCreateData(NULL
, bundleURL
, kCFStringEncodingUTF8
, true);
142 CFRelease(bundleURL
);
146 xpc_dictionary_set_data(reply
, "bundleURL", CFDataGetBytePtr(data
), CFDataGetLength(data
));
152 xpc_connection_send_message(peer
, reply
);
157 static void CodeSigningHelper_peer_event_handler(xpc_connection_t peer
, xpc_object_t event
)
159 xpc_type_t type
= xpc_get_type(event
);
160 if (type
== XPC_TYPE_ERROR
)
163 assert(type
== XPC_TYPE_DICTIONARY
);
165 const char *cmd
= xpc_dictionary_get_string(event
, "command");
167 xpc_connection_cancel(peer
);
168 } else if (strcmp(cmd
, "fetchData") == 0)
169 fetchData(peer
, event
);
171 syslog(LOG_ERR
, "peer sent invalid command %s", cmd
);
172 xpc_connection_cancel(peer
);
176 static void CodeSigningHelper_event_handler(xpc_connection_t peer
)
178 xpc_connection_set_event_handler(peer
, ^(xpc_object_t event
) {
179 CodeSigningHelper_peer_event_handler(peer
, event
);
181 xpc_connection_resume(peer
);
184 int main(int argc
, const char *argv
[])
187 if (sandbox_init("com.apple.CodeSigningHelper", SANDBOX_NAMED
, &error
)) {
188 syslog(LOG_ERR
, "failed to enter sandbox: %s", error
);
191 xpc_main(CodeSigningHelper_event_handler
);