diff options
| author | 2010-06-04 17:11:36 +0200 | |
|---|---|---|
| committer | 2010-06-04 17:11:36 +0200 | |
| commit | e528494384b9a670a6bfd630524665657aae9311 (patch) | |
| tree | cf0385328ce266e5525656896dc6fb6a68d9f4fa /tools/idevicebackup.c | |
| parent | 2169750afea6e8a50da249a1def1112b95d3003e (diff) | |
| download | libimobiledevice-e528494384b9a670a6bfd630524665657aae9311.tar.gz libimobiledevice-e528494384b9a670a6bfd630524665657aae9311.tar.bz2 | |
idevicebackup: read and verify manifest.plist when restoring
Diffstat (limited to 'tools/idevicebackup.c')
| -rw-r--r-- | tools/idevicebackup.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c index 2018bc6..15b8d05 100644 --- a/tools/idevicebackup.c +++ b/tools/idevicebackup.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | #include <signal.h> | 27 | #include <signal.h> |
| 28 | #include <glib.h> | 28 | #include <glib.h> |
| 29 | #include <gcrypt.h> | ||
| 29 | 30 | ||
| 30 | #include <libimobiledevice/libimobiledevice.h> | 31 | #include <libimobiledevice/libimobiledevice.h> |
| 31 | #include <libimobiledevice/lockdown.h> | 32 | #include <libimobiledevice/lockdown.h> |
| @@ -59,6 +60,23 @@ enum device_link_file_status_t { | |||
| 59 | DEVICE_LINK_FILE_STATUS_LAST_HUNK | 60 | DEVICE_LINK_FILE_STATUS_LAST_HUNK |
| 60 | }; | 61 | }; |
| 61 | 62 | ||
| 63 | static void sha1_of_data(const char *input, uint32_t size, unsigned char *hash_out) | ||
| 64 | { | ||
| 65 | gcry_md_hash_buffer(GCRY_MD_SHA1, hash_out, input, size); | ||
| 66 | } | ||
| 67 | |||
| 68 | static int compare_hash(const unsigned char *hash1, const unsigned char *hash2, int hash_len) | ||
| 69 | { | ||
| 70 | int i; | ||
| 71 | for (i = 0; i < hash_len; i++) { | ||
| 72 | if (hash1[i] != hash2[i]) { | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | return 1; | ||
| 77 | } | ||
| 78 | |||
| 79 | |||
| 62 | static void notify_cb(const char *notification, void *userdata) | 80 | static void notify_cb(const char *notification, void *userdata) |
| 63 | { | 81 | { |
| 64 | if (!strcmp(notification, NP_SYNC_CANCEL_REQUEST)) { | 82 | if (!strcmp(notification, NP_SYNC_CANCEL_REQUEST)) { |
| @@ -913,6 +931,58 @@ int main(int argc, char *argv[]) | |||
| 913 | break; | 931 | break; |
| 914 | } | 932 | } |
| 915 | /* now make sure backup integrity is ok! verify all files */ | 933 | /* now make sure backup integrity is ok! verify all files */ |
| 934 | printf("Reading existing Manifest.\n"); | ||
| 935 | plist_read_from_filename(&manifest_plist, manifest_path); | ||
| 936 | if (!manifest_plist) { | ||
| 937 | printf("Could not read Manifest.plist. Aborting.\n"); | ||
| 938 | break; | ||
| 939 | } | ||
| 940 | |||
| 941 | printf("Verifying backup integrity, please wait.\n"); | ||
| 942 | char *bin = NULL; | ||
| 943 | uint64_t binsize = 0; | ||
| 944 | node = plist_dict_get_item(manifest_plist, "Data"); | ||
| 945 | if (!node || (plist_get_node_type(node) != PLIST_DATA)) { | ||
| 946 | printf("Could not read Data key from Manifest.plist!\n"); | ||
| 947 | break; | ||
| 948 | } | ||
| 949 | plist_get_data_val(node, &bin, &binsize); | ||
| 950 | plist_t backup_data = NULL; | ||
| 951 | if (bin) { | ||
| 952 | char *auth_ver = NULL; | ||
| 953 | unsigned char *auth_sig = NULL; | ||
| 954 | uint64_t auth_sig_len = 0; | ||
| 955 | /* verify AuthSignature */ | ||
| 956 | node = plist_dict_get_item(manifest_plist, "AuthVersion"); | ||
| 957 | plist_get_string_val(node, &auth_ver); | ||
| 958 | if (auth_ver && (strcmp(auth_ver, "2.0") == 0)) { | ||
| 959 | node = plist_dict_get_item(manifest_plist, "AuthSignature"); | ||
| 960 | if (node && (plist_get_node_type(node) == PLIST_DATA)) { | ||
| 961 | plist_get_data_val(node, (char**)&auth_sig, &auth_sig_len); | ||
| 962 | } | ||
| 963 | if (auth_sig && (auth_sig_len == 20)) { | ||
| 964 | /* calculate the sha1, then compare */ | ||
| 965 | unsigned char data_sha1[20]; | ||
| 966 | sha1_of_data(bin, binsize, data_sha1); | ||
| 967 | if (compare_hash(auth_sig, data_sha1, 20)) { | ||
| 968 | printf("AuthSignature is valid\n"); | ||
| 969 | } else { | ||
| 970 | printf("ERROR: AuthSignature is NOT VALID\n"); | ||
| 971 | } | ||
| 972 | } else { | ||
| 973 | printf("Could not get AuthSignature from manifest!\n"); | ||
| 974 | } | ||
| 975 | g_free(auth_sig); | ||
| 976 | } else if (auth_ver) { | ||
| 977 | printf("Unknown AuthVersion '%s', cannot verify AuthSignature\n", auth_ver); | ||
| 978 | } | ||
| 979 | plist_from_bin(bin, (uint32_t)binsize, &backup_data); | ||
| 980 | g_free(bin); | ||
| 981 | } | ||
| 982 | if (!backup_data) { | ||
| 983 | printf("Could not read plist from Manifest.plist Data key!\n"); | ||
| 984 | break; | ||
| 985 | } | ||
| 916 | /* loop over Files entries in Manifest data plist */ | 986 | /* loop over Files entries in Manifest data plist */ |
| 917 | /* make sure both .mddata/.mdinfo files are available for each entry */ | 987 | /* make sure both .mddata/.mdinfo files are available for each entry */ |
| 918 | /* request restore from device with manifest (BackupMessageRestoreMigrate) */ | 988 | /* request restore from device with manifest (BackupMessageRestoreMigrate) */ |
