diff options
author | 2024-06-27 11:20:59 +0200 | |
---|---|---|
committer | 2024-06-27 11:20:59 +0200 | |
commit | 68df374762b95ab40ca5242da66e3474360669b5 (patch) | |
tree | a75acdd2a57df58346f02e75577c7dad00b52b83 /src/mobile_image_mounter.c | |
parent | ed0d66d0341562731bb19928dfe48155509fa7a7 (diff) | |
download | libimobiledevice-68df374762b95ab40ca5242da66e3474360669b5.tar.gz libimobiledevice-68df374762b95ab40ca5242da66e3474360669b5.tar.bz2 |
Add support for iOS 17+ Personalized Developer Disk image mounting
Diffstat (limited to 'src/mobile_image_mounter.c')
-rw-r--r-- | src/mobile_image_mounter.c | 274 |
1 files changed, 270 insertions, 4 deletions
diff --git a/src/mobile_image_mounter.c b/src/mobile_image_mounter.c index 5df8e86..6df50c4 100644 --- a/src/mobile_image_mounter.c +++ b/src/mobile_image_mounter.c | |||
@@ -181,7 +181,7 @@ static mobile_image_mounter_error_t process_result(plist_t result, const char *e | |||
181 | return res; | 181 | return res; |
182 | } | 182 | } |
183 | 183 | ||
184 | mobile_image_mounter_error_t mobile_image_mounter_upload_image(mobile_image_mounter_client_t client, const char *image_type, size_t image_size, const char *signature, uint16_t signature_size, mobile_image_mounter_upload_cb_t upload_cb, void* userdata) | 184 | mobile_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 | { | 185 | { |
186 | if (!client || !image_type || (image_size == 0) || !upload_cb) { | 186 | if (!client || !image_type || (image_size == 0) || !upload_cb) { |
187 | return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; | 187 | return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; |
@@ -192,7 +192,7 @@ mobile_image_mounter_error_t mobile_image_mounter_upload_image(mobile_image_moun | |||
192 | plist_t dict = plist_new_dict(); | 192 | plist_t dict = plist_new_dict(); |
193 | plist_dict_set_item(dict, "Command", plist_new_string("ReceiveBytes")); | 193 | plist_dict_set_item(dict, "Command", plist_new_string("ReceiveBytes")); |
194 | if (signature && signature_size != 0) | 194 | if (signature && signature_size != 0) |
195 | plist_dict_set_item(dict, "ImageSignature", plist_new_data(signature, signature_size)); | 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)); | 196 | plist_dict_set_item(dict, "ImageSize", plist_new_uint(image_size)); |
197 | plist_dict_set_item(dict, "ImageType", plist_new_string(image_type)); | 197 | plist_dict_set_item(dict, "ImageType", plist_new_string(image_type)); |
198 | 198 | ||
@@ -241,6 +241,7 @@ mobile_image_mounter_error_t mobile_image_mounter_upload_image(mobile_image_moun | |||
241 | free(buf); | 241 | free(buf); |
242 | if (tx < image_size) { | 242 | if (tx < image_size) { |
243 | debug_info("Error: failed to upload image"); | 243 | debug_info("Error: failed to upload image"); |
244 | res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED; | ||
244 | goto leave_unlock; | 245 | goto leave_unlock; |
245 | } | 246 | } |
246 | debug_info("image uploaded"); | 247 | debug_info("image uploaded"); |
@@ -260,7 +261,7 @@ leave_unlock: | |||
260 | 261 | ||
261 | } | 262 | } |
262 | 263 | ||
263 | mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, const char *image_path, const char *signature, uint16_t signature_size, const char *image_type, plist_t *result) | 264 | mobile_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) |
264 | { | 265 | { |
265 | if (!client || !image_path || !image_type || !result) { | 266 | if (!client || !image_path || !image_type || !result) { |
266 | return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; | 267 | return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; |
@@ -271,8 +272,11 @@ mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mount | |||
271 | plist_dict_set_item(dict, "Command", plist_new_string("MountImage")); | 272 | plist_dict_set_item(dict, "Command", plist_new_string("MountImage")); |
272 | plist_dict_set_item(dict, "ImagePath", plist_new_string(image_path)); | 273 | plist_dict_set_item(dict, "ImagePath", plist_new_string(image_path)); |
273 | if (signature && signature_size != 0) | 274 | if (signature && signature_size != 0) |
274 | plist_dict_set_item(dict, "ImageSignature", plist_new_data(signature, signature_size)); | 275 | plist_dict_set_item(dict, "ImageSignature", plist_new_data((char*)signature, signature_size)); |
275 | plist_dict_set_item(dict, "ImageType", plist_new_string(image_type)); | 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 | } | ||
276 | 280 | ||
277 | 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)); |
278 | plist_free(dict); | 282 | plist_free(dict); |
@@ -292,6 +296,56 @@ leave_unlock: | |||
292 | return res; | 296 | return res; |
293 | } | 297 | } |
294 | 298 | ||
299 | mobile_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) | ||
300 | { | ||
301 | return mobile_image_mounter_mount_image_with_options(client, image_path, signature, signature_size, image_type, NULL, result); | ||
302 | } | ||
303 | |||
304 | mobile_image_mounter_error_t mobile_image_mounter_unmount_image(mobile_image_mounter_client_t client, const char *mount_path) | ||
305 | { | ||
306 | if (!client || !mount_path) { | ||
307 | return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; | ||
308 | } | ||
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 | |||
344 | leave_unlock: | ||
345 | mobile_image_mounter_unlock(client); | ||
346 | return res; | ||
347 | } | ||
348 | |||
295 | mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client) | 349 | mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client) |
296 | { | 350 | { |
297 | if (!client) { | 351 | if (!client) { |
@@ -324,3 +378,215 @@ leave_unlock: | |||
324 | mobile_image_mounter_unlock(client); | 378 | mobile_image_mounter_unlock(client); |
325 | return res; | 379 | return res; |
326 | } | 380 | } |
381 | |||
382 | mobile_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 | |||
404 | leave_unlock: | ||
405 | mobile_image_mounter_unlock(client); | ||
406 | return res; | ||
407 | } | ||
408 | |||
409 | mobile_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 | |||
449 | leave_unlock: | ||
450 | mobile_image_mounter_unlock(client); | ||
451 | return res; | ||
452 | } | ||
453 | |||
454 | mobile_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 | |||
485 | leave_unlock: | ||
486 | mobile_image_mounter_unlock(client); | ||
487 | return res; | ||
488 | } | ||
489 | |||
490 | mobile_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 | |||
531 | leave_unlock: | ||
532 | mobile_image_mounter_unlock(client); | ||
533 | return res; | ||
534 | } | ||
535 | |||
536 | mobile_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 | |||
560 | leave_unlock: | ||
561 | mobile_image_mounter_unlock(client); | ||
562 | return res; | ||
563 | } | ||
564 | |||
565 | mobile_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 | |||
589 | leave_unlock: | ||
590 | mobile_image_mounter_unlock(client); | ||
591 | return res; | ||
592 | } | ||