libimobiledevice / libimobiledevice

A cross-platform protocol library to communicate with iOS devices
https://libimobiledevice.org
GNU Lesser General Public License v2.1
6.67k stars 1.33k forks source link

[BUG] idevicebackup2 fails with iPhone XS/XS Max (new UDID) #711

Closed Blefish closed 6 years ago

Blefish commented 6 years ago

The problem comes because mobilebackup2 TargetIdentifier/SourceIdentifier is set up according to USB serial no (which is without dash "-"). The device's UniqueDeviceID is with the dash.

If I manually modify it to give the correct TargetIdentifier/SourceIdentifier (with dash), it works.

Seems like a headache to fix though, maybe there are other places affected by this as well?

https://github.com/libimobiledevice/libimobiledevice/blob/master/src/mobilebackup2.c#L332 https://github.com/libimobiledevice/libimobiledevice/blob/master/src/mobilebackup2.c#L334

Blefish commented 6 years ago

After https://github.com/libimobiledevice/usbmuxd/commit/f838cf6dc212c779562984e8a16a4cedfc1d6daf + my patch it works.

nikias commented 6 years ago

Wait. Now it WANTS it with hyphen/dash, is that correct? Just deleted my previous comment because apparently I didn't get it right. What extra patch are you talking about?

Blefish commented 6 years ago

Yeah, idevicebackup2 requires the hyphen. If you check my link you will see my fix for your commit and that allowed it to work.

Apparently the usb serial number sent is still 40 chars, it's only 24 + 0 for the rest

dnsBlah commented 6 years ago

Yeah, idevicebackup2 requires the hyphen. If you check my link you will see my fix for your commit and that allowed it to work.

Apparently the usb serial number sent is still 40 chars, it's only 24 + 0 for the rest

That's indeed correct. I'm using these libraries in cooperation with my own usb hook. I'm trimming the identifier on alphanumeric only, and add the - if the characters end up being 24.

kamstrup commented 6 years ago

I have this issue as well. idevicebackup2 is just stuck in a loop waiting for the device to become "ready":

$ idevicebackup2 backup  foo
Backup directory is "foo"
Started "com.apple.mobilebackup2" service on port 52643.
Negotiated Protocol Version 2.1
Reading Info.plist from backup.
Starting backup...
Backup will be unencrypted.
Requesting backup from device...
Incremental backup mode.
Device is not ready yet. Going to try again in 2 seconds...
Device is not ready yet. Going to try again in 2 seconds...
Device is not ready yet. Going to try again in 2 seconds...
Device is not ready yet. Going to try again in 2 seconds...
....

I can confirm that this ugly patch makes stuff work (not suitable for merging of course!):

diff --git a/src/mobilebackup2.c b/src/mobilebackup2.c
index 08ce22b..6f2286e 100644
--- a/src/mobilebackup2.c
+++ b/src/mobilebackup2.c
@@ -19,7 +19,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */

+#define _GNU_SOURCE
+
 #include <plist/plist.h>
+#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>

@@ -329,9 +332,12 @@ LIBIMOBILEDEVICE_API mobilebackup2_error_t mobilebackup2_send_request(mobileback
                return MOBILEBACKUP2_E_INVALID_ARG;

        plist_t dict = plist_new_dict();
-       plist_dict_set_item(dict, "TargetIdentifier", plist_new_string(target_identifier));
+  char* xxx = NULL;
+  asprintf(&xxx, "%.8s-%s", target_identifier, target_identifier+8);
+       plist_dict_set_item(dict, "TargetIdentifier", plist_new_string(xxx));
        if (source_identifier) {
-               plist_dict_set_item(dict, "SourceIdentifier", plist_new_string(source_identifier));
+    asprintf(&xxx, "%.8s-%s", source_identifier, source_identifier+8);
+               plist_dict_set_item(dict, "SourceIdentifier", plist_new_string(xxx));
        }
        if (options) {
                plist_dict_set_item(dict, "Options", plist_copy(options));
kamstrup commented 6 years ago

Well, "working" in relation to my previous comment should be taken with a grain of salt...

Seems there is some confusion about when to use dashes, and when not to, in the UDID in the file paths in the backup.

Blefish commented 6 years ago

I suspect the TargetIdentifier is what the phone is using to detect if it should be restored to that device. Anyway, this is not an issue when the - is added from usbmuxd. The problem is that the current dash patch for usbmuxd is not working for me in Linux, hence I submitted a quick fix (on Linux at least).

nikias commented 6 years ago

@Blefish can you try this fix? I think it's more elegant than adding the 0 byte and then breaking and changing the di == 24 check to di == 25 IMO.

diff --git a/src/usb.c b/src/usb.c
index 44c33ce..b659d90 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -274,6 +274,8 @@ static void get_serial_callback(struct libusb_transfer *transfer)
        for (di = 0, si = 2; si < data[0] && di < sizeof(usbdev->serial)-1; si += 2) {
                if ((data[si] & 0x80) || (data[si + 1])) /* non-ASCII */
                        usbdev->serial[di++] = '?';
+               else if (data[si] == '\0')
+                       break;
                else
                        usbdev->serial[di++] = data[si];
        }
Blefish commented 6 years ago

Hey, I'll give it a go.

I hate my patch already as well, too many changes for little win :D.

Will report back

nikias commented 6 years ago

thanks. I don't have a matching device, so I can't test it myself.

Blefish commented 6 years ago

Confirmed working, idevice_id -l shows the devices with hyphen and idevicebackup2 also works fine.

kamstrup commented 6 years ago

I am working on a branch here that seems to be working... It's a bit tricky with all the UDID mapping though, so no guarantees! :-) https://github.com/kamstrup/libimobiledevice/tree/backup2-xs-fixes Will test a bit more before I send a PR

kamstrup commented 6 years ago

Oh, didn't see your conversation before now. Happy if my branch is unneeded! It's kinda ugly ;-) Will check later.

nikias commented 6 years ago

@kamstrup hey hi :) yeah it should be fine now.

nikias commented 6 years ago

@Blefish pushed: https://github.com/libimobiledevice/usbmuxd/commit/1cc8b343a4bc9320758c78e187b13bb3c9029f12

kamstrup commented 6 years ago

I can create the backup without issues using the new usbmuxd, but when restoring I get an error:

Sending '00008020-001D099A1108002E/92/923565845ab590c7d7fa8b6547b93748887497ab' (117 Bytes)
Sending '00008020-001D099A1108002E/77/77e6b5a266733afee2b161f9ec40f2164639ab21' (301 Bytes)
[==================================================] 100% Finished
ErrorCode 102: Error moving incomplete restore directory into place at path "/var/.backup.i" (MBErrorDomain/102). Underlying error: “.backup.i” couldn’t be moved to “var” because an item with the same name already exists. at path "/var/.backup.i" (NSCocoaErrorDomain/516). Underlying error: The operation couldn’t be completed. File exists (NSPOSIXErrorDomain/17)..
Restore Failed (Error Code 102).
kamstrup commented 6 years ago

The suspicion dawned on me that it might be artifacts from a bugged restoration attempt on an earlier codebase. After factory resetting the device I can now restore! <3

kamstrup commented 6 years ago

No, wait. I can't restore the same backup again once it succeeded the first time. I get the same error. If I create a new backup and try to restore that I also get the error. It seems like restoring backups leave a file in /var/.backup.i on the device that must not be there...