diff options
-rw-r--r-- | src/common.c | 1 | ||||
-rw-r--r-- | src/ipsw.c | 169 | ||||
-rw-r--r-- | src/ipsw.h | 3 | ||||
-rw-r--r-- | src/restore.c | 62 |
4 files changed, 183 insertions, 52 deletions
diff --git a/src/common.c b/src/common.c index 80d8256..d31c558 100644 --- a/src/common.c +++ b/src/common.c @@ -85,7 +85,6 @@ static thread_once_t init_once = THREAD_ONCE_INIT; static void _log_init(void) { - printf("******** _log_init ********\n"); mutex_init(&log_mutex); } @@ -300,7 +300,7 @@ int ipsw_print_info(const char* path) ipsw_archive_t ipsw_open(const char* ipsw) { int err = 0; - ipsw_archive_t archive = (ipsw_archive_t)malloc(sizeof(struct ipsw_archive)); + ipsw_archive_t archive = (ipsw_archive_t)calloc(1, sizeof(struct ipsw_archive)); if (archive == NULL) { error("ERROR: Out of memory\n"); return NULL; @@ -312,14 +312,15 @@ ipsw_archive_t ipsw_open(const char* ipsw) return NULL; } if (S_ISDIR(fst.st_mode)) { - archive->zip = NULL; + archive->zip = 0; } else { - archive->zip = zip_open(ipsw, 0, &err); - if (archive->zip == NULL) { + struct zip *zip = zip_open(ipsw, 0, &err); + if (zip == NULL) { error("ERROR: zip_open: %s: %d\n", ipsw, err); free(archive); return NULL; } + archive->zip = 1; } archive->path = strdup(ipsw); return (ipsw_archive_t)archive; @@ -329,10 +330,6 @@ void ipsw_close(ipsw_archive_t ipsw) { if (ipsw != NULL) { free(ipsw->path); - if (ipsw->zip) { - zip_unchange_all(ipsw->zip); - zip_close(ipsw->zip); - } free(ipsw); } } @@ -355,18 +352,30 @@ int ipsw_get_file_size(ipsw_archive_t ipsw, const char* infile, uint64_t* size) } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { error("ERROR: zip_name_locate: %s\n", infile); + zip_unchange_all(zip); + zip_close(zip); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { error("ERROR: zip_stat_index: %s\n", infile); + zip_unchange_all(zip); + zip_close(zip); return -1; } + zip_unchange_all(zip); + zip_close(zip); *size = zstat.size; } else { @@ -396,35 +405,52 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, cancel_flag = 0; if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_name_locate: %s\n", infile); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_stat_index: %s\n", infile); return -1; } char* buffer = (char*) malloc(BUFSIZE); if (buffer == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: Unable to allocate memory\n"); return -1; } - struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0); + struct zip_file* zfile = zip_fopen_index(zip, zindex, 0); if (zfile == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_fopen_index: %s\n", infile); return -1; } FILE* fd = fopen(outfile, "wb"); if (fd == NULL) { - error("ERROR: Unable to open output file: %s\n", outfile); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); + error("ERROR: Unable to open output file: %s\n", outfile); return -1; } @@ -439,7 +465,10 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, size = i; count = zip_fread(zfile, buffer, size); if (count < 0) { - error("ERROR: zip_fread: %s\n", infile); + int zep = 0; + int sep = 0; + zip_file_error_get(zfile, &zep, &sep); + error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep); ret = -1; break; } @@ -458,6 +487,8 @@ int ipsw_extract_to_file_with_progress(ipsw_archive_t ipsw, const char* infile, free(buffer); fclose(fd); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); } else { char *filepath = build_path(ipsw->path, infile); char actual_filepath[PATH_MAX+1]; @@ -558,7 +589,15 @@ int ipsw_file_exists(ipsw_archive_t ipsw, const char* infile) } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return 0; + } + int zindex = zip_name_locate(zip, infile, 0); + zip_unchange_all(zip); + zip_close(zip); if (zindex < 0) { return 0; } @@ -584,21 +623,34 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { + zip_unchange_all(zip); + zip_close(zip); debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_stat_index: %s\n", infile); return -1; } - struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0); + struct zip_file* zfile = zip_fopen_index(zip, zindex, 0); if (zfile == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_fopen_index: %s\n", infile); return -1; } @@ -608,19 +660,29 @@ int ipsw_extract_to_memory(ipsw_archive_t ipsw, const char* infile, unsigned cha if (buffer == NULL) { error("ERROR: Out of memory\n"); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); return -1; } - if (zip_fread(zfile, buffer, size) != size) { - error("ERROR: zip_fread: %s\n", infile); - zip_fclose(zfile); + zip_int64_t zr = zip_fread(zfile, buffer, size); + zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); + if (zr < 0) { + int zep = 0; + int sep = 0; + zip_file_error_get(zfile, &zep, &sep); + error("ERROR: zip_fread: %s %d %d\n", infile, zep, sep); + free(buffer); + return -1; + } else if (zr != size) { + error("ERROR: zip_fread: %s got only %lld of %zu\n", infile, zr, size); free(buffer); return -1; } buffer[size] = '\0'; - - zip_fclose(zfile); } else { char *filepath = build_path(ipsw->path, infile); struct stat fst; @@ -691,21 +753,34 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip } if (ipsw->zip) { - int zindex = zip_name_locate(ipsw->zip, infile, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int zindex = zip_name_locate(zip, infile, 0); if (zindex < 0) { + zip_unchange_all(zip); + zip_close(zip); debug("NOTE: zip_name_locate: '%s' not found in archive.\n", infile); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); - if (zip_stat_index(ipsw->zip, zindex, 0, &zstat) != 0) { + if (zip_stat_index(zip, zindex, 0, &zstat) != 0) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_stat_index: %s\n", infile); return -1; } - struct zip_file* zfile = zip_fopen_index(ipsw->zip, zindex, 0); + struct zip_file* zfile = zip_fopen_index(zip, zindex, 0); if (zfile == NULL) { + zip_unchange_all(zip); + zip_close(zip); error("ERROR: zip_fopen_index: %s\n", infile); return -1; } @@ -713,8 +788,10 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip total_size = zstat.size; buffer = (unsigned char*) malloc(blocksize); if (buffer == NULL) { - error("ERROR: Out of memory\n"); zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); + error("ERROR: Out of memory\n"); return -1; } @@ -736,6 +813,9 @@ int ipsw_extract_send(ipsw_archive_t ipsw, const char* infile, int blocksize, ip done += zr; } free(buffer); + zip_fclose(zfile); + zip_unchange_all(zip); + zip_close(zip); } else { char *filepath = build_path(ipsw->path, infile); struct stat fst; @@ -918,7 +998,14 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx) } if (ipsw->zip) { - int64_t entries = zip_get_num_entries(ipsw->zip, 0); + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return -1; + } + + int64_t entries = zip_get_num_entries(zip, 0); if (entries < 0) { error("ERROR: zip_get_num_entries failed\n"); return -1; @@ -928,7 +1015,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx) zip_stat_t stat; zip_stat_init(&stat); - if (zip_stat_index(ipsw->zip, index, 0, &stat) < 0) { + if (zip_stat_index(zip, index, 0, &stat) < 0) { error("ERROR: zip_stat_index failed for %s\n", stat.name); ret = -1; continue; @@ -936,7 +1023,7 @@ int ipsw_list_contents(ipsw_archive_t ipsw, ipsw_list_cb cb, void *ctx) uint8_t opsys; uint32_t attributes; - if (zip_file_get_external_attributes(ipsw->zip, index, 0, &opsys, &attributes) < 0) { + if (zip_file_get_external_attributes(zip, index, 0, &opsys, &attributes) < 0) { error("ERROR: zip_file_get_external_attributes failed for %s\n", stat.name); ret = -1; continue; @@ -1300,23 +1387,35 @@ ipsw_file_handle_t ipsw_file_open(ipsw_archive_t ipsw, const char* path) { ipsw_file_handle_t handle = (ipsw_file_handle_t)calloc(1, sizeof(struct ipsw_file_handle)); if (ipsw->zip) { + int err = 0; + struct zip *zip = zip_open(ipsw->path, 0, &err); + if (zip == NULL) { + error("ERROR: zip_open: %s: %d\n", ipsw->path, err); + return NULL; + } + zip_stat_t zst; - zip_int64_t zindex = zip_name_locate(ipsw->zip, path, 0); + zip_int64_t zindex = zip_name_locate(zip, path, 0); if (zindex < 0) { error("ERROR: zip_name_locate: %s not found\n", path); + zip_unchange_all(zip); + zip_close(zip); free(handle); return NULL; } - handle->zfile = zip_fopen_index(ipsw->zip, zindex, 0); + handle->zfile = zip_fopen_index(zip, zindex, 0); if (handle->zfile == NULL) { error("ERROR: zip_fopen_index: %s could not be opened\n", path); + zip_unchange_all(zip); + zip_close(zip); free(handle); return NULL; } zip_stat_init(&zst); - zip_stat(ipsw->zip, path, 0, &zst); + zip_stat(zip, path, 0, &zst); handle->size = zst.size; handle->seekable = (zst.comp_method == ZIP_CM_STORE); + handle->zip = zip; } else { struct stat st; char *filepath = build_path(ipsw->path, path); @@ -1338,6 +1437,8 @@ void ipsw_file_close(ipsw_file_handle_t handle) { if (handle && handle->zfile) { zip_fclose(handle->zfile); + zip_unchange_all(handle->zip); + zip_close(handle->zip); } else if (handle && handle->file) { fclose(handle->file); } @@ -33,7 +33,7 @@ extern "C" { #include <sys/stat.h> struct ipsw_archive { - struct zip* zip; + int zip; char *path; }; typedef struct ipsw_archive* ipsw_archive_t; @@ -48,6 +48,7 @@ typedef int (*ipsw_send_cb)(void *ctx, void *data, size_t size, size_t done, siz struct ipsw_file_handle { FILE* file; + struct zip* zip; struct zip_file* zfile; uint64_t size; int seekable; diff --git a/src/restore.c b/src/restore.c index a62886d..d3828f9 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1235,7 +1235,7 @@ static size_t _curl_header_callback(char* buffer, size_t size, size_t nitems, vo key[i] = '\0'; i++; while (i < len && buffer[i] == ' ' || buffer[i] == '\t') i++; - val = malloc(len-i); + val = malloc(len-i+1); strncpy(val, buffer+i, len-i); val[len-i] = '\0'; break; @@ -2687,7 +2687,7 @@ static plist_t restore_get_se_firmware_data(struct idevicerestore_client_t* clie return response; } -static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t* client, plist_t p_info) +static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = NULL; char *comp_path = NULL; @@ -2704,6 +2704,12 @@ static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t* return NULL; } + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Savage request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2720,7 +2726,7 @@ static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t* plist_dict_merge(¶meters, p_info); /* add required tags for Savage TSS request */ - tss_request_add_savage_tags(request, parameters, NULL, &comp_name); + tss_request_add_savage_tags(request, parameters, device_generated_request, &comp_name); plist_free(parameters); @@ -2783,7 +2789,7 @@ static plist_t restore_get_savage_firmware_data(struct idevicerestore_client_t* return response; } -static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t* client, plist_t p_info) +static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = NULL; char *comp_path = NULL; @@ -2799,6 +2805,12 @@ static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t* return NULL; } + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Yonkers request */ request = tss_request_new(NULL); if (request == NULL) { @@ -2817,7 +2829,7 @@ static plist_t restore_get_yonkers_firmware_data(struct idevicerestore_client_t* plist_dict_merge(¶meters, p_info); /* add required tags for Yonkers TSS request */ - tss_request_add_yonkers_tags(request, parameters, NULL, &comp_name); + tss_request_add_yonkers_tags(request, parameters, device_generated_request, &comp_name); plist_free(parameters); @@ -3024,7 +3036,7 @@ static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* cl return response; } -static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t* client, plist_t p_info) +static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = "BMU,FirmwareMap"; char *comp_path = NULL; @@ -3040,6 +3052,12 @@ static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t return NULL; } + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Veridian request */ request = tss_request_new(NULL); if (request == NULL) { @@ -3057,7 +3075,7 @@ static plist_t restore_get_veridian_firmware_data(struct idevicerestore_client_t plist_dict_merge(¶meters, p_info); /* add required tags for Veridian TSS request */ - tss_request_add_veridian_tags(request, parameters, NULL); + tss_request_add_veridian_tags(request, parameters, device_generated_request); plist_free(parameters); @@ -3180,7 +3198,7 @@ static plist_t restore_get_generic_firmware_data(struct idevicerestore_client_t* return response; } -static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* client, plist_t p_info) +static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char *comp_name = "Baobab,TCON"; char *comp_path = NULL; @@ -3196,6 +3214,12 @@ static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* cl return NULL; } + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Baobab request */ request = tss_request_new(NULL); if (request == NULL) { @@ -3213,7 +3237,7 @@ static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* cl plist_dict_merge(¶meters, p_info); /* add required tags for Baobab TSS request */ - tss_request_add_tcon_tags(request, parameters, NULL); + tss_request_add_tcon_tags(request, parameters, device_generated_request); plist_free(parameters); @@ -3254,7 +3278,7 @@ static plist_t restore_get_tcon_firmware_data(struct idevicerestore_client_t* cl return response; } -static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* client, plist_t p_info) +static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments) { char comp_name[64]; char *comp_path = NULL; @@ -3275,6 +3299,12 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c return NULL; } + plist_t device_generated_request = plist_dict_get_item(arguments, "DeviceGeneratedRequest"); + if (device_generated_request && !PLIST_IS_DICT(device_generated_request)) { + error("ERROR: %s: DeviceGeneratedRequest has invalid type!\n", __func__); + return NULL; + } + /* create Timer request */ request = tss_request_new(NULL); if (request == NULL) { @@ -3345,7 +3375,7 @@ static plist_t restore_get_timer_firmware_data(struct idevicerestore_client_t* c } /* add required tags for Timer TSS request */ - tss_request_add_timer_tags(request, parameters, NULL); + tss_request_add_timer_tags(request, parameters, device_generated_request); plist_free(parameters); @@ -3642,9 +3672,9 @@ static int restore_send_firmware_updater_data(struct idevicerestore_client_t* cl plist_t p_info2 = plist_dict_get_item(p_info, "YonkersDeviceInfo"); if (p_info2 && plist_get_node_type(p_info2) == PLIST_DICT) { fwtype = "Yonkers"; - fwdict = restore_get_yonkers_firmware_data(client, p_info2); + fwdict = restore_get_yonkers_firmware_data(client, p_info2, arguments); } else { - fwdict = restore_get_savage_firmware_data(client, p_info); + fwdict = restore_get_savage_firmware_data(client, p_info, arguments); } if (fwdict == NULL) { error("ERROR: %s: Couldn't get %s firmware data\n", __func__, fwtype); @@ -3657,13 +3687,13 @@ static int restore_send_firmware_updater_data(struct idevicerestore_client_t* cl goto error_out; } } else if (strcmp(s_updater_name, "T200") == 0) { - fwdict = restore_get_veridian_firmware_data(client, p_info); + fwdict = restore_get_veridian_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get Veridian firmware data\n", __func__); goto error_out; } } else if (strcmp(s_updater_name, "AppleTCON") == 0) { - fwdict = restore_get_tcon_firmware_data(client, p_info); + fwdict = restore_get_tcon_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get AppleTCON firmware data\n", __func__); goto error_out; @@ -3675,7 +3705,7 @@ static int restore_send_firmware_updater_data(struct idevicerestore_client_t* cl goto error_out; } } else if (strcmp(s_updater_name, "AppleTypeCRetimer") == 0) { - fwdict = restore_get_timer_firmware_data(client, p_info); + fwdict = restore_get_timer_firmware_data(client, p_info, arguments); if (fwdict == NULL) { error("ERROR: %s: Couldn't get AppleTypeCRetimer firmware data\n", __func__); goto error_out; |