summaryrefslogtreecommitdiffstats
path: root/src/mobile_image_mounter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mobile_image_mounter.c')
-rw-r--r--src/mobile_image_mounter.c514
1 files changed, 416 insertions, 98 deletions
diff --git a/src/mobile_image_mounter.c b/src/mobile_image_mounter.c
index 367bee0..6df50c4 100644
--- a/src/mobile_image_mounter.c
+++ b/src/mobile_image_mounter.c
@@ -2,23 +2,26 @@
2 * mobile_image_mounter.c 2 * mobile_image_mounter.c
3 * com.apple.mobile.mobile_image_mounter service implementation. 3 * com.apple.mobile.mobile_image_mounter service implementation.
4 * 4 *
5 * Copyright (c) 2010 Nikias Bassen, All Rights Reserved. 5 * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 10 * version 2.1 of the License, or (at your option) any later version.
11 * 11 *
12 * This library is distributed in the hope that it will be useful, 12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 15 * Lesser General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public 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 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 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
22#include <string.h> 25#include <string.h>
23#include <stdlib.h> 26#include <stdlib.h>
24#include <unistd.h> 27#include <unistd.h>
@@ -26,7 +29,7 @@
26 29
27#include "mobile_image_mounter.h" 30#include "mobile_image_mounter.h"
28#include "property_list_service.h" 31#include "property_list_service.h"
29#include "debug.h" 32#include "common/debug.h"
30 33
31/** 34/**
32 * Locks a mobile_image_mounter client, used for thread safety. 35 * Locks a mobile_image_mounter client, used for thread safety.
@@ -35,17 +38,17 @@
35 */ 38 */
36static void mobile_image_mounter_lock(mobile_image_mounter_client_t client) 39static void mobile_image_mounter_lock(mobile_image_mounter_client_t client)
37{ 40{
38 g_mutex_lock(client->mutex); 41 mutex_lock(&client->mutex);
39} 42}
40 43
41/** 44/**
42 * Unlocks a mobile_image_mounter client, used for thread safety. 45 * Unlocks a mobile_image_mounter client, used for thread safety.
43 * 46 *
44 * @param client mobile_image_mounter client to unlock 47 * @param client mobile_image_mounter client to unlock
45 */ 48 */
46static void mobile_image_mounter_unlock(mobile_image_mounter_client_t client) 49static void mobile_image_mounter_unlock(mobile_image_mounter_client_t client)
47{ 50{
48 g_mutex_unlock(client->mutex); 51 mutex_unlock(&client->mutex);
49} 52}
50 53
51/** 54/**
@@ -75,51 +78,30 @@ static mobile_image_mounter_error_t mobile_image_mounter_error(property_list_ser
75 return MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR; 78 return MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR;
76} 79}
77 80
78/** 81mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, lockdownd_service_descriptor_t service, mobile_image_mounter_client_t *client)
79 * Connects to the mobile_image_mounter service on the specified device.
80 *
81 * @param device The device to connect to.
82 * @param port Destination port (usually given by lockdownd_start_service).
83 * @param client Pointer that will be set to a newly allocated
84 * mobile_image_mounter_client_t upon successful return.
85 *
86 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success,
87 * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if device is NULL,
88 * or MOBILE_IMAGE_MOUNTER_E_CONN_FAILED if the connection to the
89 * device could not be established.
90 */
91mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, uint16_t port, mobile_image_mounter_client_t *client)
92{ 82{
93 /* makes sure thread environment is available */
94 if (!g_thread_supported())
95 g_thread_init(NULL);
96
97 if (!device)
98 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
99
100 property_list_service_client_t plistclient = NULL; 83 property_list_service_client_t plistclient = NULL;
101 if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { 84 mobile_image_mounter_error_t err = mobile_image_mounter_error(property_list_service_client_new(device, service, &plistclient));
102 return MOBILE_IMAGE_MOUNTER_E_CONN_FAILED; 85 if (err != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
86 return err;
103 } 87 }
104 88
105 mobile_image_mounter_client_t client_loc = (mobile_image_mounter_client_t) malloc(sizeof(struct mobile_image_mounter_client_private)); 89 mobile_image_mounter_client_t client_loc = (mobile_image_mounter_client_t) malloc(sizeof(struct mobile_image_mounter_client_private));
106 client_loc->parent = plistclient; 90 client_loc->parent = plistclient;
107 91
108 client_loc->mutex = g_mutex_new(); 92 mutex_init(&client_loc->mutex);
109 93
110 *client = client_loc; 94 *client = client_loc;
111 return MOBILE_IMAGE_MOUNTER_E_SUCCESS; 95 return MOBILE_IMAGE_MOUNTER_E_SUCCESS;
112} 96}
113 97
114/** 98mobile_image_mounter_error_t mobile_image_mounter_start_service(idevice_t device, mobile_image_mounter_client_t * client, const char* label)
115 * Disconnects a mobile_image_mounter client from the device and frees up the 99{
116 * mobile_image_mounter client data. 100 mobile_image_mounter_error_t err = MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR;
117 * 101 service_client_factory_start_service(device, MOBILE_IMAGE_MOUNTER_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(mobile_image_mounter_new), &err);
118 * @param client The mobile_image_mounter client to disconnect and free. 102 return err;
119 * 103}
120 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, 104
121 * or MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if client is NULL.
122 */
123mobile_image_mounter_error_t mobile_image_mounter_free(mobile_image_mounter_client_t client) 105mobile_image_mounter_error_t mobile_image_mounter_free(mobile_image_mounter_client_t client)
124{ 106{
125 if (!client) 107 if (!client)
@@ -127,27 +109,12 @@ mobile_image_mounter_error_t mobile_image_mounter_free(mobile_image_mounter_clie
127 109
128 property_list_service_client_free(client->parent); 110 property_list_service_client_free(client->parent);
129 client->parent = NULL; 111 client->parent = NULL;
130 if (client->mutex) { 112 mutex_destroy(&client->mutex);
131 g_mutex_free(client->mutex);
132 }
133 free(client); 113 free(client);
134 114
135 return MOBILE_IMAGE_MOUNTER_E_SUCCESS; 115 return MOBILE_IMAGE_MOUNTER_E_SUCCESS;
136} 116}
137 117
138/**
139 * Tells if the image of ImageType is already mounted.
140 *
141 * @param client The client use
142 * @param image_type The type of the image to look up
143 * @param result Pointer to a plist that will receive the result of the
144 * operation.
145 *
146 * @note This function may return MOBILE_IMAGE_MOUNTER_E_SUCCESS even if the
147 * operation has failed. Check the resulting plist for further information.
148 *
149 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, or an error code on error
150 */
151mobile_image_mounter_error_t mobile_image_mounter_lookup_image(mobile_image_mounter_client_t client, const char *image_type, plist_t *result) 118mobile_image_mounter_error_t mobile_image_mounter_lookup_image(mobile_image_mounter_client_t client, const char *image_type, plist_t *result)
152{ 119{
153 if (!client || !image_type || !result) { 120 if (!client || !image_type || !result) {
@@ -156,8 +123,8 @@ mobile_image_mounter_error_t mobile_image_mounter_lookup_image(mobile_image_moun
156 mobile_image_mounter_lock(client); 123 mobile_image_mounter_lock(client);
157 124
158 plist_t dict = plist_new_dict(); 125 plist_t dict = plist_new_dict();
159 plist_dict_insert_item(dict,"Command", plist_new_string("LookupImage")); 126 plist_dict_set_item(dict,"Command", plist_new_string("LookupImage"));
160 plist_dict_insert_item(dict,"ImageType", plist_new_string(image_type)); 127 plist_dict_set_item(dict,"ImageType", plist_new_string(image_type));
161 128
162 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict)); 129 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
163 plist_free(dict); 130 plist_free(dict);
@@ -177,39 +144,139 @@ leave_unlock:
177 return res; 144 return res;
178} 145}
179 146
180/** 147static mobile_image_mounter_error_t process_result(plist_t result, const char *expected_status)
181 * Mounts an image on the device. 148{
182 * 149 mobile_image_mounter_error_t res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
183 * @param client The connected mobile_image_mounter client. 150 char* strval = NULL;
184 * @param image_path The absolute path of the image to mount. The image must 151 plist_t node;
185 * be present before calling this function. 152
186 * @param image_signature Pointer to a buffer holding the images' signature 153 node = plist_dict_get_item(result, "Error");
187 * @param signature_length Length of the signature image_signature points to 154 if (node && plist_get_node_type(node) == PLIST_STRING) {
188 * @param image_type Type of image to mount 155 plist_get_string_val(node, &strval);
189 * @param result Pointer to a plist that will receive the result of the 156 }
190 * operation. 157 if (strval) {
191 * 158 if (!strcmp(strval, "DeviceLocked")) {
192 * @note This function may return MOBILE_IMAGE_MOUNTER_E_SUCCESS even if the 159 debug_info("Device is locked, can't mount");
193 * operation has failed. Check the resulting plist for further information. 160 res = MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED;
194 * Note that there is no unmounting function. The mount persists until the 161 } else {
195 * device is rebooted. 162 debug_info("Unhandled error '%s' received", strval);
196 * 163 }
197 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, 164 free(strval);
198 * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if on ore more parameters are 165 return res;
199 * invalid, or another error code otherwise. 166 }
200 */ 167
201mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, const char *image_path, const char *image_signature, uint16_t signature_length, const char *image_type, plist_t *result) 168 node = plist_dict_get_item(result, "Status");
169 if (node && plist_get_node_type(node) == PLIST_STRING) {
170 plist_get_string_val(node, &strval);
171 }
172 if (!strval) {
173 debug_info("Error: Unexpected response received!");
174 } else if (strcmp(strval, expected_status) == 0) {
175 res = MOBILE_IMAGE_MOUNTER_E_SUCCESS;
176 } else {
177 debug_info("Error: didn't get %s but %s", expected_status, strval);
178 }
179 free(strval);
180
181 return res;
182}
183
184mobile_image_mounter_error_t mobile_image_mounter_upload_image(mobile_image_mounter_client_t client, const char *image_type, size_t image_size, const unsigned char *signature, unsigned int signature_size, mobile_image_mounter_upload_cb_t upload_cb, void* userdata)
185{
186 if (!client || !image_type || (image_size == 0) || !upload_cb) {
187 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
188 }
189 mobile_image_mounter_lock(client);
190 plist_t result = NULL;
191
192 plist_t dict = plist_new_dict();
193 plist_dict_set_item(dict, "Command", plist_new_string("ReceiveBytes"));
194 if (signature && signature_size != 0)
195 plist_dict_set_item(dict, "ImageSignature", plist_new_data((char*)signature, signature_size));
196 plist_dict_set_item(dict, "ImageSize", plist_new_uint(image_size));
197 plist_dict_set_item(dict, "ImageType", plist_new_string(image_type));
198
199 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
200 plist_free(dict);
201
202 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
203 debug_info("Error sending XML plist to device!");
204 goto leave_unlock;
205 }
206
207 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
208 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
209 debug_info("Error receiving response from device!");
210 goto leave_unlock;
211 }
212 res = process_result(result, "ReceiveBytesAck");
213 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
214 goto leave_unlock;
215 }
216
217 size_t tx = 0;
218 size_t bufsize = 65536;
219 unsigned char *buf = (unsigned char*)malloc(bufsize);
220 if (!buf) {
221 debug_info("Out of memory");
222 res = MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR;
223 goto leave_unlock;
224 }
225 debug_info("uploading image (%d bytes)", (int)image_size);
226 while (tx < image_size) {
227 size_t remaining = image_size - tx;
228 size_t amount = (remaining < bufsize) ? remaining : bufsize;
229 ssize_t r = upload_cb(buf, amount, userdata);
230 if (r < 0) {
231 debug_info("upload_cb returned %d", (int)r);
232 break;
233 }
234 uint32_t sent = 0;
235 if (service_send(client->parent->parent, (const char*)buf, (uint32_t)r, &sent) != SERVICE_E_SUCCESS) {
236 debug_info("service_send failed");
237 break;
238 }
239 tx += r;
240 }
241 free(buf);
242 if (tx < image_size) {
243 debug_info("Error: failed to upload image");
244 res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
245 goto leave_unlock;
246 }
247 debug_info("image uploaded");
248
249 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
250 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
251 debug_info("Error receiving response from device!");
252 goto leave_unlock;
253 }
254 res = process_result(result, "Complete");
255
256leave_unlock:
257 mobile_image_mounter_unlock(client);
258 if (result)
259 plist_free(result);
260 return res;
261
262}
263
264mobile_image_mounter_error_t mobile_image_mounter_mount_image_with_options(mobile_image_mounter_client_t client, const char *image_path, const unsigned char *signature, unsigned int signature_size, const char *image_type, plist_t options, plist_t *result)
202{ 265{
203 if (!client || !image_path || !image_signature || (signature_length == 0) || !image_type || !result) { 266 if (!client || !image_path || !image_type || !result) {
204 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; 267 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
205 } 268 }
206 mobile_image_mounter_lock(client); 269 mobile_image_mounter_lock(client);
207 270
208 plist_t dict = plist_new_dict(); 271 plist_t dict = plist_new_dict();
209 plist_dict_insert_item(dict, "Command", plist_new_string("MountImage")); 272 plist_dict_set_item(dict, "Command", plist_new_string("MountImage"));
210 plist_dict_insert_item(dict, "ImagePath", plist_new_string(image_path)); 273 plist_dict_set_item(dict, "ImagePath", plist_new_string(image_path));
211 plist_dict_insert_item(dict, "ImageSignature", plist_new_data(image_signature, signature_length)); 274 if (signature && signature_size != 0)
212 plist_dict_insert_item(dict, "ImageType", plist_new_string(image_type)); 275 plist_dict_set_item(dict, "ImageSignature", plist_new_data((char*)signature, signature_size));
276 plist_dict_set_item(dict, "ImageType", plist_new_string(image_type));
277 if (PLIST_IS_DICT(options)) {
278 plist_dict_merge(&dict, options);
279 }
213 280
214 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict)); 281 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
215 plist_free(dict); 282 plist_free(dict);
@@ -229,17 +296,56 @@ leave_unlock:
229 return res; 296 return res;
230} 297}
231 298
232/** 299mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, const char *image_path, const unsigned char *signature, unsigned int signature_size, const char *image_type, plist_t *result)
233 * Hangs up the connection to the mobile_image_mounter service. 300{
234 * This functions has to be called before freeing up a mobile_image_mounter 301 return mobile_image_mounter_mount_image_with_options(client, image_path, signature, signature_size, image_type, NULL, result);
235 * instance. If not, errors appear in the device's syslog. 302}
236 * 303
237 * @param client The client to hang up 304mobile_image_mounter_error_t mobile_image_mounter_unmount_image(mobile_image_mounter_client_t client, const char *mount_path)
238 * 305{
239 * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, 306 if (!client || !mount_path) {
240 * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if client is invalid, 307 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
241 * or another error code otherwise. 308 }
242 */ 309 mobile_image_mounter_lock(client);
310
311 plist_t dict = plist_new_dict();
312 plist_dict_set_item(dict, "Command", plist_new_string("UnmountImage"));
313 plist_dict_set_item(dict, "MountPath", plist_new_string(mount_path));
314 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
315 plist_free(dict);
316
317 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
318 debug_info("%s: Error sending XML plist to device!", __func__);
319 goto leave_unlock;
320 }
321
322 plist_t result = NULL;
323 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
324 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
325 debug_info("%s: Error receiving response from device!", __func__);
326 } else {
327 plist_t p_error = plist_dict_get_item(result, "Error");
328 if (p_error) {
329 plist_t p_detailed = plist_dict_get_item(result, "DetailedError");
330 const char* detailederr = (p_detailed) ? plist_get_string_ptr(p_detailed, NULL) : "";
331 const char* errstr = plist_get_string_ptr(p_error, NULL);
332 if (errstr && !strcmp(errstr, "UnknownCommand")) {
333 res = MOBILE_IMAGE_MOUNTER_E_NOT_SUPPORTED;
334 } else if (errstr && !strcmp(errstr, "DeviceLocked")) {
335 res = MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED;
336 } else if (strstr(detailederr, "no matching entry")) {
337 res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
338 } else {
339 res = MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR;
340 }
341 }
342 }
343
344leave_unlock:
345 mobile_image_mounter_unlock(client);
346 return res;
347}
348
243mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client) 349mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client)
244{ 350{
245 if (!client) { 351 if (!client) {
@@ -248,7 +354,7 @@ mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_cl
248 mobile_image_mounter_lock(client); 354 mobile_image_mounter_lock(client);
249 355
250 plist_t dict = plist_new_dict(); 356 plist_t dict = plist_new_dict();
251 plist_dict_insert_item(dict, "Command", plist_new_string("Hangup")); 357 plist_dict_set_item(dict, "Command", plist_new_string("Hangup"));
252 358
253 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict)); 359 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
254 plist_free(dict); 360 plist_free(dict);
@@ -272,3 +378,215 @@ leave_unlock:
272 mobile_image_mounter_unlock(client); 378 mobile_image_mounter_unlock(client);
273 return res; 379 return res;
274} 380}
381
382mobile_image_mounter_error_t mobile_image_mounter_query_developer_mode_status(mobile_image_mounter_client_t client, plist_t *result)
383{
384 if (!client || !result) {
385 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
386 }
387 mobile_image_mounter_lock(client);
388
389 plist_t dict = plist_new_dict();
390 plist_dict_set_item(dict, "Command", plist_new_string("QueryDeveloperModeStatus"));
391 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
392 plist_free(dict);
393
394 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
395 debug_info("%s: Error sending XML plist to device!", __func__);
396 goto leave_unlock;
397 }
398
399 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, result));
400 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
401 debug_info("%s: Error receiving response from device!", __func__);
402 }
403
404leave_unlock:
405 mobile_image_mounter_unlock(client);
406 return res;
407}
408
409mobile_image_mounter_error_t mobile_image_mounter_query_nonce(mobile_image_mounter_client_t client, const char* image_type, unsigned char** nonce, unsigned int* nonce_size)
410{
411 if (!client || !nonce || !nonce_size) {
412 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
413 }
414 mobile_image_mounter_lock(client);
415
416 plist_t dict = plist_new_dict();
417 plist_dict_set_item(dict, "Command", plist_new_string("QueryNonce"));
418 if (image_type) {
419 plist_dict_set_item(dict, "PersonalizedImageType", plist_new_string(image_type));
420 }
421 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
422 plist_free(dict);
423
424 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
425 debug_info("%s: Error sending XML plist to device!", __func__);
426 goto leave_unlock;
427 }
428
429 plist_t result = NULL;
430 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
431 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
432 debug_info("%s: Error receiving response from device!", __func__);
433 } else {
434 plist_t p_nonce = plist_dict_get_item(result, "PersonalizationNonce");
435 if (!p_nonce) {
436 res = MOBILE_IMAGE_MOUNTER_E_NOT_SUPPORTED;
437 } else {
438 uint64_t nonce_size_ = 0;
439 plist_get_data_val(p_nonce, (char**)nonce, &nonce_size_);
440 if (*nonce) {
441 *nonce_size = (unsigned int)nonce_size_;
442 } else {
443 res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
444 }
445 }
446 }
447 plist_free(result);
448
449leave_unlock:
450 mobile_image_mounter_unlock(client);
451 return res;
452}
453
454mobile_image_mounter_error_t mobile_image_mounter_query_personalization_identifiers(mobile_image_mounter_client_t client, const char* image_type, plist_t *result)
455{
456 if (!client || !result) {
457 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
458 }
459 mobile_image_mounter_lock(client);
460
461 plist_t dict = plist_new_dict();
462 plist_dict_set_item(dict, "Command", plist_new_string("QueryPersonalizationIdentifiers"));
463 if (image_type) {
464 plist_dict_set_item(dict, "PersonalizedImageType", plist_new_string(image_type));
465 }
466 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
467 plist_free(dict);
468
469 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
470 debug_info("%s: Error sending XML plist to device!", __func__);
471 goto leave_unlock;
472 }
473
474 plist_t _result = NULL;
475 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &_result));
476 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
477 debug_info("%s: Error receiving response from device!", __func__);
478 }
479 *result = plist_copy(plist_dict_get_item(_result, "PersonalizationIdentifiers"));
480 if (!*result) {
481 debug_info("%s: Response did not contain PersonalizationIdentifiers!", __func__);
482 res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
483 }
484
485leave_unlock:
486 mobile_image_mounter_unlock(client);
487 return res;
488}
489
490mobile_image_mounter_error_t mobile_image_mounter_query_personalization_manifest(mobile_image_mounter_client_t client, const char* image_type, const unsigned char* signature, unsigned int signature_size, unsigned char** manifest, unsigned int* manifest_size)
491{
492 if (!client || !image_type || !signature || !signature_size || !manifest || !manifest_size) {
493 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
494 }
495 mobile_image_mounter_lock(client);
496
497 plist_t dict = plist_new_dict();
498 plist_dict_set_item(dict, "Command", plist_new_string("QueryPersonalizationManifest"));
499 plist_dict_set_item(dict, "PersonalizedImageType", plist_new_string(image_type));
500 plist_dict_set_item(dict, "ImageType", plist_new_string(image_type));
501 plist_dict_set_item(dict, "ImageSignature", plist_new_data((char*)signature, signature_size));
502
503 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
504 plist_free(dict);
505
506 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
507 debug_info("%s: Error sending XML plist to device!", __func__);
508 goto leave_unlock;
509 }
510
511 plist_t result = NULL;
512 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
513 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
514 debug_info("%s: Error receiving response from device!", __func__);
515 } else {
516 plist_t p_manifest = plist_dict_get_item(result, "ImageSignature");
517 if (!p_manifest) {
518 res = MOBILE_IMAGE_MOUNTER_E_NOT_SUPPORTED;
519 } else {
520 uint64_t manifest_size_ = 0;
521 plist_get_data_val(p_manifest, (char**)manifest, &manifest_size_);
522 if (*manifest) {
523 *manifest_size = (unsigned int)manifest_size_;
524 } else {
525 res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED;
526 }
527 }
528 }
529 plist_free(result);
530
531leave_unlock:
532 mobile_image_mounter_unlock(client);
533 return res;
534}
535
536mobile_image_mounter_error_t mobile_image_mounter_roll_personalization_nonce(mobile_image_mounter_client_t client)
537{
538 if (!client) {
539 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
540 }
541 mobile_image_mounter_lock(client);
542
543 plist_t dict = plist_new_dict();
544 plist_dict_set_item(dict, "Command", plist_new_string("RollPersonalizationNonce"));
545 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
546 plist_free(dict);
547
548 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
549 debug_info("%s: Error sending XML plist to device!", __func__);
550 goto leave_unlock;
551 }
552
553 plist_t result = NULL;
554 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
555 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
556 debug_info("%s: Error receiving response from device!", __func__);
557 }
558 plist_free(result);
559
560leave_unlock:
561 mobile_image_mounter_unlock(client);
562 return res;
563}
564
565mobile_image_mounter_error_t mobile_image_mounter_roll_cryptex_nonce(mobile_image_mounter_client_t client)
566{
567 if (!client) {
568 return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG;
569 }
570 mobile_image_mounter_lock(client);
571
572 plist_t dict = plist_new_dict();
573 plist_dict_set_item(dict, "Command", plist_new_string("RollCryptexNonce"));
574 mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict));
575 plist_free(dict);
576
577 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
578 debug_info("%s: Error sending XML plist to device!", __func__);
579 goto leave_unlock;
580 }
581
582 plist_t result = NULL;
583 res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &result));
584 if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) {
585 debug_info("%s: Error receiving response from device!", __func__);
586 }
587 plist_free(result);
588
589leave_unlock:
590 mobile_image_mounter_unlock(client);
591 return res;
592}