summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md223
-rw-r--r--src/asr.c15
-rw-r--r--src/asr.h4
-rw-r--r--src/common.c35
-rw-r--r--src/common.h1
-rw-r--r--src/idevicerestore.c5
-rw-r--r--src/restore.c1027
-rw-r--r--src/restore.h17
8 files changed, 1098 insertions, 229 deletions
diff --git a/README.md b/README.md
index 3b52567..1af2d93 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,21 @@
![](https://github.com/libimobiledevice/idevicerestore/actions/workflows/build.yml/badge.svg)
+## Table of Contents
+- [Features](#features)
+- [Building](#building)
+ - [Prerequisites](#prerequisites)
+ - [Linux (Debian/Ubuntu based)](#linux-debianubuntu-based)
+ - [macOS](#macos)
+ - [Windows](#windows)
+ - [Configuring the source tree](#configuring-the-source-tree)
+ - [Building and installation](#building-and-installation)
+- [Usage](#usage)
+- [Contributing](#contributing)
+- [Links](#links)
+- [License](#license)
+- [Credits](#credits)
+
## Features
The idevicerestore application is a full reimplementation of all granular steps
@@ -33,56 +48,176 @@ Use with caution and make sure to backup your data before trying to restore.
**In any case, usage is at your own risk.**
-## Installation / Getting started
-
-### Debian / Ubuntu Linux
+## Building
+
+### Prerequisites
+
+You need to have a working compiler (gcc/clang) and development environent
+available. This project uses autotools for the build process, allowing to
+have common build steps across different platforms.
+Only the prerequisites differ and they are described in this section.
+
+#### Linux (Debian/Ubuntu based)
+
+* Install all required dependencies and build tools:
+ ```shell
+ sudo apt-get install \
+ build-essential \
+ pkg-config \
+ checkinstall \
+ git \
+ autoconf \
+ automake \
+ libtool-bin \
+ libreadline-dev \
+ libusb-1.0-0-dev \
+ libplist-dev \
+ libimobiledevice-dev \
+ libimobiledevice-glue-dev \
+ libtatsu-dev \
+ libcurl4-openssl-dev \
+ libssl-dev \
+ libzip-dev \
+ zlib1g-dev
+ ```
+ NOTE: [libtatsu](https://github.com/libimobiledevice/libtatsu) (and thus `libtatsu-dev`)
+ is a new library that was just published recently, you have to
+ [build it from source](https://github.com/libimobiledevice/libtatsu?tab=readme-ov-file#building).
+ Also, other `*-dev` packages might not be available for your distribution,
+ so you will have to build these packages on your own as well.
+
+#### macOS
+
+* Make sure the Xcode command line tools are installed.
+
+ **Option 1**:
+ The easiest way to build and install `idevicerestore` for macOS is using
+ the following build script which will do the work for you, it will build
+ and install all required dependencies:
+ ```bash
+ mkdir -p limd-build
+ cd limd-build
+ curl -o ./limd-build-macos.sh -L https://is.gd/limdmacos
+ bash ./limd-build-macos.sh
+ ```
+ Follow the prompts of the script and you should have a working `idevicerestore`
+ available.
+
+ **Option 2**:
+ Use either [MacPorts](https://www.macports.org/)
+ or [Homebrew](https://brew.sh/) to install `automake`, `autoconf`, and `libtool`.
+
+ Using MacPorts:
+ ```shell
+ sudo port install libtool autoconf automake
+ ```
+
+ Using Homebrew:
+ ```shell
+ brew install libtool autoconf automake
+ ```
+
+ `idevicerestore` has a few dependencies from the libimobiledevice project.
+ You will have to build and install the following:
+ * [libplist](https://github.com/libimobiledevice/libplist)
+ * [libimobiledevice-glue](https://github.com/libimobiledevice/libimobiledevice-glue)
+ * [libusbmuxd](https://github.com/libimobiledevice/libusbmuxd)
+ * [libimobiledevice](https://github.com/libimobiledevice/libimobiledevice)
+ * [libirecovery](https://github.com/libimobiledevice/libirecovery)
+ * [libtatsu](https://github.com/libimobiledevice/libtatsu)
+
+ Check their `README.md` for building and installation instructions.
+
+#### Windows
+
+* Using [MSYS2](https://www.msys2.org/) is the official way of compiling this project on Windows. Download the MSYS2 installer
+ and follow the installation steps.
+
+ It is recommended to use the _MSYS2 MinGW 64-bit_ shell. Run it and make sure the required dependencies are installed:
+
+ ```shell
+ pacman -S base-devel \
+ git \
+ mingw-w64-x86_64-gcc \
+ make \
+ libtool \
+ autoconf \
+ automake-wrapper
+ ```
+ NOTE: You can use a different shell and different compiler according to your needs. Adapt the above command accordingly.
+
+ `idevicerestore` has a few dependencies from the libimobiledevice project.
+ You will have to build and install the following:
+ * [libplist](https://github.com/libimobiledevice/libplist)
+ * [libimobiledevice-glue](https://github.com/libimobiledevice/libimobiledevice-glue)
+ * [libusbmuxd](https://github.com/libimobiledevice/libusbmuxd)
+ * [libimobiledevice](https://github.com/libimobiledevice/libimobiledevice)
+ * [libirecovery](https://github.com/libimobiledevice/libirecovery)
+ * [libtatsu](https://github.com/libimobiledevice/libtatsu)
+
+ Check their `README.md` for building and installation instructions.
+
+
+### Configuring the source tree
+
+You can build the source code from a git checkout, or from a `.tar.bz2` release tarball from [Releases](https://github.com/libimobiledevice/idevicerestore/releases).
+Before we can build it, the source tree has to be configured for building. The steps depend on where you got the source from.
+
+* **From git**
+
+ If you haven't done already, clone the actual project repository and change into the directory.
+ ```shell
+ git clone https://github.com/libimobiledevice/idevicerestore.git
+ cd idevicerestore
+ ```
+
+ Configure the source tree for building:
+ ```shell
+ ./autogen.sh
+ ```
+
+* **From release tarball (.tar.bz2)**
+
+ When using an official [release tarball](https://github.com/libimobiledevice/idevicerestore/releases) (`idevicerestore-x.y.z.tar.bz2`)
+ the procedure is slightly different.
+
+ Extract the tarball:
+ ```shell
+ tar xjf idevicerestore-x.y.z.tar.bz2
+ cd idevicerestore-x.y.z
+ ```
+
+ Configure the source tree for building:
+ ```shell
+ ./configure
+ ```
+
+Both `./configure` and `./autogen.sh` (which generates and calls `configure`) accept a few options, for example `--prefix` to allow
+building for a different target folder. You can simply pass them like this:
-First install all required dependencies and build tools:
```shell
-sudo apt-get install \
- build-essential \
- pkg-config \
- checkinstall \
- git \
- autoconf \
- automake \
- libtool-bin \
- libreadline-dev \
- libusb-1.0-0-dev \
- libplist-dev \
- libimobiledevice-dev \
- libimobiledevice-glue-dev \
- libcurl4-openssl-dev \
- libssl-dev \
- libzip-dev \
- zlib1g-dev
+./autogen.sh --prefix=/usr/local
```
-
-Then clone, build and install [libirecovery](https://github.com/libimobiledevice/libirecovery.git) which is not yet packaged:
+or
```shell
-git clone https://github.com/libimobiledevice/libirecovery.git
-cd libirecovery
-./autogen.sh
-make
-sudo make install
-cd ..
+./configure --prefix=/usr/local
```
-If the configure processes indicates old or missing libraries, your distribution
-might not have yet packaged the latest versions. In that case you will have to
-clone [these libraries](https://github.com/libimobiledevice/) separately and repeat the process in order to proceed.
-
-Continue with cloning the actual project repository:
-```shell
-git clone https://github.com/libimobiledevice/idevicerestore.git
-cd idevicerestore
+Once the command is successful, the last few lines of output will look like this:
```
+[...]
+config.status: creating config.h
+config.status: config.h is unchanged
+config.status: executing depfiles commands
+config.status: executing libtool commands
-Now you can build and install it:
-```shell
-./autogen.sh
-make
-sudo make install
+Configuration for idevicerestore 1.1.0:
+-------------------------------------------
+
+ Install prefix: .........: /usr/local
+
+ Now type 'make' to build idevicerestore 1.1.0,
+ and then 'make install' for installation.
```
**Important**
@@ -142,8 +277,6 @@ Please make sure your contribution adheres to:
* Try to split larger changes into individual commits of a common domain
* Use your real name and a valid email address for your commits
-We are still working on the guidelines so bear with us!
-
## Links
* Homepage: https://libimobiledevice.org/
@@ -166,4 +299,4 @@ iPadOS, tvOS, watchOS, and macOS are trademarks of Apple Inc.
This project is an independent software application and has not been
authorized, sponsored, or otherwise approved by Apple Inc.
-README Updated on: 2022-04-04
+README Updated on: 2024-06-19
diff --git a/src/asr.c b/src/asr.c
index aadf25a..b150e85 100644
--- a/src/asr.c
+++ b/src/asr.c
@@ -40,7 +40,6 @@
#define ASR_VERSION 1
#define ASR_STREAM_ID 1
-#define ASR_PORT 12345
#define ASR_BUFFER_SIZE 65536
#define ASR_FEC_SLICE_STRIDE 40
#define ASR_PACKETS_PER_FEC 25
@@ -48,7 +47,7 @@
#define ASR_PAYLOAD_CHUNK_SIZE 131072
#define ASR_CHECKSUM_CHUNK_SIZE 131072
-int asr_open_with_timeout(idevice_t device, asr_client_t* asr)
+int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port)
{
int i = 0;
int attempts = 10;
@@ -61,9 +60,13 @@ int asr_open_with_timeout(idevice_t device, asr_client_t* asr)
return -1;
}
- debug("Connecting to ASR\n");
+ if (port == 0) {
+ port = ASR_DEFAULT_PORT;
+ }
+ debug("Connecting to ASR on port %u\n", port);
+
for (i = 1; i <= attempts; i++) {
- device_error = idevice_connect(device, ASR_PORT, &connection);
+ device_error = idevice_connect(device, port, &connection);
if (device_error == IDEVICE_E_SUCCESS) {
break;
}
@@ -358,7 +361,7 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file)
sendsize += 20;
}
if (asr_send_buffer(asr, data, sendsize) < 0) {
- error("ERROR: Unable to send filesystem payload\n");
+ error("Unable to send filesystem payload chunk, retrying...\n");
retry--;
continue;
}
@@ -374,5 +377,5 @@ int asr_send_payload(asr_client_t asr, ipsw_file_handle_t file)
}
free(data);
- return 0;
+ return (i == 0) ? 0 : -1;
}
diff --git a/src/asr.h b/src/asr.h
index 0d9534c..4473fbb 100644
--- a/src/asr.h
+++ b/src/asr.h
@@ -30,6 +30,8 @@ extern "C" {
#include <libimobiledevice/libimobiledevice.h>
+#define ASR_DEFAULT_PORT 12345
+
typedef void (*asr_progress_cb_t)(double, void*);
struct asr_client {
@@ -44,7 +46,7 @@ typedef struct asr_client *asr_client_t;
struct ipsw_file_handle;
typedef struct ipsw_file_handle* ipsw_file_handle_t;
-int asr_open_with_timeout(idevice_t device, asr_client_t* asr);
+int asr_open_with_timeout(idevice_t device, asr_client_t* asr, uint16_t port);
void asr_set_progress_callback(asr_client_t asr, asr_progress_cb_t, void* userdata);
int asr_send(asr_client_t asr, plist_t data);
int asr_receive(asr_client_t asr, plist_t* data);
diff --git a/src/common.c b/src/common.c
index e5ee07b..d31c558 100644
--- a/src/common.c
+++ b/src/common.c
@@ -35,6 +35,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
+#include <libimobiledevice-glue/thread.h>
#ifdef WIN32
#include <windows.h>
@@ -79,17 +80,30 @@ static int info_disabled = 0;
static int error_disabled = 0;
static int debug_disabled = 0;
+static mutex_t log_mutex;
+static thread_once_t init_once = THREAD_ONCE_INIT;
+
+static void _log_init(void)
+{
+ mutex_init(&log_mutex);
+}
+
void info(const char* format, ...)
{
if (info_disabled) return;
+ thread_once(&init_once, _log_init);
+ mutex_lock(&log_mutex);
va_list vargs;
va_start(vargs, format);
vfprintf((info_stream) ? info_stream : stdout, format, vargs);
va_end(vargs);
+ mutex_unlock(&log_mutex);
}
void error(const char* format, ...)
{
+ thread_once(&init_once, _log_init);
+ mutex_lock(&log_mutex);
va_list vargs, vargs2;
va_start(vargs, format);
va_copy(vargs2, vargs);
@@ -99,6 +113,7 @@ void error(const char* format, ...)
vfprintf((error_stream) ? error_stream : stderr, format, vargs2);
}
va_end(vargs2);
+ mutex_unlock(&log_mutex);
}
void debug(const char* format, ...)
@@ -107,10 +122,13 @@ void debug(const char* format, ...)
if (!idevicerestore_debug) {
return;
}
+ thread_once(&init_once, _log_init);
+ mutex_lock(&log_mutex);
va_list vargs;
va_start(vargs, format);
vfprintf((debug_stream) ? debug_stream : stderr, format, vargs);
va_end(vargs);
+ mutex_unlock(&log_mutex);
}
void idevicerestore_set_info_stream(FILE* strm)
@@ -227,9 +245,9 @@ void debug_plist(plist_t plist) {
char* data = NULL;
plist_to_xml(plist, &data, &size);
if (size <= MAX_PRINT_LEN)
- info("%s:printing %i bytes plist:\n%s", __FILE__, size, data);
+ info("printing %i bytes plist:\n%s", size, data);
else
- info("%s:supressed printing %i bytes plist...\n", __FILE__, size);
+ info("supressed printing %i bytes plist...\n", size);
free(data);
}
@@ -239,13 +257,13 @@ void print_progress_bar(double progress) {
int i = 0;
if(progress < 0) return;
if(progress > 100) progress = 100;
- info("\r[");
+ fprintf((info_stream) ? info_stream : stdout, "\r[");
for(i = 0; i < 50; i++) {
- if(i < progress / 2) info("=");
- else info(" ");
+ if(i < progress / 2) fprintf((info_stream) ? info_stream : stdout, "=");
+ else fprintf((info_stream) ? info_stream : stdout, " ");
}
- info("] %5.1f%%", progress);
- if(progress >= 100) info("\n");
+ fprintf((info_stream) ? info_stream : stdout, "] %5.1f%%", progress);
+ if(progress >= 100) fprintf((info_stream) ? info_stream : stdout, "\n");
fflush((info_stream) ? info_stream : stdout);
#endif
}
@@ -464,6 +482,8 @@ char *get_temp_filename(const char *prefix)
void idevicerestore_progress(struct idevicerestore_client_t* client, int step, double progress)
{
+ thread_once(&init_once, _log_init);
+ mutex_lock(&log_mutex);
if(client && client->progress_cb) {
client->progress_cb(step, progress, client->progress_cb_data);
} else {
@@ -472,6 +492,7 @@ void idevicerestore_progress(struct idevicerestore_client_t* client, int step, d
print_progress_bar(100.0 * progress);
}
}
+ mutex_unlock(&log_mutex);
}
#ifndef HAVE_STRSEP
diff --git a/src/common.h b/src/common.h
index 766a385..8085a1a 100644
--- a/src/common.h
+++ b/src/common.h
@@ -134,6 +134,7 @@ struct idevicerestore_client_t {
char* restore_variant;
char* filesystem;
int delete_fs;
+ int async_err;
};
extern struct idevicerestore_mode_t idevicerestore_modes[];
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 309f2b6..8de9186 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -1514,10 +1514,11 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
}
}
- info("DONE\n");
-
if (result == 0) {
+ info("DONE\n");
idevicerestore_progress(client, RESTORE_NUM_STEPS-1, 1.0);
+ } else {
+ info("RESTORE FAILED\n");
}
if (build_identity_needs_free)
diff --git a/src/restore.c b/src/restore.c
index efb03f9..5c6011f 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -31,6 +31,8 @@
#include <unistd.h>
#include <libgen.h>
#include <libimobiledevice/restore.h>
+#include <libimobiledevice/property_list_service.h>
+#include <libimobiledevice-glue/thread.h>
#ifdef HAVE_REVERSE_PROXY
#include <libimobiledevice/reverse_proxy.h>
#else
@@ -39,6 +41,7 @@
#include <zip.h>
#include <libirecovery.h>
#include <libtatsu/tss.h>
+#include <curl/curl.h>
#include "idevicerestore.h"
#include "asr.h"
@@ -633,6 +636,101 @@ const char* restore_progress_string(unsigned int operation)
}
}
+struct restored_service_client {
+
+};
+
+#define SERVICE_TYPE_RESTORED 1
+#define SERVICE_TYPE_PLIST 2
+
+typedef struct restore_service_client {
+ void* client;
+ int type;
+} *restore_service_client_t;
+
+static void* _restore_get_service_client_for_data_request(struct idevicerestore_client_t *client, plist_t message)
+{
+ if (!client || !client->restore || !client->restore->client || !PLIST_IS_DICT(message)) return NULL;
+ restore_service_client_t service = (restore_service_client_t)malloc(sizeof(struct restore_service_client));
+ if (!plist_dict_get_item(message, "DataPort")) {
+ service->client = client->restore->client;
+ service->type = SERVICE_TYPE_RESTORED;
+ return service;
+ }
+ plist_t data_type = plist_dict_get_item(message, "DataType");
+ uint16_t data_port = plist_dict_get_uint(message, "DataPort");
+ const char* data_type_str = plist_get_string_ptr(data_type, NULL);
+
+ struct lockdownd_service_descriptor svcdesc = {
+ data_port,
+ 0,
+ (char*)data_type_str
+ };
+ property_list_service_client_t plclient = NULL;
+ info("Connecting to %s data port %u\n", data_type_str, data_port);
+ if (property_list_service_client_new(client->restore->device, &svcdesc, &plclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) {
+ error("ERROR: Failed to start service connection for %s on port %u\n", data_type_str, data_port);
+ free(service);
+ return NULL;
+ }
+ service->client = plclient;
+ service->type = SERVICE_TYPE_PLIST;
+
+ return service;
+}
+
+static int _restore_service_send(restore_service_client_t service, plist_t plist, plist_format_t fmt)
+{
+ if (!service) {
+ return -1;
+ }
+ switch (service->type) {
+ case SERVICE_TYPE_RESTORED:
+ return restored_send((restored_client_t)service->client, plist);
+ case SERVICE_TYPE_PLIST:
+ if (fmt == PLIST_FORMAT_BINARY) {
+ return property_list_service_send_binary_plist((property_list_service_client_t)service->client, plist);
+ }
+ return property_list_service_send_xml_plist((property_list_service_client_t)service->client, plist);
+ default:
+ break;
+ }
+ return -1;
+}
+
+static int _restore_service_recv(restore_service_client_t service, plist_t *plist)
+{
+ if (!service) {
+ return -1;
+ }
+ switch (service->type) {
+ case SERVICE_TYPE_RESTORED:
+ return restored_receive((restored_client_t)service->client, plist);
+ case SERVICE_TYPE_PLIST:
+ return property_list_service_receive_plist((property_list_service_client_t)service->client, plist);
+ default:
+ break;
+ }
+ return -1;
+}
+
+static void _restore_service_free(restore_service_client_t service)
+{
+ if (!service) {
+ return;
+ }
+ switch (service->type) {
+ case SERVICE_TYPE_RESTORED:
+ break;
+ case SERVICE_TYPE_PLIST:
+ property_list_service_client_free((property_list_service_client_t)service->client);
+ break;
+ default:
+ break;
+ }
+ free(service);
+}
+
static int lastop = 0;
static int restore_handle_previous_restore_log_msg(restored_client_t client, plist_t msg)
@@ -686,6 +784,9 @@ int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t
info("%s (%d)\n", restore_progress_string(adapted_operation), (int)operation);
}
switch (adapted_operation) {
+ case RESTORE_IMAGE:
+ idevicerestore_progress(client, RESTORE_STEP_UPLOAD_FS, progress / 100.0);
+ break;
case VERIFY_RESTORE:
idevicerestore_progress(client, RESTORE_STEP_VERIFY_FS, progress / 100.0);
break;
@@ -715,7 +816,7 @@ int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t
return 0;
}
-int restore_handle_status_msg(restored_client_t client, plist_t msg)
+int restore_handle_status_msg(struct idevicerestore_client_t* client, plist_t msg)
{
int result = 0;
uint64_t value = 0;
@@ -781,10 +882,10 @@ int restore_handle_status_msg(restored_client_t client, plist_t msg)
return result;
}
-static int restore_handle_baseband_updater_output_data(restored_client_t restore, struct idevicerestore_client_t* client, idevice_t device, plist_t msg)
+static int restore_handle_baseband_updater_output_data(struct idevicerestore_client_t* client, plist_t message)
{
int result = -1;
- plist_t node = plist_dict_get_item(msg, "DataPort");
+ plist_t node = plist_dict_get_item(message, "DataPort");
uint64_t u64val = 0;
plist_get_uint_val(node, &u64val);
uint16_t data_port = (uint16_t)u64val;
@@ -793,9 +894,14 @@ static int restore_handle_baseband_updater_output_data(restored_client_t restore
idevice_connection_t connection = NULL;
idevice_error_t device_error = IDEVICE_E_SUCCESS;
+ if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
debug("Connecting to baseband updater data port\n");
while (--attempts > 0) {
- device_error = idevice_connect(device, data_port, &connection);
+ device_error = idevice_connect(client->restore->device, data_port, &connection);
if (device_error == IDEVICE_E_SUCCESS) {
break;
}
@@ -850,10 +956,10 @@ static int restore_handle_baseband_updater_output_data(restored_client_t restore
return result;
}
-static int restore_handle_bb_update_status_msg(restored_client_t client, plist_t msg)
+static int restore_handle_bb_update_status_msg(struct idevicerestore_client_t* client, plist_t message)
{
int result = -1;
- plist_t node = plist_dict_get_item(msg, "Accepted");
+ plist_t node = plist_dict_get_item(message, "Accepted");
uint8_t accepted = 0;
plist_get_bool_val(node, &accepted);
@@ -863,14 +969,14 @@ static int restore_handle_bb_update_status_msg(restored_client_t client, plist_t
}
uint8_t done = 0;
- node = plist_access_path(msg, 2, "Output", "done");
+ node = plist_access_path(message, 2, "Output", "done");
if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {
plist_get_bool_val(node, &done);
}
if (done) {
info("Updating Baseband completed.\n");
- plist_t provisioning = plist_access_path(msg, 2, "Output", "provisioning");
+ plist_t provisioning = plist_access_path(message, 2, "Output", "provisioning");
if (provisioning && plist_get_node_type(provisioning) == PLIST_DICT) {
char* sval = NULL;
node = plist_dict_get_item(provisioning, "IMEI");
@@ -898,16 +1004,21 @@ static void restore_asr_progress_cb(double progress, void* userdata)
}
}
-int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, plist_t build_identity)
+int restore_send_filesystem(struct idevicerestore_client_t* client, plist_t message)
{
asr_client_t asr = NULL;
-
- info("About to send filesystem...\n");
-
ipsw_archive_t ipsw_dummy = NULL;
ipsw_file_handle_t file = NULL;
char* fsname = NULL;
- if (build_identity_get_component_path(build_identity, "OS", &fsname) < 0) {
+
+ if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
+ info("About to send filesystem...\n");
+
+ if (build_identity_get_component_path(client->restore->build_identity, "OS", &fsname) < 0) {
error("ERROR: Unable to get path for filesystem component\n");
return -1;
}
@@ -926,7 +1037,11 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de
free(fsname);
}
- if (asr_open_with_timeout(device, &asr) < 0) {
+ uint16_t asr_port = (uint16_t)plist_dict_get_uint(message, "DataPort");
+ if (asr_port == 0) {
+ asr_port = ASR_DEFAULT_PORT;
+ }
+ if (asr_open_with_timeout(client->restore->device, &asr, asr_port) < 0) {
ipsw_file_close(file);
ipsw_close(ipsw_dummy);
error("ERROR: Unable to connect to ASR\n");
@@ -934,7 +1049,9 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de
}
info("Connected to ASR\n");
- asr_set_progress_callback(asr, restore_asr_progress_cb, (void*)client);
+ if (asr_port == ASR_DEFAULT_PORT) {
+ asr_set_progress_callback(asr, restore_asr_progress_cb, (void*)client);
+ }
// this step sends requested chunks of data from various offsets to asr so
// it can validate the filesystem before installing it
@@ -967,7 +1084,7 @@ int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t de
return 0;
}
-int restore_send_recovery_os_root_ticket(restored_client_t restore, struct idevicerestore_client_t* client)
+int restore_send_recovery_os_root_ticket(struct idevicerestore_client_t* client, plist_t message)
{
restored_error_t restore_error;
plist_t dict;
@@ -1007,9 +1124,16 @@ int restore_send_recovery_os_root_ticket(restored_client_t restore, struct idevi
free(data);
}
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending RecoveryOSRootTicket now...\n");
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Unable to send RootTicket (%d)\n", restore_error);
return -1;
@@ -1020,7 +1144,7 @@ int restore_send_recovery_os_root_ticket(restored_client_t restore, struct idevi
}
-int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_client_t* client)
+int restore_send_root_ticket(struct idevicerestore_client_t* client, plist_t message)
{
restored_error_t restore_error;
plist_t dict;
@@ -1060,9 +1184,16 @@ int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_cl
free(data);
}
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending RootTicket now...\n");
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Unable to send RootTicket (%d)\n", restore_error);
return -1;
@@ -1072,7 +1203,246 @@ int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_cl
return 0;
}
-int restore_send_component(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, const char* component, const char* component_name)
+typedef struct {
+ int length;
+ char* content;
+} query_response;
+
+static size_t _curl_write_callback(char* data, size_t size, size_t nmemb, query_response* response)
+{
+ size_t total = size * nmemb;
+ if (total != 0) {
+ response->content = realloc(response->content, response->length + total + 1);
+ memcpy(response->content + response->length, data, total);
+ response->content[response->length + total] = '\0';
+ response->length += total;
+ }
+
+ return total;
+}
+
+static size_t _curl_header_callback(char* buffer, size_t size, size_t nitems, void* userdata)
+{
+ plist_t header_dict = (plist_t)userdata;
+ size_t len = nitems*size;
+ char* key = NULL;
+ char* val = NULL;
+ size_t i = 0;
+ while (i < len) {
+ if (buffer[i] == ':') {
+ key = malloc(i+1);
+ strncpy(key, buffer, i);
+ key[i] = '\0';
+ i++;
+ while (i < len && buffer[i] == ' ' || buffer[i] == '\t') i++;
+ val = malloc(len-i);
+ strncpy(val, buffer+i, len-i);
+ val[len-i] = '\0';
+ break;
+ }
+ i++;
+ }
+ if (key && val) {
+ plist_dict_set_item(header_dict, key, plist_new_string(val));
+ }
+ free(key);
+ free(val);
+ return len;
+}
+
+int restore_send_url_asset(struct idevicerestore_client_t* client, plist_t message)
+{
+ debug("DEBUG: %s\n", __func__);
+ plist_t arguments = plist_dict_get_item(message, "Arguments");
+ if (!PLIST_IS_DICT(arguments)) {
+ error("ERROR: %s: Unexpected arguments\n", __func__);
+ debug_plist(arguments);
+ return -1;
+ }
+
+ const char* request_method = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestMethod"), NULL);
+ if (!request_method) {
+ error("ERROR: %s: Unable to extract RequestMethod from Arguments\n", __func__);
+ return -1;
+ }
+ if (strcmp(request_method, "GET")) {
+ error("ERROR: %s: Unexpected RequestMethod '%s' in message\n", __func__, request_method);
+ return -1;
+ }
+ const char* request_url = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestURL"), NULL);
+ if (!request_url) {
+ error("ERROR: %s: Unable to extract RequestURL from Arguments\n", __func__);
+ return -1;
+ }
+ info("Requesting URLAsset from %s\n", request_url);
+
+ char curl_error_message[CURL_ERROR_SIZE];
+ CURL* handle = curl_easy_init();
+ /* disable SSL verification to allow download from untrusted https locations */
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
+
+ query_response* response = malloc(sizeof(query_response));
+ if (response == NULL) {
+ error("ERROR: %s: Unable to allocate sufficient memory\n", __func__);
+ return -1;
+ }
+
+ response->length = 0;
+ response->content = malloc(1);
+ response->content[0] = '\0';
+
+ curl_easy_setopt(handle, CURLOPT_HTTPGET, 1L);
+ curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_message);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&_curl_write_callback);
+ curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, &_curl_header_callback);
+ plist_t response_headers = plist_new_dict();
+ curl_easy_setopt(handle, CURLOPT_HEADERDATA, response_headers);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, response);
+ if (idevicerestore_debug) {
+ curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);
+ }
+ curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt(handle, CURLOPT_URL, request_url);
+ curl_easy_perform(handle);
+
+ long http_response = 0;
+ curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_response);
+
+ curl_easy_cleanup(handle);
+
+ plist_t dict = plist_new_dict();
+ plist_dict_set_item(dict, "ResponseBody", plist_new_data(response->content, response->length));
+ plist_dict_set_item(dict, "ResponseBodyDone", plist_new_bool(1));
+ plist_dict_set_item(dict, "ResponseHeaders", response_headers);
+ plist_dict_set_item(dict, "ResponseStatus", plist_new_uint(http_response));
+
+ free(response);
+
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
+ _restore_service_send(service, dict, PLIST_FORMAT_BINARY);
+ _restore_service_free(service);
+
+ return 0;
+}
+
+int restore_send_streamed_image_decryption_key(struct idevicerestore_client_t* client, plist_t message)
+{
+ debug("DEBUG: %s\n", __func__);
+ plist_t arguments = plist_dict_get_item(message, "Arguments");
+ if (!PLIST_IS_DICT(arguments)) {
+ error("ERROR: %s: Unexpected arguments\n", __func__);
+ debug_plist(arguments);
+ return -1;
+ }
+
+ const char* request_method = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestMethod"), NULL);
+ if (!request_method) {
+ error("ERROR: %s: Unable to extract RequestMethod from Arguments\n", __func__);
+ return -1;
+ }
+ if (strcmp(request_method, "POST")) {
+ error("ERROR: %s: Unexpected RequestMethod '%s' in message\n", __func__, request_method);
+ return -1;
+ }
+ const char* request_url = plist_get_string_ptr(plist_dict_get_item(arguments, "RequestURL"), NULL);
+ if (!request_url) {
+ error("ERROR: %s: Unable to extract RequestURL from Arguments\n", __func__);
+ return -1;
+ }
+
+ struct curl_slist* header = NULL;
+
+ plist_t headers = plist_dict_get_item(arguments, "RequestAdditionalHeaders");
+ if (!headers) {
+ error("ERROR: %s: Missing 'RequestAdditionalHeaders'\n", __func__);
+ return -1;
+ }
+
+ uint64_t request_body_size = 0;
+ const char* request_body = plist_get_data_ptr(plist_dict_get_item(arguments, "RequestBody"), &request_body_size);
+ if (!request_body) {
+ error("ERROR: %s: Missing 'RequestBody'\n", __func__);
+ return -1;
+ }
+
+ info("Requesting image decryption key from %s\n", request_url);
+
+ char curl_error_message[CURL_ERROR_SIZE];
+ char header_tmp[1024];
+ plist_dict_iter iter = NULL;
+ plist_dict_new_iter(headers, &iter);
+ plist_t node = NULL;
+ do {
+ char *key = NULL;
+ plist_dict_next_item(headers, iter, &key, &node);
+ if (!node) break;
+ snprintf(header_tmp, sizeof(header_tmp), "%s: %s", key, plist_get_string_ptr(node, NULL));
+ curl_slist_append(header, header_tmp);
+ } while (node);
+ plist_mem_free(iter);
+
+ CURL* handle = curl_easy_init();
+ /* disable SSL verification to allow download from untrusted https locations */
+ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
+
+ query_response* response = malloc(sizeof(query_response));
+ if (response == NULL) {
+ error("ERROR: %s: Unable to allocate sufficient memory\n", __func__);
+ return -1;
+ }
+
+ response->length = 0;
+ response->content = malloc(1);
+ response->content[0] = '\0';
+
+ curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_message);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&_curl_write_callback);
+ curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, &_curl_header_callback);
+ plist_t response_headers = plist_new_dict();
+ curl_easy_setopt(handle, CURLOPT_HEADERDATA, response_headers);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, response);
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header);
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request_body);
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, request_body_size);
+ if (idevicerestore_debug) {
+ curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);
+ }
+ curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt(handle, CURLOPT_URL, request_url);
+ curl_easy_perform(handle);
+ curl_slist_free_all(header);
+
+ long http_response = 0;
+ curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_response);
+
+ curl_easy_cleanup(handle);
+
+ plist_t dict = plist_new_dict();
+ plist_dict_set_item(dict, "ResponseBody", plist_new_data(response->content, response->length));
+ plist_dict_set_item(dict, "ResponseBodyDone", plist_new_bool(1));
+ plist_dict_set_item(dict, "ResponseHeaders", response_headers);
+ plist_dict_set_item(dict, "ResponseStatus", plist_new_uint(http_response));
+
+ free(response);
+
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
+ _restore_service_send(service, dict, PLIST_FORMAT_BINARY);
+ _restore_service_free(service);
+
+ return 0;
+}
+
+int restore_send_component(struct idevicerestore_client_t* client, plist_t message, const char* component, const char* component_name)
{
unsigned int size = 0;
unsigned char* data = NULL;
@@ -1081,6 +1451,11 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie
plist_t dict = NULL;
restored_error_t restore_error = RESTORE_E_SUCCESS;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
if (component_name == NULL) {
component_name = component;
}
@@ -1093,7 +1468,7 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie
}
}
if (!path) {
- if (build_identity_get_component_path(build_identity, component, &path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, component, &path) < 0) {
error("ERROR: Unable to find %s path from build identity\n", component);
return -1;
}
@@ -1124,9 +1499,16 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie
plist_dict_set_item(dict, compkeyname, blob);
free(data);
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending %s now...\n", component_name);
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Unable to send component %s data\n", component_name);
return -1;
@@ -1136,7 +1518,7 @@ int restore_send_component(restored_client_t restore, struct idevicerestore_clie
return 0;
}
-int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message)
+int restore_send_nor(struct idevicerestore_client_t* client, plist_t message)
{
char* llb_path = NULL;
char* llb_filename = NULL;
@@ -1156,6 +1538,11 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
plist_t firmware_files = NULL;
int flash_version_1 = 0;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
info("About to send NORData...\n");
plist_t arguments = plist_dict_get_item(message, "Arguments");
@@ -1169,7 +1556,7 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
}
}
if (llb_path == NULL) {
- if (build_identity_get_component_path(build_identity, "LLB", &llb_path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, "LLB", &llb_path) < 0) {
error("ERROR: Unable to get component path for LLB\n");
return -1;
}
@@ -1209,7 +1596,7 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
} else {
info("Getting firmware manifest from build identity\n");
plist_dict_iter iter = NULL;
- plist_t build_id_manifest = plist_dict_get_item(build_identity, "Manifest");
+ plist_t build_id_manifest = plist_dict_get_item(client->restore->build_identity, "Manifest");
if (build_id_manifest) {
plist_dict_new_iter(build_id_manifest, &iter);
}
@@ -1362,8 +1749,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
unsigned char* personalized_data = NULL;
unsigned int personalized_size = 0;
- if (build_identity_has_component(build_identity, "RestoreSEP") &&
- build_identity_get_component_path(build_identity, "RestoreSEP", &restore_sep_path) == 0) {
+ if (build_identity_has_component(client->restore->build_identity, "RestoreSEP") &&
+ build_identity_get_component_path(client->restore->build_identity, "RestoreSEP", &restore_sep_path) == 0) {
component = "RestoreSEP";
ret = extract_component(client->ipsw, restore_sep_path, &component_data, &component_size);
free(restore_sep_path);
@@ -1387,8 +1774,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
personalized_size = 0;
}
- if (build_identity_has_component(build_identity, "SEP") &&
- build_identity_get_component_path(build_identity, "SEP", &sep_path) == 0) {
+ if (build_identity_has_component(client->restore->build_identity, "SEP") &&
+ build_identity_get_component_path(client->restore->build_identity, "SEP", &sep_path) == 0) {
component = "SEP";
ret = extract_component(client->ipsw, sep_path, &component_data, &component_size);
free(sep_path);
@@ -1412,8 +1799,8 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
personalized_size = 0;
}
- if (build_identity_has_component(build_identity, "SepStage1") &&
- build_identity_get_component_path(build_identity, "SepStage1", &sep_path) == 0) {
+ if (build_identity_has_component(client->restore->build_identity, "SepStage1") &&
+ build_identity_get_component_path(client->restore->build_identity, "SepStage1", &sep_path) == 0) {
component = "SepStage1";
ret = extract_component(client->ipsw, sep_path, &component_data, &component_size);
free(sep_path);
@@ -1440,15 +1827,22 @@ int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t*
if (idevicerestore_debug)
debug_plist(dict);
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending NORData now...\n");
- if (restored_send(restore, dict) != RESTORE_E_SUCCESS) {
+ restored_error_t restore_error = _restore_service_send(service, dict, 0);
+ plist_free(dict);
+ _restore_service_free(service);
+ if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Unable to send NORData\n");
- plist_free(dict);
return -1;
}
info("Done sending NORData\n");
- plist_free(dict);
return 0;
}
@@ -1820,7 +2214,7 @@ leave:
return res;
}
-static int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message)
+static int restore_send_baseband_data(struct idevicerestore_client_t* client, plist_t message)
{
int res = -1;
uint64_t bb_cert_id = 0;
@@ -1834,6 +2228,11 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer
char* bbfwtmp = NULL;
plist_t dict = NULL;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
info("About to send BasebandData...\n");
// NOTE: this function is called 2 or 3 times!
@@ -1870,7 +2269,7 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer
plist_dict_set_item(parameters, "BbGoldCertId", plist_new_uint(bb_cert_id));
plist_dict_set_item(parameters, "BbSNUM", plist_new_data((const char*)bb_snum, bb_snum_size));
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
/* create baseband request */
plist_t request = tss_request_new(NULL);
@@ -1884,7 +2283,7 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer
tss_request_add_common_tags(request, parameters, NULL);
tss_request_add_baseband_tags(request, parameters, NULL);
- plist_t node = plist_access_path(build_identity, 2, "Info", "FDRSupport");
+ plist_t node = plist_access_path(client->restore->build_identity, 2, "Info", "FDRSupport");
if (node && plist_get_node_type(node) == PLIST_BOOLEAN) {
uint8_t b = 0;
plist_get_bool_val(node, &b);
@@ -1911,7 +2310,7 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer
}
// get baseband firmware file path from build identity
- plist_t bbfw_path = plist_access_path(build_identity, 4, "Manifest", "BasebandFirmware", "Info", "Path");
+ plist_t bbfw_path = plist_access_path(client->restore->build_identity, 4, "Manifest", "BasebandFirmware", "Info", "Path");
if (!bbfw_path || plist_get_node_type(bbfw_path) != PLIST_STRING) {
error("ERROR: Unable to get BasebandFirmware/Info/Path node\n");
plist_free(response);
@@ -1965,12 +2364,20 @@ static int restore_send_baseband_data(restored_client_t restore, struct idevicer
free(buffer);
buffer = NULL;
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending BasebandData now...\n");
- if (restored_send(restore, dict) != RESTORE_E_SUCCESS) {
+ if (_restore_service_send(service, dict, 0) != RESTORE_E_SUCCESS) {
error("ERROR: Unable to send BasebandData data\n");
goto leave;
}
+ _restore_service_free(service);
+
info("Done sending BasebandData\n");
res = 0;
@@ -1986,7 +2393,7 @@ leave:
return res;
}
-int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device)
+int restore_send_fdr_trust_data(struct idevicerestore_client_t* client, plist_t message)
{
restored_error_t restore_error;
plist_t dict;
@@ -1998,9 +2405,16 @@ int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device)
* and this is what iTunes seems to be doing too */
dict = plist_new_dict();
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending FDR Trust data now...\n");
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: During sending FDR Trust data (%d)\n", restore_error);
return -1;
@@ -2011,7 +2425,7 @@ int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device)
return 0;
}
-static int restore_send_image_data(restored_client_t restore, struct idevicerestore_client_t *client, plist_t build_identity, plist_t message, const char *image_list_k, const char *image_type_k, const char *image_data_k)
+static int restore_send_image_data(struct idevicerestore_client_t *client, plist_t message, const char *image_list_k, const char *image_type_k, const char *image_data_k)
{
restored_error_t restore_error;
plist_t arguments;
@@ -2024,6 +2438,11 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest
char *image_name = NULL;
int want_image_list = 0;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
arguments = plist_dict_get_item(message, "Arguments");
want_image_list = plist_dict_get_bool(arguments, image_list_k);
node = plist_dict_get_item(arguments, "ImageName");
@@ -2051,7 +2470,7 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest
data_dict = plist_new_dict();
}
- build_id_manifest = plist_dict_get_item(build_identity, "Manifest");
+ build_id_manifest = plist_dict_get_item(client->restore->build_identity, "Manifest");
if (build_id_manifest) {
plist_dict_new_iter(build_id_manifest, &iter);
}
@@ -2083,7 +2502,7 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest
if (!image_name) {
info("Found %s component '%s'\n", image_type_k, component);
}
- build_identity_get_component_path(build_identity, component, &path);
+ build_identity_get_component_path(client->restore->build_identity, component, &path);
if (path) {
ret = extract_component(client->ipsw, path, &component_data, &component_size);
}
@@ -2110,6 +2529,12 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest
free(iter);
}
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
dict = plist_new_dict();
if (want_image_list) {
plist_dict_set_item(dict, image_list_k, matched_images);
@@ -2128,8 +2553,9 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest
}
}
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
if (want_image_list) {
error("ERROR: Failed to send %s image list (%d)\n", image_type_k, restore_error);
@@ -2155,7 +2581,7 @@ static int restore_send_image_data(restored_client_t restore, struct idevicerest
return 0;
}
-static plist_t restore_get_se_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments)
+static plist_t restore_get_se_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments)
{
const char *comp_name = NULL;
char *comp_path = NULL;
@@ -2167,6 +2593,12 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id
plist_t p_dgr = NULL;
int ret;
uint64_t chip_id = 0;
+
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return NULL;
+ }
+
plist_t node = plist_dict_get_item(p_info, "SE,ChipID");
if (node && plist_get_node_type(node) == PLIST_UINT) {
plist_get_uint_val(node, &chip_id);
@@ -2177,9 +2609,9 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id
comp_name = "SE,UpdatePayload";
} else {
info("WARNING: Unknown SE,ChipID 0x%" PRIx64 " detected. Restore might fail.\n", (uint64_t)chip_id);
- if (build_identity_has_component(build_identity, "SE,UpdatePayload"))
+ if (build_identity_has_component(client->restore->build_identity, "SE,UpdatePayload"))
comp_name = "SE,UpdatePayload";
- else if (build_identity_has_component(build_identity, "SE,Firmware"))
+ else if (build_identity_has_component(client->restore->build_identity, "SE,Firmware"))
comp_name = "SE,Firmware";
else {
error("ERROR: Neither 'SE,Firmware' nor 'SE,UpdatePayload' found in build identity.\n");
@@ -2196,7 +2628,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id
return NULL;
}
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
error("ERROR: Unable to get path for '%s' component\n", comp_name);
return NULL;
}
@@ -2220,7 +2652,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id
parameters = plist_new_dict();
/* add manifest for current build_identity to parameters */
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
/* add SE,* tags from info dictionary to parameters */
plist_dict_merge(&parameters, p_info);
@@ -2255,7 +2687,7 @@ static plist_t restore_get_se_firmware_data(restored_client_t restore, struct id
return response;
}
-static plist_t restore_get_savage_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, 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;
@@ -2267,6 +2699,17 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc
plist_t response = NULL;
int ret;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ 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) {
@@ -2277,13 +2720,13 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc
parameters = plist_new_dict();
/* add manifest for current build_identity to parameters */
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
/* add Savage,* tags from info dictionary to parameters */
plist_dict_merge(&parameters, 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);
@@ -2310,7 +2753,7 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc
}
/* now get actual component data */
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
error("ERROR: Unable to get path for '%s' component\n", comp_name);
free(comp_name);
return NULL;
@@ -2346,7 +2789,7 @@ static plist_t restore_get_savage_firmware_data(restored_client_t restore, struc
return response;
}
-static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, 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;
@@ -2357,6 +2800,17 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru
plist_t response = NULL;
int ret;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ 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) {
@@ -2369,13 +2823,13 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru
parameters = plist_new_dict();
/* add manifest for current build_identity to parameters */
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
/* add Yonkers,* tags from info dictionary to parameters */
plist_dict_merge(&parameters, 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);
@@ -2401,7 +2855,7 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru
error("ERROR: No 'Yonkers,Ticket' in TSS response, this might not work\n");
}
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
error("ERROR: Unable to get path for '%s' component\n", comp_name);
free(comp_name);
return NULL;
@@ -2430,7 +2884,7 @@ static plist_t restore_get_yonkers_firmware_data(restored_client_t restore, stru
return response;
}
-static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments)
+static plist_t restore_get_rose_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments)
{
char *comp_name = NULL;
char *comp_path = NULL;
@@ -2444,6 +2898,11 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct
plist_t response = NULL;
int ret;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return NULL;
+ }
+
/* create Rose request */
request = tss_request_new(NULL);
if (request == NULL) {
@@ -2455,7 +2914,7 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct
parameters = plist_new_dict();
/* add manifest for current build_identity to parameters */
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1));
if (client->image4supported) {
@@ -2501,7 +2960,7 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct
}
comp_name = "Rap,RTKitOS";
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
error("ERROR: Unable to get path for '%s' component\n", comp_name);
return NULL;
}
@@ -2525,8 +2984,8 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct
}
comp_name = "Rap,RestoreRTKitOS";
- if (build_identity_has_component(build_identity, comp_name)) {
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_has_component(client->restore->build_identity, comp_name)) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
ftab_free(ftab);
error("ERROR: Unable to get path for '%s' component\n", comp_name);
return NULL;
@@ -2577,7 +3036,7 @@ static plist_t restore_get_rose_firmware_data(restored_client_t restore, struct
return response;
}
-static plist_t restore_get_veridian_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, 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;
@@ -2588,6 +3047,17 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str
plist_t response = NULL;
int ret;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ 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) {
@@ -2599,13 +3069,13 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str
parameters = plist_new_dict();
/* add manifest for current build_identity to parameters */
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
/* add BMU,* tags from info dictionary to parameters */
plist_dict_merge(&parameters, 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);
@@ -2624,7 +3094,7 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str
error("ERROR: No 'BMU,Ticket' in TSS response, this might not work\n");
}
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
error("ERROR: Unable to get path for '%s' component\n", comp_name);
return NULL;
}
@@ -2653,7 +3123,7 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str
return NULL;
}
- plist_t fw_map_digest = plist_access_path(build_identity, 3, "Manifest", comp_name, "Digest");
+ plist_t fw_map_digest = plist_access_path(client->restore->build_identity, 3, "Manifest", comp_name, "Digest");
if (!fw_map_digest) {
plist_free(fw_map);
error("ERROR: Unable to get Digest for '%s' component\n", comp_name);
@@ -2673,7 +3143,7 @@ static plist_t restore_get_veridian_firmware_data(restored_client_t restore, str
return response;
}
-static plist_t restore_get_generic_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments)
+static plist_t restore_get_generic_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments)
{
plist_t request = NULL;
plist_t response = NULL;
@@ -2728,7 +3198,7 @@ static plist_t restore_get_generic_firmware_data(restored_client_t restore, stru
return response;
}
-static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, 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;
@@ -2739,6 +3209,17 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct
plist_t response = NULL;
int ret;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ 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) {
@@ -2750,13 +3231,13 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct
parameters = plist_new_dict();
/* add manifest for current build_identity to parameters */
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
/* add Baobab,* tags from info dictionary to parameters */
plist_dict_merge(&parameters, 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);
@@ -2775,7 +3256,7 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct
error("ERROR: No 'Baobab,Ticket' in TSS response, this might not work\n");
}
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
error("ERROR: Unable to get path for '%s' component\n", comp_name);
return NULL;
}
@@ -2797,7 +3278,7 @@ static plist_t restore_get_tcon_firmware_data(restored_client_t restore, struct
return response;
}
-static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, 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;
@@ -2813,6 +3294,17 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct
uint32_t tag = 0;
int ret;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ 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) {
@@ -2823,7 +3315,7 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct
parameters = plist_new_dict();
/* add manifest for current build_identity to parameters */
- tss_parameters_add_from_manifest(parameters, build_identity, true);
+ tss_parameters_add_from_manifest(parameters, client->restore->build_identity, true);
plist_dict_set_item(parameters, "ApProductionMode", plist_new_bool(1));
if (client->image4supported) {
@@ -2883,7 +3375,7 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct
}
/* 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);
@@ -2902,8 +3394,8 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct
}
sprintf(comp_name, "Timer,RTKitOS,%u", tag);
- if (build_identity_has_component(build_identity, comp_name)) {
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_has_component(client->restore->build_identity, comp_name)) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
error("ERROR: Unable to get path for '%s' component\n", comp_name);
return NULL;
}
@@ -2930,8 +3422,8 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct
}
sprintf(comp_name, "Timer,RestoreRTKitOS,%u", tag);
- if (build_identity_has_component(build_identity, comp_name)) {
- if (build_identity_get_component_path(build_identity, comp_name, &comp_path) < 0) {
+ if (build_identity_has_component(client->restore->build_identity, comp_name)) {
+ if (build_identity_get_component_path(client->restore->build_identity, comp_name, &comp_path) < 0) {
ftab_free(ftab);
error("ERROR: Unable to get path for '%s' component\n", comp_name);
return NULL;
@@ -2982,12 +3474,17 @@ static plist_t restore_get_timer_firmware_data(restored_client_t restore, struct
return response;
}
-static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t p_info, plist_t arguments)
+static plist_t restore_get_cryptex1_firmware_data(struct idevicerestore_client_t* client, plist_t p_info, plist_t arguments)
{
plist_t parameters = NULL;
plist_t request = NULL;
plist_t response = NULL;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return NULL;
+ }
+
plist_t p_updater_name = plist_dict_get_item(arguments, "MessageArgUpdaterName");
const char* s_updater_name = plist_get_string_ptr(p_updater_name, NULL);
@@ -3019,7 +3516,7 @@ static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, str
for (i = 0; i < plist_array_get_size(build_identity_tags); i++) {
plist_t node = plist_array_get_item(build_identity_tags, i);
const char* key = plist_get_string_ptr(node, NULL);
- plist_t item = plist_dict_get_item(build_identity, key);
+ plist_t item = plist_dict_get_item(client->restore->build_identity, key);
if (item) {
plist_dict_set_item(parameters, key, plist_copy(item));
}
@@ -3034,10 +3531,10 @@ static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, str
plist_dict_set_item(parameters, "ApSecurityMode", plist_new_bool(1));
}
if (!plist_dict_get_item(parameters, "ApChipID")) {
- plist_dict_copy_uint(parameters, build_identity, "ApChipID", NULL);
+ plist_dict_copy_uint(parameters, client->restore->build_identity, "ApChipID", NULL);
}
if (!plist_dict_get_item(parameters, "ApBoardID")) {
- plist_dict_copy_uint(parameters, build_identity, "ApBoardID", NULL);
+ plist_dict_copy_uint(parameters, client->restore->build_identity, "ApBoardID", NULL);
}
/* add device generated request data to parameters */
@@ -3072,7 +3569,7 @@ static plist_t restore_get_cryptex1_firmware_data(restored_client_t restore, str
return response;
}
-static int restore_send_firmware_updater_preflight(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message)
+static int restore_send_firmware_updater_preflight(struct idevicerestore_client_t* client, plist_t message)
{
plist_t dict = NULL;
int restore_error;
@@ -3082,11 +3579,18 @@ static int restore_send_firmware_updater_preflight(restored_client_t restore, st
debug_plist(message);
}
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
dict = plist_new_dict();
info("Sending FirmwareResponsePreflight now...\n");
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Couldn't send FirmwareResponsePreflight data (%d)\n", restore_error);
return -1;
@@ -3096,7 +3600,7 @@ static int restore_send_firmware_updater_preflight(restored_client_t restore, st
return 0;
}
-static int restore_send_firmware_updater_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message)
+static int restore_send_firmware_updater_data(struct idevicerestore_client_t* client, plist_t message)
{
plist_t arguments;
plist_t p_type, p_updater_name, p_loop_count, p_info;
@@ -3107,6 +3611,11 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct
char *s_updater_name = NULL;
int restore_error;
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
if (idevicerestore_debug) {
debug("DEBUG: %s: Got FirmwareUpdaterData request:\n", __func__);
debug_plist(message);
@@ -3153,7 +3662,7 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct
plist_get_string_val(p_updater_name, &s_updater_name);
if (strcmp(s_updater_name, "SE") == 0) {
- fwdict = restore_get_se_firmware_data(restore, client, build_identity, p_info, arguments);
+ fwdict = restore_get_se_firmware_data(client, p_info, arguments);
if (fwdict == NULL) {
error("ERROR: %s: Couldn't get SE firmware data\n", __func__);
goto error_out;
@@ -3163,59 +3672,59 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct
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(restore, client, build_identity, p_info2);
+ fwdict = restore_get_yonkers_firmware_data(client, p_info2, arguments);
} else {
- fwdict = restore_get_savage_firmware_data(restore, client, build_identity, 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);
goto error_out;
}
} else if (strcmp(s_updater_name, "Rose") == 0) {
- fwdict = restore_get_rose_firmware_data(restore, client, build_identity, p_info, arguments);
+ fwdict = restore_get_rose_firmware_data(client, p_info, arguments);
if (fwdict == NULL) {
error("ERROR: %s: Couldn't get Rose firmware data\n", __func__);
goto error_out;
}
} else if (strcmp(s_updater_name, "T200") == 0) {
- fwdict = restore_get_veridian_firmware_data(restore, client, build_identity, 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(restore, client, build_identity, 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;
}
} else if (strcmp(s_updater_name, "PS190") == 0) {
- fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments);
+ fwdict = restore_get_generic_firmware_data(client, p_info, arguments);
if (fwdict == NULL) {
error("ERROR: %s: Couldn't get PCON1 firmware data\n", __func__);
goto error_out;
}
} else if (strcmp(s_updater_name, "AppleTypeCRetimer") == 0) {
- fwdict = restore_get_timer_firmware_data(restore, client, build_identity, 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;
}
} else if ((strcmp(s_updater_name, "Cryptex1") == 0) || (strcmp(s_updater_name, "Cryptex1LocalPolicy") == 0)) {
- fwdict = restore_get_cryptex1_firmware_data(restore, client, build_identity, p_info, arguments);
+ fwdict = restore_get_cryptex1_firmware_data(client, p_info, arguments);
if (fwdict == NULL) {
error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name);
goto error_out;
}
} else if (strcmp(s_updater_name, "Ace3") == 0) {
- fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments);
+ fwdict = restore_get_generic_firmware_data(client, p_info, arguments);
if (fwdict == NULL) {
error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name);
goto error_out;
}
} else {
error("ERROR: %s: Got unknown updater name '%s', trying to discover from device generated request.\n", __func__, s_updater_name);
- fwdict = restore_get_generic_firmware_data(restore, client, build_identity, p_info, arguments);
+ fwdict = restore_get_generic_firmware_data(client, p_info, arguments);
if (fwdict == NULL) {
error("ERROR: %s: Couldn't get %s firmware data\n", __func__, s_updater_name);
goto error_out;
@@ -3224,12 +3733,19 @@ static int restore_send_firmware_updater_data(restored_client_t restore, struct
free(s_updater_name);
s_updater_name = NULL;
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
dict = plist_new_dict();
plist_dict_set_item(dict, "FirmwareResponseData", fwdict);
info("Sending FirmwareResponse data now...\n");
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Couldn't send FirmwareResponse data (%d)\n", restore_error);
goto error_out;
@@ -3246,23 +3762,35 @@ error_out:
return -1;
}
-static int restore_send_receipt_manifest(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity)
+static int restore_send_receipt_manifest(struct idevicerestore_client_t* client, plist_t message)
{
plist_t dict;
int restore_error;
- plist_t manifest = plist_dict_get_item(build_identity, "Manifest");
+ if (!client || !client->restore || !client->restore->build_identity) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
+ plist_t manifest = plist_dict_get_item(client->restore->build_identity, "Manifest");
if (!manifest) {
error("failed to get Manifest node from build_identity");
goto error_out;
}
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
dict = plist_new_dict();
plist_dict_set_item(dict, "ReceiptManifest", plist_copy(manifest));
info("Sending ReceiptManifest data now...\n");
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
plist_free(dict);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Couldn't send ReceiptManifest data (%d)\n", restore_error);
goto error_out;
@@ -3379,7 +3907,7 @@ static int restore_bootability_send_one(void *ctx, ipsw_archive_t ipsw, const ch
return ret;
}
-static int restore_send_bootability_bundle_data(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message, idevice_t device)
+static int restore_send_bootability_bundle_data(struct idevicerestore_client_t* client, plist_t message)
{
if (idevicerestore_debug) {
debug("DEBUG: %s: Got BootabilityBundle request:\n", __func__);
@@ -3395,9 +3923,14 @@ static int restore_send_bootability_bundle_data(restored_client_t restore, struc
idevice_connection_t connection = NULL;
idevice_error_t device_error = IDEVICE_E_SUCCESS;
+ if (!client || !client->restore || !client->restore->build_identity || !client->restore->device) {
+ error("ERROR: %s: idevicerestore client not initialized?!\n", __func__);
+ return -1;
+ }
+
debug("Connecting to BootabilityBundle data port\n");
while (--attempts > 0) {
- device_error = idevice_connect(device, data_port, &connection);
+ device_error = idevice_connect(client->restore->device, data_port, &connection);
if (device_error == IDEVICE_E_SUCCESS) {
break;
}
@@ -3442,16 +3975,16 @@ plist_t restore_get_build_identity(struct idevicerestore_client_t* client, uint8
plist_t unique_id_node = plist_dict_get_item(client->build_manifest, "UniqueBuildID");
if (unique_id_node) {
- printf("UniqueBuildID: ");
+ info("UniqueBuildID: ");
plist_write_to_stream(unique_id_node, stdout, PLIST_FORMAT_PRINT, PLIST_OPT_NONE);
}
return build_identity;
}
-plist_t restore_get_build_identity_from_request(struct idevicerestore_client_t* client, plist_t msg)
+plist_t restore_get_build_identity_from_request(struct idevicerestore_client_t* client, plist_t message)
{
- plist_t args = plist_dict_get_item(msg, "Arguments");
+ plist_t args = plist_dict_get_item(message, "Arguments");
return restore_get_build_identity(client, plist_dict_get_bool(args, "IsRecoveryOS"));
}
@@ -3531,7 +4064,7 @@ int extract_global_manifest(struct idevicerestore_client_t* client, plist_t buil
struct _restore_send_file_data_ctx {
struct idevicerestore_client_t* client;
- restored_client_t restore;
+ restore_service_client_t service;
int last_progress;
};
@@ -3545,13 +4078,22 @@ static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, voi
// Send FileDataDone to mark end of transfer
plist_dict_set_item(dict, "FileDataDone", plist_new_bool(1));
}
- restored_error_t restore_error = restored_send(rctx->restore, dict);
+ restored_error_t restore_error = _restore_service_send(rctx->service, dict, 0);
if (restore_error != RESTORE_E_SUCCESS) {
plist_free(dict);
error("ERROR: %s: Failed to send data (%d)\n", __func__, restore_error);
return -1;
}
plist_free(dict);
+
+ /* special handling for AEA image format */
+ if (done == 0 && (memcmp(data, "AEA1", 4) == 0)) {
+ info("Encountered First Chunk in AEA image\n");
+ plist_t message = NULL;
+ _restore_service_recv(rctx->service, &message);
+ restore_send_url_asset(rctx->client, message);
+ }
+
if (total_size > 0x1000000) {
double progress = (double)done / (double)total_size;
int progress_int = (int)(progress*100.0);
@@ -3563,15 +4105,15 @@ static int _restore_send_file_data(struct _restore_send_file_data_ctx* rctx, voi
return 0;
}
-int restore_send_personalized_boot_object_v3(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg, plist_t build_identity)
+int restore_send_personalized_boot_object_v3(struct idevicerestore_client_t* client, plist_t message)
{
if (idevicerestore_debug) {
debug("DEBUG: %s: Got PersonalizedBootObjectV3 request:\n", __func__);
- debug_plist(msg);
+ debug_plist(message);
}
char *image_name = NULL;
- plist_t node = plist_access_path(msg, 2, "Arguments", "ImageName");
+ plist_t node = plist_access_path(message, 2, "Arguments", "ImageName");
if (!node || plist_get_node_type(node) != PLIST_STRING) {
debug("Failed to parse arguments from PersonalizedBootObjectV3 plist\n");
return -1;
@@ -3593,7 +4135,7 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i
info("About to send %s...\n", component);
if (strcmp(image_name, "__GlobalManifest__") == 0) {
- int ret = extract_global_manifest(client, build_identity, NULL, &data, &size);
+ int ret = extract_global_manifest(client, client->restore->build_identity, NULL, &data, &size);
if (ret != 0) {
return -1;
}
@@ -3617,7 +4159,7 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i
}
}
if (!path) {
- plist_t build_identity = restore_get_build_identity_from_request(client, msg);
+ plist_t build_identity = restore_get_build_identity_from_request(client, message);
if (!build_identity) {
error("ERROR: Unable to find a matching build identity\n");
return -1;
@@ -3649,11 +4191,17 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i
}
}
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending %s now (%" PRIu64 " bytes)...\n", component, (uint64_t)size);
struct _restore_send_file_data_ctx rctx;
rctx.client = client;
- rctx.restore = restore;
+ rctx.service = service;
rctx.last_progress = 0;
int64_t i = size;
@@ -3661,6 +4209,7 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i
int blob_size = i > 8192 ? 8192 : i;
if (_restore_send_file_data(&rctx, (data + size - i), blob_size, size-i, size) < 0) {
free(data);
+ _restore_service_free(service);
error("ERROR: Unable to send component %s data\n", component);
return -1;
}
@@ -3670,19 +4219,21 @@ int restore_send_personalized_boot_object_v3(restored_client_t restore, struct i
_restore_send_file_data(&rctx, NULL, 0, size-i, size);
+ _restore_service_free(service);
+
info("Done sending %s\n", component);
return 0;
}
-int restore_send_source_boot_object_v4(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg, plist_t build_identity)
+int restore_send_source_boot_object_v4(struct idevicerestore_client_t* client, plist_t message)
{
if (idevicerestore_debug) {
debug("DEBUG: %s: Got SourceBootObjectV4 request:\n", __func__);
- debug_plist(msg);
+ debug_plist(message);
}
char *image_name = NULL;
- plist_t node = plist_access_path(msg, 2, "Arguments", "ImageName");
+ plist_t node = plist_access_path(message, 2, "Arguments", "ImageName");
if (!node || plist_get_node_type(node) != PLIST_STRING) {
debug("Failed to parse arguments from SourceBootObjectV4 plist\n");
return -1;
@@ -3707,7 +4258,7 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice
if (strcmp(image_name, "__GlobalManifest__") == 0) {
char *variant = NULL;
- plist_t node = plist_access_path(msg, 2, "Arguments", "Variant");
+ plist_t node = plist_access_path(message, 2, "Arguments", "Variant");
if (!node || plist_get_node_type(node) != PLIST_STRING) {
debug("Failed to parse arguments from SourceBootObjectV4 plist\n");
return -1;
@@ -3718,7 +4269,7 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice
return -1;
}
- path = extract_global_manifest_path(build_identity, variant);
+ path = extract_global_manifest_path(client->restore->build_identity, variant);
} else if (strcmp(image_name, "__RestoreVersion__") == 0) {
path = strdup("RestoreVersion.plist");
} else if (strcmp(image_name, "__SystemVersion__") == 0) {
@@ -3731,7 +4282,7 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice
}
}
if (!path) {
- plist_t build_identity = restore_get_build_identity_from_request(client, msg);
+ plist_t build_identity = restore_get_build_identity_from_request(client, message);
if (build_identity_get_component_path(build_identity, component, &path) < 0) {
error("ERROR: Unable to find %s path from build identity\n", component);
return -1;
@@ -3747,25 +4298,34 @@ int restore_send_source_boot_object_v4(restored_client_t restore, struct idevice
uint64_t fsize = 0;
ipsw_get_file_size(client->ipsw, path, &fsize);
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("Sending %s now (%" PRIu64 " bytes)\n", component, fsize);
struct _restore_send_file_data_ctx rctx;
rctx.client = client;
- rctx.restore = restore;
+ rctx.service = service;
rctx.last_progress = 0;
if (ipsw_extract_send(client->ipsw, path, 8192, (ipsw_send_cb)_restore_send_file_data, &rctx) < 0) {
free(path);
+ _restore_service_free(service);
error("ERROR: Failed to send component %s\n", component);
return -1;
}
free(path);
+ _restore_service_free(service);
+
info("Done sending %s\n", component);
return 0;
}
-int restore_send_restore_local_policy(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg)
+int restore_send_restore_local_policy(struct idevicerestore_client_t* client, plist_t message)
{
unsigned int size = 0;
unsigned char* data = NULL;
@@ -3782,7 +4342,7 @@ int restore_send_restore_local_policy(restored_client_t restore, struct idevicer
// The Update mode does not have a specific build identity for the recovery os.
plist_t build_identity = restore_get_build_identity(client, client->flags & FLAG_ERASE ? 1 : 0);
- int ret = get_recovery_os_local_policy_tss_response(client, build_identity, &client->tss_localpolicy, plist_dict_get_item(msg, "Arguments"));
+ int ret = get_recovery_os_local_policy_tss_response(client, build_identity, &client->tss_localpolicy, plist_dict_get_item(message, "Arguments"));
if (ret < 0) {
error("ERROR: Unable to get recovery os local policy tss response\n");
return -1;
@@ -3799,7 +4359,15 @@ int restore_send_restore_local_policy(restored_client_t restore, struct idevicer
plist_t dict = plist_new_dict();
plist_dict_set_item(dict, "Ap,LocalPolicy", plist_new_data((char*)data, size));
- int restore_error = restored_send(restore, dict);
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
+ int restore_error = 0;
+ restore_error = _restore_service_send(service, dict, 0);
+ _restore_service_free(service);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Unable to send component %s data\n", component);
return -1;
@@ -3811,19 +4379,25 @@ int restore_send_restore_local_policy(restored_client_t restore, struct idevicer
return 0;
}
-int restore_send_buildidentity(restored_client_t restore, struct idevicerestore_client_t* client, plist_t msg)
+int restore_send_buildidentity(struct idevicerestore_client_t* client, plist_t message)
{
restored_error_t restore_error;
plist_t dict;
+ restore_service_client_t service = _restore_get_service_client_for_data_request(client, message);
+ if (!service) {
+ error("ERROR: %s: Unable to connect to service client\n", __func__);
+ return -1;
+ }
+
info("About to send BuildIdentity Dict...\n");
- plist_t build_identity = restore_get_build_identity_from_request(client, msg);
+ plist_t build_identity = restore_get_build_identity_from_request(client, message);
dict = plist_new_dict();
plist_dict_set_item(dict, "BuildIdentityDict", plist_copy(build_identity));
- plist_t node = plist_access_path(msg, 2, "Arguments", "Variant");
+ plist_t node = plist_access_path(message, 2, "Arguments", "Variant");
if(node) {
plist_dict_set_item(dict, "Variant", plist_copy(node));
} else {
@@ -3831,7 +4405,8 @@ int restore_send_buildidentity(restored_client_t restore, struct idevicerestore_
}
info("Sending BuildIdentityDict now...\n");
- restore_error = restored_send(restore, dict);
+ restore_error = _restore_service_send(service, dict, 0);
+ _restore_service_free(service);
plist_free(dict);
if (restore_error != RESTORE_E_SUCCESS) {
error("ERROR: Unable to send BuildIdentityDict (%d)\n", restore_error);
@@ -3842,7 +4417,7 @@ int restore_send_buildidentity(restored_client_t restore, struct idevicerestore_
return 0;
}
-int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity)
+int restore_handle_data_request_msg(struct idevicerestore_client_t* client, plist_t message)
{
plist_t node = NULL;
@@ -3851,38 +4426,38 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
node = plist_dict_get_item(message, "DataType");
if (node && PLIST_STRING == plist_get_node_type(node)) {
const char *type = plist_get_string_ptr(node, NULL);
-
+debug("%s: type = %s\n", __func__, type);
// this request is sent when restored is ready to receive the filesystem
if (!strcmp(type, "SystemImageData")) {
- if(restore_send_filesystem(client, device, build_identity) < 0) {
+ if (restore_send_filesystem(client, message) < 0) {
error("ERROR: Unable to send filesystem\n");
return -2;
}
}
else if (!strcmp(type, "BuildIdentityDict")) {
- if (restore_send_buildidentity(restore, client, message) < 0) {
+ if (restore_send_buildidentity(client, message) < 0) {
error("ERROR: Unable to send RootTicket\n");
return -1;
}
}
else if (!strcmp(type, "PersonalizedBootObjectV3")) {
- if (restore_send_personalized_boot_object_v3(restore, client, message, build_identity) < 0) {
+ if (restore_send_personalized_boot_object_v3(client, message) < 0) {
error("ERROR: Unable to send PersonalizedBootObjectV3\n");
return -1;
}
}
else if (!strcmp(type, "SourceBootObjectV4")) {
- if (restore_send_source_boot_object_v4(restore, client, message, build_identity) < 0) {
+ if (restore_send_source_boot_object_v4(client, message) < 0) {
error("ERROR: Unable to send SourceBootObjectV4\n");
return -1;
}
}
else if (!strcmp(type, "RecoveryOSLocalPolicy")) {
- if (restore_send_restore_local_policy(restore, client, message) < 0) {
+ if (restore_send_restore_local_policy(client, message) < 0) {
error("ERROR: Unable to send RecoveryOSLocalPolicy\n");
return -1;
}
@@ -3890,7 +4465,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
// this request is sent when restored is ready to receive the filesystem
else if (!strcmp(type, "RecoveryOSASRImage")) {
- if(restore_send_filesystem(client, device, build_identity) < 0) {
+ if (restore_send_filesystem(client, message) < 0) {
error("ERROR: Unable to send filesystem\n");
return -2;
}
@@ -3898,7 +4473,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
// Send RecoveryOS RTD
else if(!strcmp(type, "RecoveryOSRootTicketData")) {
- if (restore_send_recovery_os_root_ticket(restore, client) < 0) {
+ if (restore_send_recovery_os_root_ticket(client, message) < 0) {
error("ERROR: Unable to send RootTicket\n");
return -1;
}
@@ -3906,35 +4481,35 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
// send RootTicket (== APTicket from the TSS request)
else if (!strcmp(type, "RootTicket")) {
- if (restore_send_root_ticket(restore, client) < 0) {
+ if (restore_send_root_ticket(client, message) < 0) {
error("ERROR: Unable to send RootTicket\n");
return -1;
}
}
// send KernelCache
else if (!strcmp(type, "KernelCache")) {
- if (restore_send_component(restore, client, build_identity, "KernelCache", NULL) < 0) {
+ if (restore_send_component(client, message, "KernelCache", NULL) < 0) {
error("ERROR: Unable to send kernelcache\n");
return -1;
}
}
else if (!strcmp(type, "DeviceTree")) {
- if (restore_send_component(restore, client, build_identity, "DeviceTree", NULL) < 0) {
+ if (restore_send_component(client, message, "DeviceTree", NULL) < 0) {
error("ERROR: Unable to send DeviceTree\n");
return -1;
}
}
else if (!strcmp(type, "SystemImageRootHash")) {
- if (restore_send_component(restore, client, build_identity, "SystemVolume", type) < 0) {
+ if (restore_send_component(client, message, "SystemVolume", type) < 0) {
error("ERROR: Unable to send SystemImageRootHash data\n");
return -1;
}
}
else if (!strcmp(type, "SystemImageCanonicalMetadata")) {
- if (restore_send_component(restore, client, build_identity, "Ap,SystemVolumeCanonicalMetadata", type) < 0) {
+ if (restore_send_component(client, message, "Ap,SystemVolumeCanonicalMetadata", type) < 0) {
error("ERROR: Unable to send SystemImageCanonicalMetadata data\n");
return -1;
}
@@ -3942,7 +4517,7 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
else if (!strcmp(type, "NORData")) {
if((client->flags & FLAG_EXCLUDE) == 0) {
- if(restore_send_nor(restore, client, build_identity, message) < 0) {
+ if(restore_send_nor(client, message) < 0) {
error("ERROR: Unable to send NOR data\n");
return -1;
}
@@ -3953,75 +4528,89 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
}
else if (!strcmp(type, "BasebandData")) {
- if(restore_send_baseband_data(restore, client, build_identity, message) < 0) {
+ if(restore_send_baseband_data(client, message) < 0) {
error("ERROR: Unable to send baseband data\n");
return -1;
}
}
else if (!strcmp(type, "FDRTrustData")) {
- if(restore_send_fdr_trust_data(restore, device) < 0) {
+ if(restore_send_fdr_trust_data(client, message) < 0) {
error("ERROR: Unable to send FDR Trust data\n");
return -1;
}
}
else if (!strcmp(type, "FUDData")) {
- if(restore_send_image_data(restore, client, build_identity, message, "FUDImageList", "IsFUDFirmware", "FUDImageData") < 0) {
+ if(restore_send_image_data(client, message, "FUDImageList", "IsFUDFirmware", "FUDImageData") < 0) {
error("ERROR: Unable to send FUD data\n");
return -1;
}
}
else if (!strcmp(type, "FirmwareUpdaterPreflight")) {
- if(restore_send_firmware_updater_preflight(restore, client, build_identity, message) < 0) {
+ if(restore_send_firmware_updater_preflight(client, message) < 0) {
error("ERROR: Unable to send FirmwareUpdaterPreflight\n");
return -1;
}
}
else if (!strcmp(type, "FirmwareUpdaterData")) {
- if(restore_send_firmware_updater_data(restore, client, build_identity, message) < 0) {
+ if(restore_send_firmware_updater_data(client, message) < 0) {
error("ERROR: Unable to send FirmwareUpdater data\n");
return -1;
}
}
else if (!strcmp(type, "PersonalizedData")) {
- if(restore_send_image_data(restore, client, build_identity, message, "ImageList", NULL, "ImageData") < 0) {
+ if(restore_send_image_data(client, message, "ImageList", NULL, "ImageData") < 0) {
error("ERROR: Unable to send Personalized data\n");
return -1;
}
}
else if (!strcmp(type, "EANData")) {
- if(restore_send_image_data(restore, client, build_identity, message, "EANImageList", "IsEarlyAccessFirmware", "EANData") < 0) {
+ if(restore_send_image_data(client, message, "EANImageList", "IsEarlyAccessFirmware", "EANData") < 0) {
error("ERROR: Unable to send Personalized data\n");
return -1;
}
}
else if (!strcmp(type, "BootabilityBundle")) {
- if (restore_send_bootability_bundle_data(restore, client, build_identity, message, device) < 0) {
+ if (restore_send_bootability_bundle_data(client, message) < 0) {
error("ERROR: Unable to send BootabilityBundle data\n");
return -1;
}
}
else if (!strcmp(type, "ReceiptManifest")) {
- if (restore_send_receipt_manifest(restore, client, build_identity) < 0) {
+ if (restore_send_receipt_manifest(client, message) < 0) {
error("ERROR: Unable to send ReceiptManifest data\n");
return -1;
}
}
else if (!strcmp(type, "BasebandUpdaterOutputData")) {
- if (restore_handle_baseband_updater_output_data(restore, client, device, message) < 0) {
+ if (restore_handle_baseband_updater_output_data(client, message) < 0) {
error("ERROR: Unable to send BasebandUpdaterOutputData data\n");
return -1;
}
}
+ else if (!strcmp(type, "URLAsset")) {
+ if (restore_send_url_asset(client, message) < 0) {
+ error("ERROR: Unable to send URLAsset data\n");
+ return -1;
+ }
+ }
+
+ else if (!strcmp(type, "StreamedImageDecryptionKey")) {
+ if (restore_send_streamed_image_decryption_key(client, message) < 0) {
+ error("ERROR: Unable to send StreamedImageDecryptionKey data\n");
+ return -1;
+ }
+ }
+
else {
// Unknown DataType!!
error("Unknown data request '%s' received\n", type);
@@ -4032,6 +4621,70 @@ int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idev
return 0;
}
+struct _restore_async_args {
+ struct idevicerestore_client_t* client;
+ plist_t message;
+};
+
+static void* _restore_handle_async_data_request(void* args)
+{
+ struct _restore_async_args* async_args = (struct _restore_async_args*)args;
+ struct idevicerestore_client_t* client = async_args->client;
+ plist_t message = async_args->message;
+ free(async_args);
+
+ int err = restore_handle_data_request_msg(client, message);
+ if (err < 0) {
+ client->async_err = err;
+ client->flags |= FLAG_QUIT;
+ }
+
+ plist_free(message);
+ return NULL;
+}
+
+static int restore_handle_restored_crash(struct idevicerestore_client_t* client, plist_t message)
+{
+ plist_t backtrace = plist_dict_get_item(message, "RestoredBacktrace");
+ info("*** restored crashed, backtrace following ***");
+ if (PLIST_IS_STRING(backtrace)) {
+ info("%s\n", plist_get_string_ptr(backtrace, NULL));
+ } else if (PLIST_IS_ARRAY(backtrace)) {
+ uint32_t i = 0;
+ for (i = 0; i < plist_array_get_size(backtrace); i++) {
+ plist_t line = plist_array_get_item(backtrace, i);
+ info("\t%s\n", plist_get_string_ptr(line, NULL));
+ }
+ } else {
+ debug_plist(message);
+ }
+ return 0;
+}
+
+static int restore_handle_async_wait(struct idevicerestore_client_t* client, plist_t message)
+{
+ debug("AsyncWait\n");
+ if (idevicerestore_debug)
+ debug_plist(message);
+ return 0;
+}
+
+static int restore_handle_restore_attestation(struct idevicerestore_client_t* client, plist_t message)
+{
+ if (idevicerestore_debug)
+ debug_plist(message);
+ debug("Sending RestoreShouldAttest: false\n");
+ plist_t dict = plist_new_dict();
+ plist_dict_set_item(dict, "RestoreShouldAttest", plist_new_bool(0));
+ restored_error_t restore_error = restored_send(client->restore->client, dict);
+ plist_free(dict);
+ if (restore_error != RESTORE_E_SUCCESS) {
+ error("ERROR: Unable to send RestoreShouldAttest (%d)\n", restore_error);
+ return -1;
+ }
+ return 0;
+}
+
// Extracted from ac2
plist_t restore_supported_data_types()
{
@@ -4098,6 +4751,10 @@ plist_t restore_supported_data_types()
plist_dict_set_item(dict, "RestoreLocalPolicy", plist_new_bool(1));
plist_dict_set_item(dict, "AuthInstallCACert", plist_new_bool(1));
plist_dict_set_item(dict, "OverlayRootDataForKeyIndex", plist_new_bool(1));
+ plist_dict_set_item(dict, "FirmwareUpdaterDataV3", plist_new_bool(1));
+ plist_dict_set_item(dict, "MessageUseStreamedImageFile", plist_new_bool(1));
+ plist_dict_set_item(dict, "UpdateVolumeOverlayRootDataCount", plist_new_bool(1));
+ plist_dict_set_item(dict, "URLAsset", plist_new_bool(1));
return dict;
}
@@ -4118,6 +4775,9 @@ plist_t restore_supported_message_types()
plist_dict_set_item(dict, "ReceivedFinalStatusMsg", plist_new_bool(0));
plist_dict_set_item(dict, "RestoredCrash", plist_new_bool(1));
plist_dict_set_item(dict, "StatusMsg", plist_new_bool(0));
+ plist_dict_set_item(dict, "AsyncDataRequestMsg", plist_new_bool(1));
+ plist_dict_set_item(dict, "AsyncWait", plist_new_bool(1));
+ plist_dict_set_item(dict, "RestoreAttestation", plist_new_bool(1));
return dict;
}
@@ -4157,6 +4817,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
}
info("Device %s has successfully entered restore mode\n", client->udid);
+ client->restore->build_identity = build_identity;
restore = client->restore->client;
device = client->restore->device;
@@ -4354,6 +5015,18 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
// FIXME: does this have any effect actually?
plist_dict_set_item(opts, "UpdateBaseband", plist_new_bool(0));
+ // Added for iOS 18.0 beta 1
+ plist_dict_set_item(opts, "HostHasFixFor99053849", plist_new_bool(1));
+ plist_dict_set_item(opts, "SystemImageFormat", plist_new_string("AEAWrappedDiskImage"));
+ plist_dict_set_item(opts, "WaitForDeviceConnectionToFinishStateMachine", plist_new_bool(0));
+ plist_t async_data_types = plist_new_dict();
+ plist_dict_set_item(async_data_types, "BasebandData", plist_new_bool(0));
+ plist_dict_set_item(async_data_types, "RecoveryOSASRImage", plist_new_bool(0));
+ plist_dict_set_item(async_data_types, "StreamedImageDecryptionKey", plist_new_bool(0));
+ plist_dict_set_item(async_data_types, "SystemImageData", plist_new_bool(0));
+ plist_dict_set_item(async_data_types, "URLAsset", plist_new_bool(1));
+ plist_dict_set_item(opts, "SupportedAsyncDataTypes", async_data_types);
+
plist_t sep = plist_access_path(build_identity, 3, "Manifest", "SEP", "Info");
if (sep) {
node = plist_dict_get_item(sep, "RequiredCapacity");
@@ -4456,7 +5129,22 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
// files sent to the server by the client. these data requests include
// SystemImageData, RootTicket, KernelCache, NORData and BasebandData requests
if (!strcmp(type, "DataRequestMsg")) {
- err = restore_handle_data_request_msg(client, device, restore, message, build_identity);
+ err = restore_handle_data_request_msg(client, message);
+ }
+
+ // async data request message
+ else if (!strcmp(type, "AsyncDataRequestMsg")) {
+ THREAD_T t = THREAD_T_NULL;
+ struct _restore_async_args* args = (struct _restore_async_args*)malloc(sizeof(struct _restore_async_args));
+ args->client = client;
+ args->message = plist_copy(message);
+ if (thread_new(&t, _restore_handle_async_data_request, args) < 0) {
+ free(args);
+ error("ERROR: Failed to start async data request handler thread!\n");
+ err = -1;
+ } else {
+ thread_detach(t);
+ }
}
// restore logs are available if a previous restore failed
@@ -4473,7 +5161,7 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
// status messages usually indicate the current state of the restored
// process or often to signal an error has been encountered
else if (!strcmp(type, "StatusMsg")) {
- err = restore_handle_status_msg(restore, message);
+ err = restore_handle_status_msg(client, message);
if (restore_finished) {
plist_t dict = plist_new_dict();
plist_dict_set_item(dict, "MsgType", plist_new_string("ReceivedFinalStatusMsg"));
@@ -4492,7 +5180,8 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
node = plist_dict_get_item(message, "CHECKPOINT_ID");
if (!node || plist_get_node_type(node) != PLIST_INT) {
debug("Failed to parse checkpoint id from checkpoint plist\n");
- return -1;
+ err = -1;
+ break;
}
plist_get_uint_val(node, &ckpt_id);
// Get checkpoint_name
@@ -4502,7 +5191,8 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
node = plist_dict_get_item(message, "CHECKPOINT_RESULT");
if (!node || plist_get_node_type(node) != PLIST_INT) {
debug("Failed to parse checkpoint result from checkpoint plist\n");
- return -1;
+ err = -1;
+ break;
}
plist_get_int_val(node, &ckpt_res);
// Get checkpoint complete
@@ -4528,12 +5218,26 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
// baseband update message
else if (!strcmp(type, "BBUpdateStatusMsg")) {
- err = restore_handle_bb_update_status_msg(restore, message);
+ err = restore_handle_bb_update_status_msg(client, message);
}
// baseband updater output data request
else if (!strcmp(type, "BasebandUpdaterOutputData")) {
- err = restore_handle_baseband_updater_output_data(restore, client, device, message);
+ err = restore_handle_baseband_updater_output_data(client, message);
+ }
+
+ // handle restored crash, print backtrace
+ else if (!strcmp(type, "RestoredCrash")) {
+ err = restore_handle_restored_crash(client, message);
+ }
+
+ // handle async wait
+ else if (!strcmp(type, "AsyncWait")) {
+ err = restore_handle_async_wait(client, message);
+ }
+
+ else if (!strcmp(type, "RestoreAttestation")) {
+ err = restore_handle_restore_attestation(client, message);
}
// there might be some other message types i'm not aware of, but I think
@@ -4548,6 +5252,9 @@ int restore_device(struct idevicerestore_client_t* client, plist_t build_identit
plist_free(message);
message = NULL;
}
+ if (client->async_err != 0) {
+ err = client->async_err;
+ }
#ifdef HAVE_REVERSE_PROXY
reverse_proxy_client_free(rproxy);
diff --git a/src/restore.h b/src/restore.h
index 765f374..763331d 100644
--- a/src/restore.h
+++ b/src/restore.h
@@ -40,6 +40,7 @@ struct restore_client_t {
unsigned int operation;
uint64_t protocol_version;
restored_client_t client;
+ plist_t build_identity;
};
int restore_check_mode(struct idevicerestore_client_t* client);
@@ -49,16 +50,16 @@ void restore_client_free(struct idevicerestore_client_t* client);
int restore_is_image4_supported(struct idevicerestore_client_t* client);
int restore_reboot(struct idevicerestore_client_t* client);
const char* restore_progress_string(unsigned int operation);
-int restore_handle_status_msg(restored_client_t client, plist_t msg);
-int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t msg);
-int restore_handle_data_request_msg(struct idevicerestore_client_t* client, idevice_t device, restored_client_t restore, plist_t message, plist_t build_identity);
-int restore_send_nor(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, plist_t message);
-int restore_send_root_ticket(restored_client_t restore, struct idevicerestore_client_t* client);
-int restore_send_component(restored_client_t restore, struct idevicerestore_client_t* client, plist_t build_identity, const char* component, const char* component_name);
+int restore_handle_status_msg(struct idevicerestore_client_t* client, plist_t message);
+int restore_handle_progress_msg(struct idevicerestore_client_t* client, plist_t message);
+int restore_handle_data_request_msg(struct idevicerestore_client_t* client, plist_t message);
+int restore_send_nor(struct idevicerestore_client_t* client, plist_t message);
+int restore_send_root_ticket(struct idevicerestore_client_t* client, plist_t message);
+int restore_send_component(struct idevicerestore_client_t* client, plist_t message, const char* component, const char* component_name);
int restore_device(struct idevicerestore_client_t* client, plist_t build_identity);
int restore_open_with_timeout(struct idevicerestore_client_t* client);
-int restore_send_filesystem(struct idevicerestore_client_t* client, idevice_t device, plist_t build_identity);
-int restore_send_fdr_trust_data(restored_client_t restore, idevice_t device);
+int restore_send_filesystem(struct idevicerestore_client_t* client, plist_t message);
+int restore_send_fdr_trust_data(struct idevicerestore_client_t* client, plist_t message);
#ifdef __cplusplus
}