summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/idevicebackup2.c115
1 files changed, 39 insertions, 76 deletions
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index 0a06f3f..7256ee9 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -472,67 +472,6 @@ static int mb2_status_check_snapshot_state(const char *path, const char *udid, c
472 return ret; 472 return ret;
473} 473}
474 474
475static int mobilebackup_info_is_current_device(plist_t info)
476{
477 plist_t value_node = NULL;
478 plist_t node = NULL;
479 plist_t root_node = NULL;
480 int ret = 0;
481
482 if (!info)
483 return ret;
484
485 if (plist_get_node_type(info) != PLIST_DICT)
486 return ret;
487
488 /* get basic device information in one go */
489 lockdownd_get_value(client, NULL, NULL, &root_node);
490
491 /* verify UDID */
492 value_node = plist_dict_get_item(root_node, "UniqueDeviceID");
493 node = plist_dict_get_item(info, "Target Identifier");
494
495 if(plist_compare_node_value(value_node, node))
496 ret = 1;
497 else {
498 printf("Info.plist: UniqueDeviceID does not match.\n");
499 }
500
501 /* verify SerialNumber */
502 if (ret == 1) {
503 value_node = plist_dict_get_item(root_node, "SerialNumber");
504 node = plist_dict_get_item(info, "Serial Number");
505
506 if(plist_compare_node_value(value_node, node))
507 ret = 1;
508 else {
509 printf("Info.plist: SerialNumber does not match.\n");
510 ret = 0;
511 }
512 }
513
514 /* verify ProductVersion to prevent using backup with different OS version */
515 if (ret == 1) {
516 value_node = plist_dict_get_item(root_node, "ProductVersion");
517 node = plist_dict_get_item(info, "Product Version");
518
519 if(plist_compare_node_value(value_node, node))
520 ret = 1;
521 else {
522 printf("Info.plist: ProductVersion does not match.\n");
523 ret = 0;
524 }
525 }
526
527 plist_free(root_node);
528 root_node = NULL;
529
530 value_node = NULL;
531 node = NULL;
532
533 return ret;
534}
535
536static void do_post_notification(const char *notification) 475static void do_post_notification(const char *notification)
537{ 476{
538 uint16_t nport = 0; 477 uint16_t nport = 0;
@@ -1186,6 +1125,7 @@ static void print_usage(int argc, char **argv)
1186 printf("options:\n"); 1125 printf("options:\n");
1187 printf(" -d, --debug\t\tenable communication debugging\n"); 1126 printf(" -d, --debug\t\tenable communication debugging\n");
1188 printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); 1127 printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n");
1128 printf(" -s, --source UDID\tuse backup data from device specified by UDID\n");
1189 printf(" -h, --help\t\tprints usage information\n"); 1129 printf(" -h, --help\t\tprints usage information\n");
1190 printf("\n"); 1130 printf("\n");
1191} 1131}
@@ -1195,6 +1135,7 @@ int main(int argc, char *argv[])
1195 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; 1135 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
1196 int i; 1136 int i;
1197 char* udid = NULL; 1137 char* udid = NULL;
1138 char* source_udid = NULL;
1198 uint16_t port = 0; 1139 uint16_t port = 0;
1199 int cmd = -1; 1140 int cmd = -1;
1200 int cmd_flags = 0; 1141 int cmd_flags = 0;
@@ -1229,6 +1170,15 @@ int main(int argc, char *argv[])
1229 udid = strdup(argv[i]); 1170 udid = strdup(argv[i]);
1230 continue; 1171 continue;
1231 } 1172 }
1173 else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--source")) {
1174 i++;
1175 if (!argv[i] || (strlen(argv[i]) != 40)) {
1176 print_usage(argc, argv);
1177 return 0;
1178 }
1179 source_udid = strdup(argv[i]);
1180 continue;
1181 }
1232 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 1182 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
1233 print_usage(argc, argv); 1183 print_usage(argc, argv);
1234 return 0; 1184 return 0;
@@ -1307,12 +1257,16 @@ int main(int argc, char *argv[])
1307 idevice_get_udid(device, &udid); 1257 idevice_get_udid(device, &udid);
1308 } 1258 }
1309 1259
1260 if (!source_udid) {
1261 source_udid = strdup(udid);
1262 }
1263
1310 /* backup directory must contain an Info.plist */ 1264 /* backup directory must contain an Info.plist */
1311 char *info_path = build_path(backup_directory, udid, "Info.plist", NULL); 1265 char *info_path = build_path(backup_directory, source_udid, "Info.plist", NULL);
1312 if (cmd == CMD_RESTORE) { 1266 if (cmd == CMD_RESTORE) {
1313 if (stat(info_path, &st) != 0) { 1267 if (stat(info_path, &st) != 0) {
1314 free(info_path); 1268 free(info_path);
1315 printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found for UDID %s.\n", backup_directory, udid); 1269 printf("ERROR: Backup directory \"%s\" is invalid. No Info.plist found for UDID %s.\n", backup_directory, source_udid);
1316 return -1; 1270 return -1;
1317 } 1271 }
1318 } 1272 }
@@ -1387,12 +1341,6 @@ int main(int argc, char *argv[])
1387 printf("Could not read Info.plist\n"); 1341 printf("Could not read Info.plist\n");
1388 is_full_backup = 1; 1342 is_full_backup = 1;
1389 } 1343 }
1390 if (info_plist && ((cmd == CMD_BACKUP) || (cmd == CMD_RESTORE))) {
1391 if (!mobilebackup_info_is_current_device(info_plist)) {
1392 printf("Aborting. Backup data is not compatible with the current device.\n");
1393 cmd = CMD_LEAVE;
1394 }
1395 }
1396 } else { 1344 } else {
1397 if (cmd == CMD_RESTORE) { 1345 if (cmd == CMD_RESTORE) {
1398 printf("Aborting restore. Info.plist is missing.\n"); 1346 printf("Aborting restore. Info.plist is missing.\n");
@@ -1440,10 +1388,22 @@ checkpoint:
1440 PRINT_VERBOSE(1, "Starting backup...\n"); 1388 PRINT_VERBOSE(1, "Starting backup...\n");
1441 1389
1442 /* make sure backup device sub-directory exists */ 1390 /* make sure backup device sub-directory exists */
1443 char *devbackupdir = build_path(backup_directory, udid, NULL); 1391 char* devbackupdir = build_path(backup_directory, source_udid, NULL);
1444 __mkdir(devbackupdir, 0755); 1392 __mkdir(devbackupdir, 0755);
1445 free(devbackupdir); 1393 free(devbackupdir);
1446 1394
1395 if (strcmp(source_udid, udid) != 0) {
1396 /* handle different source backup directory */
1397 // make sure target backup device sub-directory exists
1398 devbackupdir = build_path(backup_directory, udid, NULL);
1399 __mkdir(devbackupdir, 0755);
1400 free(devbackupdir);
1401
1402 // use Info.plist path in target backup folder */
1403 free(info_path);
1404 info_path = build_path(backup_directory, udid, "Info.plist", NULL);
1405 }
1406
1447 /* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */ 1407 /* TODO: check domain com.apple.mobile.backup key RequiresEncrypt and WillEncrypt with lockdown */
1448 /* TODO: verify battery on AC enough battery remaining */ 1408 /* TODO: verify battery on AC enough battery remaining */
1449 1409
@@ -1463,7 +1423,7 @@ checkpoint:
1463 /* request backup from device with manifest from last backup */ 1423 /* request backup from device with manifest from last backup */
1464 PRINT_VERBOSE(1, "Requesting backup from device...\n"); 1424 PRINT_VERBOSE(1, "Requesting backup from device...\n");
1465 1425
1466 err = mobilebackup2_send_request(mobilebackup2, "Backup", udid, NULL, NULL); 1426 err = mobilebackup2_send_request(mobilebackup2, "Backup", udid, source_udid, NULL);
1467 if (err == MOBILEBACKUP2_E_SUCCESS) { 1427 if (err == MOBILEBACKUP2_E_SUCCESS) {
1468 if (is_full_backup) { 1428 if (is_full_backup) {
1469 PRINT_VERBOSE(1, "Full backup mode.\n"); 1429 PRINT_VERBOSE(1, "Full backup mode.\n");
@@ -1485,7 +1445,7 @@ checkpoint:
1485 /* TODO: verify battery on AC enough battery remaining */ 1445 /* TODO: verify battery on AC enough battery remaining */
1486 1446
1487 /* verify if Status.plist says we read from an successful backup */ 1447 /* verify if Status.plist says we read from an successful backup */
1488 if (!mb2_status_check_snapshot_state(backup_directory, udid, "finished")) { 1448 if (!mb2_status_check_snapshot_state(backup_directory, source_udid, "finished")) {
1489 printf("ERROR: Cannot ensure we restore from a successful backup. Aborting.\n"); 1449 printf("ERROR: Cannot ensure we restore from a successful backup. Aborting.\n");
1490 cmd = CMD_LEAVE; 1450 cmd = CMD_LEAVE;
1491 break; 1451 break;
@@ -1505,7 +1465,7 @@ checkpoint:
1505 plist_dict_insert_item(opts, "RestorePreserveSettings", plist_new_bool((cmd_flags & CMD_FLAG_RESTORE_SETTINGS) == 0)); 1465 plist_dict_insert_item(opts, "RestorePreserveSettings", plist_new_bool((cmd_flags & CMD_FLAG_RESTORE_SETTINGS) == 0));
1506 PRINT_VERBOSE(1, "Preserve settings of device: %s\n", ((cmd_flags & CMD_FLAG_RESTORE_SETTINGS) == 0 ? "Yes":"No")); 1466 PRINT_VERBOSE(1, "Preserve settings of device: %s\n", ((cmd_flags & CMD_FLAG_RESTORE_SETTINGS) == 0 ? "Yes":"No"));
1507 1467
1508 err = mobilebackup2_send_request(mobilebackup2, "Restore", udid, udid, opts); 1468 err = mobilebackup2_send_request(mobilebackup2, "Restore", udid, source_udid, opts);
1509 plist_free(opts); 1469 plist_free(opts);
1510 if (err != MOBILEBACKUP2_E_SUCCESS) { 1470 if (err != MOBILEBACKUP2_E_SUCCESS) {
1511 if (err == MOBILEBACKUP2_E_BAD_VERSION) { 1471 if (err == MOBILEBACKUP2_E_BAD_VERSION) {
@@ -1520,7 +1480,7 @@ checkpoint:
1520 break; 1480 break;
1521 case CMD_INFO: 1481 case CMD_INFO:
1522 PRINT_VERBOSE(1, "Requesting backup info from device...\n"); 1482 PRINT_VERBOSE(1, "Requesting backup info from device...\n");
1523 err = mobilebackup2_send_request(mobilebackup2, "Info", udid, NULL, NULL); 1483 err = mobilebackup2_send_request(mobilebackup2, "Info", udid, source_udid, NULL);
1524 if (err != MOBILEBACKUP2_E_SUCCESS) { 1484 if (err != MOBILEBACKUP2_E_SUCCESS) {
1525 printf("Error requesting backup info from device, error code %d\n", err); 1485 printf("Error requesting backup info from device, error code %d\n", err);
1526 cmd = CMD_LEAVE; 1486 cmd = CMD_LEAVE;
@@ -1528,7 +1488,7 @@ checkpoint:
1528 break; 1488 break;
1529 case CMD_LIST: 1489 case CMD_LIST:
1530 PRINT_VERBOSE(1, "Requesting backup list from device...\n"); 1490 PRINT_VERBOSE(1, "Requesting backup list from device...\n");
1531 err = mobilebackup2_send_request(mobilebackup2, "List", udid, NULL, NULL); 1491 err = mobilebackup2_send_request(mobilebackup2, "List", udid, source_udid, NULL);
1532 if (err != MOBILEBACKUP2_E_SUCCESS) { 1492 if (err != MOBILEBACKUP2_E_SUCCESS) {
1533 printf("Error requesting backup list from device, error code %d\n", err); 1493 printf("Error requesting backup list from device, error code %d\n", err);
1534 cmd = CMD_LEAVE; 1494 cmd = CMD_LEAVE;
@@ -1536,7 +1496,7 @@ checkpoint:
1536 break; 1496 break;
1537 case CMD_UNBACK: 1497 case CMD_UNBACK:
1538 PRINT_VERBOSE(1, "Starting to unpack backup...\n"); 1498 PRINT_VERBOSE(1, "Starting to unpack backup...\n");
1539 err = mobilebackup2_send_request(mobilebackup2, "Unback", udid, NULL, NULL); 1499 err = mobilebackup2_send_request(mobilebackup2, "Unback", udid, source_udid, NULL);
1540 if (err != MOBILEBACKUP2_E_SUCCESS) { 1500 if (err != MOBILEBACKUP2_E_SUCCESS) {
1541 printf("Error requesting unback operation from device, error code %d\n", err); 1501 printf("Error requesting unback operation from device, error code %d\n", err);
1542 cmd = CMD_LEAVE; 1502 cmd = CMD_LEAVE;
@@ -1889,6 +1849,9 @@ files_out:
1889 if (udid) { 1849 if (udid) {
1890 free(udid); 1850 free(udid);
1891 } 1851 }
1852 if (source_udid) {
1853 free(source_udid);
1854 }
1892 1855
1893 return 0; 1856 return 0;
1894} 1857}