summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2019-08-28 03:06:18 +0200
committerGravatar Nikias Bassen2019-08-28 03:06:18 +0200
commit5086a9751f5c1298ac423a52b63ca299130aa1c2 (patch)
tree4f1bec2734cdc36d1e2f06f53056a459e524197d /src
parent9e33a26264ab6abe9eea10b7aa11f948b4bde87e (diff)
downloadlibimobiledevice-5086a9751f5c1298ac423a52b63ca299130aa1c2.tar.gz
libimobiledevice-5086a9751f5c1298ac423a52b63ca299130aa1c2.tar.bz2
Add preboardservice_v2 implementation
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/preboard.c318
-rw-r--r--src/preboard.h34
3 files changed, 353 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index fcde8ae..5fcf097 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,7 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \
29 debugserver.c debugserver.h\ 29 debugserver.c debugserver.h\
30 webinspector.c webinspector.h\ 30 webinspector.c webinspector.h\
31 mobileactivation.c mobileactivation.h\ 31 mobileactivation.c mobileactivation.h\
32 preboard.c preboard.h \
32 syslog_relay.c syslog_relay.h 33 syslog_relay.c syslog_relay.h
33 34
34if WIN32 35if WIN32
diff --git a/src/preboard.c b/src/preboard.c
new file mode 100644
index 0000000..7b27a34
--- /dev/null
+++ b/src/preboard.c
@@ -0,0 +1,318 @@
1/*
2 * preboard.c
3 * com.apple.preboardservice_v2 service implementation.
4 *
5 * Copyright (c) 2019 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25#include <string.h>
26#include <stdlib.h>
27#include <plist/plist.h>
28
29#include "preboard.h"
30#include "lockdown.h"
31#include "common/debug.h"
32
33/**
34 * Convert a property_list_service_error_t value to a preboard_error_t value.
35 * Used internally to get correct error codes.
36 *
37 * @param err An property_list_service_error_t error code
38 *
39 * @return A matching preboard_error_t error code,
40 * PREBOARD_E_UNKNOWN_ERROR otherwise.
41 */
42static preboard_error_t preboard_error(property_list_service_error_t err)
43{
44 switch (err) {
45 case PROPERTY_LIST_SERVICE_E_SUCCESS:
46 return PREBOARD_E_SUCCESS;
47 case PROPERTY_LIST_SERVICE_E_INVALID_ARG:
48 return PREBOARD_E_INVALID_ARG;
49 case PROPERTY_LIST_SERVICE_E_PLIST_ERROR:
50 return PREBOARD_E_PLIST_ERROR;
51 case PROPERTY_LIST_SERVICE_E_MUX_ERROR:
52 return PREBOARD_E_MUX_ERROR;
53 case PROPERTY_LIST_SERVICE_E_SSL_ERROR:
54 return PREBOARD_E_SSL_ERROR;
55 case PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA:
56 return PREBOARD_E_NOT_ENOUGH_DATA;
57 case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT:
58 return PREBOARD_E_TIMEOUT;
59 default:
60 break;
61 }
62 return PREBOARD_E_UNKNOWN_ERROR;
63}
64
65LIBIMOBILEDEVICE_API preboard_error_t preboard_client_new(idevice_t device, lockdownd_service_descriptor_t service, preboard_client_t * client)
66{
67 *client = NULL;
68
69 if (!device || !service || service->port == 0 || !client || *client) {
70 debug_info("Incorrect parameter passed to preboard_client_new.");
71 return PREBOARD_E_INVALID_ARG;
72 }
73
74 debug_info("Creating preboard_client, port = %d.", service->port);
75
76 property_list_service_client_t plclient = NULL;
77 preboard_error_t ret = preboard_error(property_list_service_client_new(device, service, &plclient));
78 if (ret != PREBOARD_E_SUCCESS) {
79 debug_info("Creating a property list client failed. Error: %i", ret);
80 return ret;
81 }
82
83 preboard_client_t client_loc = (preboard_client_t) malloc(sizeof(struct preboard_client_private));
84 client_loc->parent = plclient;
85 client_loc->receive_status_thread = THREAD_T_NULL;
86
87 *client = client_loc;
88
89 debug_info("preboard_client successfully created.");
90 return 0;
91}
92
93LIBIMOBILEDEVICE_API preboard_error_t preboard_client_start_service(idevice_t device, preboard_client_t * client, const char* label)
94{
95 preboard_error_t err = PREBOARD_E_UNKNOWN_ERROR;
96 service_client_factory_start_service(device, PREBOARD_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(preboard_client_new), &err);
97 return err;
98}
99
100LIBIMOBILEDEVICE_API preboard_error_t preboard_client_free(preboard_client_t client)
101{
102 if (!client)
103 return PREBOARD_E_INVALID_ARG;
104
105 property_list_service_client_t parent = client->parent;
106 client->parent = NULL;
107 if (client->receive_status_thread) {
108 debug_info("joining receive_status_thread");
109 thread_join(client->receive_status_thread);
110 thread_free(client->receive_status_thread);
111 client->receive_status_thread = THREAD_T_NULL;
112 }
113 preboard_error_t err = preboard_error(property_list_service_client_free(parent));
114 free(client);
115
116 return err;
117}
118
119LIBIMOBILEDEVICE_API preboard_error_t preboard_send(preboard_client_t client, plist_t plist)
120{
121 preboard_error_t res = PREBOARD_E_UNKNOWN_ERROR;
122 res = preboard_error(property_list_service_send_binary_plist(client->parent, plist));
123 if (res != PREBOARD_E_SUCCESS) {
124 debug_info("Sending plist failed with error %d", res);
125 return res;
126 }
127 return res;
128}
129
130LIBIMOBILEDEVICE_API preboard_error_t preboard_receive_with_timeout(preboard_client_t client, plist_t * plist, uint32_t timeout_ms)
131{
132 preboard_error_t res = PREBOARD_E_UNKNOWN_ERROR;
133 plist_t outplist = NULL;
134 res = preboard_error(property_list_service_receive_plist_with_timeout(client->parent, &outplist, timeout_ms));
135 if (res != PREBOARD_E_SUCCESS && res != PREBOARD_E_TIMEOUT) {
136 debug_info("Could not receive plist, error %d", res);
137 plist_free(outplist);
138 } else if (res == PREBOARD_E_SUCCESS) {
139 *plist = outplist;
140 }
141 return res;
142}
143
144LIBIMOBILEDEVICE_API preboard_error_t preboard_receive(preboard_client_t client, plist_t * plist)
145{
146 return preboard_receive_with_timeout(client, plist, 5000);
147}
148
149struct preboard_status_data {
150 preboard_client_t client;
151 preboard_status_cb_t cbfunc;
152 void *user_data;
153};
154
155static void* preboard_receive_status_loop_thread(void* arg)
156{
157 struct preboard_status_data *data = (struct preboard_status_data*)arg;
158
159 /* run until the service disconnects or an error occurs */
160 while (data->client && data->client->parent) {
161 plist_t pl = NULL;
162 preboard_error_t perr = preboard_receive_with_timeout(data->client, &pl, 1000);
163 if (perr == PREBOARD_E_TIMEOUT) {
164 continue;
165 } else if (perr == PREBOARD_E_SUCCESS) {
166 data->cbfunc(pl, data->user_data);
167 }
168 plist_free(pl);
169 if (perr != PREBOARD_E_SUCCESS) {
170 data->cbfunc(NULL, data->user_data);
171 break;
172 }
173 }
174
175 /* cleanup */
176 debug_info("done, cleaning up.");
177
178 if (data->client->receive_status_thread) {
179 thread_free(data->client->receive_status_thread);
180 data->client->receive_status_thread = THREAD_T_NULL;
181 }
182 free(data);
183
184 return NULL;
185}
186
187static preboard_error_t preboard_receive_status_loop_with_callback(preboard_client_t client, preboard_status_cb_t status_cb, void *user_data)
188{
189 if (!client || !client->parent) {
190 return PREBOARD_E_INVALID_ARG;
191 }
192
193 if (client->receive_status_thread) {
194 return PREBOARD_E_OP_IN_PROGRESS;
195 }
196
197 preboard_error_t res = PREBOARD_E_UNKNOWN_ERROR;
198 struct preboard_status_data *data = (struct preboard_status_data*)malloc(sizeof(struct preboard_status_data));
199 if (data) {
200 data->client = client;
201 data->cbfunc = status_cb;
202 data->user_data = user_data;
203 if (thread_new(&client->receive_status_thread, preboard_receive_status_loop_thread, data) == 0) {
204 res = PREBOARD_E_SUCCESS;
205 }
206 }
207
208 return res;
209}
210
211LIBIMOBILEDEVICE_API preboard_error_t preboard_create_stashbag(preboard_client_t client, plist_t manifest, preboard_status_cb_t status_cb, void *user_data)
212{
213 if (!client) {
214 return PREBOARD_E_INVALID_ARG;
215 }
216
217 plist_t dict = plist_new_dict();
218 plist_dict_set_item(dict, "Command", plist_new_string("CreateStashbag"));
219 if (manifest) {
220 plist_dict_set_item(dict, "Manifest", plist_copy(manifest));
221 }
222 preboard_error_t perr = preboard_send(client, dict);
223 plist_free(dict);
224 if (perr != PREBOARD_E_SUCCESS) {
225 return perr;
226 }
227 if (!status_cb) {
228 return PREBOARD_E_SUCCESS;
229 }
230
231 return preboard_receive_status_loop_with_callback(client, status_cb, user_data);
232
233 // return { ShowDialog: true} or {Timeout: true} followed by {HideDialog: true}
234 // or { Error: 1, ErrorString: <error string> }
235
236
237/*
238<?xml version="1.0" encoding="UTF-8"?>
239<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
240<plist version="1.0">
241<dict>
242 <key>ShowDialog</key>
243 <true/>
244 <key>Version</key>
245 <integer>2</integer>
246</dict>
247</plist>
248
249for success, it will send the HideDialog message, then wait up to 14400 seconds (4h) for the device to reboot?
250
251
252<!-- error: -->
253
254<?xml version="1.0" encoding="UTF-8"?>
255<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
256<plist version="1.0">
257<dict>
258 <key>Error</key>
259 <integer>1</integer>
260 <key>ErrorString</key>
261 <string>user authentication failed: Error Domain=com.apple.LocalAuthentication Code=-2 "Canceled by user." UserInfo={BiometryType=1, NSLocalizedDescription=Canceled by user.}</string>
262 <key>Version</key>
263 <integer>2</integer>
264</dict>
265</plist>
266
267<!-- or after 2 minutes -->
268
269<?xml version="1.0" encoding="UTF-8"?>
270<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
271<plist version="1.0">
272<dict>
273 <key>Timeout</key>
274 <true/>
275 <key>Version</key>
276 <integer>2</integer>
277</dict>
278</plist>
279
280<?xml version="1.0" encoding="UTF-8"?>
281<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
282<plist version="1.0">
283<dict>
284 <key>HideDialog</key>
285 <true/>
286 <key>Version</key>
287 <integer>2</integer>
288</dict>
289</plist>
290
291*/
292}
293
294LIBIMOBILEDEVICE_API preboard_error_t preboard_commit_stashbag(preboard_client_t client, plist_t manifest, preboard_status_cb_t status_cb, void *user_data)
295{
296 // returns { StashbagCommitComplete: true }
297 // or { StashbagCommitComplete: 0, Error: 1, <optional> ErrorString: <error string> }
298
299 if (!client) {
300 return PREBOARD_E_INVALID_ARG;
301 }
302
303 plist_t dict = plist_new_dict();
304 plist_dict_set_item(dict, "Command", plist_new_string("CommitStashbag"));
305 if (manifest) {
306 plist_dict_set_item(dict, "Manifest", plist_copy(manifest));
307 }
308 preboard_error_t perr = preboard_send(client, dict);
309 plist_free(dict);
310 if (perr != PREBOARD_E_SUCCESS) {
311 return perr;
312 }
313 if (!status_cb) {
314 return PREBOARD_E_SUCCESS;
315 }
316
317 return preboard_receive_status_loop_with_callback(client, status_cb, user_data);
318}
diff --git a/src/preboard.h b/src/preboard.h
new file mode 100644
index 0000000..c5143a9
--- /dev/null
+++ b/src/preboard.h
@@ -0,0 +1,34 @@
1/*
2 * preboard.h
3 * com.apple.preboard_v2 service header file.
4 *
5 * Copyright (c) 2019 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifndef __PREBOARD_H
23#define __PREBOARD_H
24
25#include "libimobiledevice/preboard.h"
26#include "property_list_service.h"
27#include "common/thread.h"
28
29struct preboard_client_private {
30 property_list_service_client_t parent;
31 THREAD_T receive_status_thread;
32};
33
34#endif