From 2c6121db9ad84b8aad05b937e071ff7dcc9c8867 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Wed, 24 Nov 2021 03:46:42 +0100 Subject: Add Reverse Proxy implementation --- include/Makefile.am | 1 + include/endianness.h | 12 ++ include/libimobiledevice/reverse_proxy.h | 209 +++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 include/libimobiledevice/reverse_proxy.h (limited to 'include') diff --git a/include/Makefile.am b/include/Makefile.am index e23b2a9..2abaf49 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -26,5 +26,6 @@ nobase_include_HEADERS = \ libimobiledevice/mobileactivation.h \ libimobiledevice/preboard.h \ libimobiledevice/companion_proxy.h \ + libimobiledevice/reverse_proxy.h \ libimobiledevice/property_list_service.h \ libimobiledevice/service.h diff --git a/include/endianness.h b/include/endianness.h index 2d6ad0e..1d414b3 100644 --- a/include/endianness.h +++ b/include/endianness.h @@ -31,6 +31,18 @@ #define htobe16 be16toh #endif +#ifndef le16toh +#if __BYTE_ORDER == __BIG_ENDIAN +#define le16toh(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8)) +#else +#define le16toh(x) (x) +#endif +#endif + +#ifndef htole16 +#define htole16 le16toh +#endif + #ifndef __bswap_32 #define __bswap_32(x) ((((x) & 0xFF000000) >> 24) \ | (((x) & 0x00FF0000) >> 8) \ diff --git a/include/libimobiledevice/reverse_proxy.h b/include/libimobiledevice/reverse_proxy.h new file mode 100644 index 0000000..2539bd9 --- /dev/null +++ b/include/libimobiledevice/reverse_proxy.h @@ -0,0 +1,209 @@ +/** + * @file libimobiledevice/reverse_proxy.h + * @brief Provide a reverse proxy to allow the device to communicate through, + * which is used during firmware restore. + * + * Copyright (c) 2021 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef IREVERSE_PROXY_H +#define IREVERSE_PROXY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define REVERSE_PROXY_DEFAULT_PORT 1082 + +/** Error Codes */ +typedef enum { + REVERSE_PROXY_E_SUCCESS = 0, + REVERSE_PROXY_E_INVALID_ARG = -1, + REVERSE_PROXY_E_PLIST_ERROR = -2, + REVERSE_PROXY_E_MUX_ERROR = -3, + REVERSE_PROXY_E_SSL_ERROR = -4, + REVERSE_PROXY_E_NOT_ENOUGH_DATA = -5, + REVERSE_PROXY_E_TIMEOUT = -6, + REVERSE_PROXY_E_UNKNOWN_ERROR = -256 +} reverse_proxy_error_t; + +typedef struct reverse_proxy_client_private reverse_proxy_client_private; +typedef reverse_proxy_client_private *reverse_proxy_client_t; /**< The client handle. */ + +typedef enum { + RP_TYPE_CTRL = 1, /**< control connection */ + RP_TYPE_CONN /**< proxy connection */ +} reverse_proxy_client_type_t; + +typedef enum { + RP_STATUS_READY = 1, /**< proxy is ready */ + RP_STATUS_TERMINATE, /**< proxy terminated */ + RP_STATUS_CONNECT_REQ, /**< connection request received (only RP_TYPE_CTRL) */ + RP_STATUS_SHUTDOWN_REQ, /**< shutdown request received (only RP_TYPE_CTRL) */ + RP_STATUS_CONNECTED, /**< connection established (only RP_TYPE_CONN) */ + RP_STATUS_DISCONNECTED, /**< connection closed (only RP_TYPE_CONN) */ +} reverse_proxy_status_t; + +typedef enum { + RP_DATA_DIRECTION_OUT = 1, /**< data going out to remote host */ + RP_DATA_DIRECTION_IN /**< data coming in from remote host */ +} reverse_proxy_data_direction_t; + +/** + * Log callback function prototype. + * + * @param client The client that called the callback function + * @param log_msg The log message + * @param user_data The user_data pointer that was set when registering the callback + */ +typedef void (*reverse_proxy_log_cb_t) (reverse_proxy_client_t client, const char* log_msg, void* user_data); + +/** + * Data callback function prototype. + * + * @param client The client that called the callback function + * @param direction The direction of the data, either RP_DATA_DIRECTION_OUT or RP_DATA_DIRECTION_IN + * @param buffer The data buffer + * @param length The length of the data buffer + * @param user_data The user_data pointer that was set when registering the callback + */ +typedef void (*reverse_proxy_data_cb_t) (reverse_proxy_client_t client, reverse_proxy_data_direction_t direction, const char* buffer, uint32_t length, void* user_data); + +/** + * Status callback function prototype. + * + * @param client The client that called the callback function + * @param status The status the client is reporting + * @param status_msg A status message the client reports along with the status + * @param user_data The user_data pointer that was set when registering the callback + */ +typedef void (*reverse_proxy_status_cb_t) (reverse_proxy_client_t client, reverse_proxy_status_t status, const char* status_msg, void* user_data); + +/** + * Create a reverse proxy client using com.apple.PurpleReverseProxy.Ctrl and + * com.apple.PurpleReverseProxy.Conn lockdown services. This will open a port + * 1083 on the device that iOS apps could connect to; \b however that is + * only allowed if an app has the com.apple.private.PurpleReverseProxy.allowed + * entitlement, which currently only \c /usr/libexec/fdrhelper holds. + * + * @note This function only creates and initializes the reverse proxy; + * to make it operational, call reverse_proxy_client_start_proxy(). + * + * @param device The device to connect to. + * @param client Pointer that will be set to a newly allocated #reverse_proxy_client_t + * upon successful return. + * @param label A label to pass to lockdownd when creating the service + * connections, usually the program name. + * + * @return REVERSE_PROXY_E_SUCCESS on success, + * or a REVERSE_PROXY_E_* error code otherwise. + */ +reverse_proxy_error_t reverse_proxy_client_create_with_service(idevice_t device, reverse_proxy_client_t* client, const char* label); + +/** + * Create a reverse proxy client using an open port on the device. This is + * used during firmware restores with the default port REVERSE_PROXY_DEFAULT_PORT (1082). + * + * @note This function only creates and initializes the reverse proxy; + * to make it operational, call reverse_proxy_client_start_proxy(). + * + * @param device The device to connect to. + * @param client Pointer that will be set to a newly allocated reverse_proxy_client_t + * upon successful return. + * @param device_port An open port on the device. Unless it's being used for + * a custom implementation, pass REVERSE_PROXY_DEFAULT_PORT here. + * + * @return REVERSE_PROXY_E_SUCCESS on success, + * or a REVERSE_PROXY_E_* error code otherwise. + */ +reverse_proxy_error_t reverse_proxy_client_create_with_port(idevice_t device, reverse_proxy_client_t* client, uint16_t device_port); + +/** + * Disconnects a reverse proxy client and frees up the client data. + * + * @param client The reverse proxy client to disconnect and free. + */ +reverse_proxy_error_t reverse_proxy_client_free(reverse_proxy_client_t client); + +/** + * Make an initialized reverse proxy client operational, i.e. start the actual proxy. + * + * @param client The reverse proxy client to start. + * @param control_protocol_version The control protocol version to use. + * This is either 1 or 2. Recent devices use 2. + * + * @return REVERSE_PROXY_E_SUCCESS on success, + * or a REVERSE_PROXY_E_* error code otherwise. + */ +reverse_proxy_error_t reverse_proxy_client_start_proxy(reverse_proxy_client_t client, int control_protocol_version); + +/** + * Set a status callback function. This allows to report the status of the + * reverse proxy, like Ready, Connect Request, Connected, etc. + * + * @note Set the callback before calling reverse_proxy_client_start_proxy(). + * + * @param client The reverse proxy client + * @param callback The status callback function that will be called + * when the status of the reverse proxy changes. + * @param user_data A pointer that will be passed to the callback function. + */ +void reverse_proxy_client_set_status_callback(reverse_proxy_client_t client, reverse_proxy_status_cb_t callback, void* user_data); + +/** + * Set a log callback function. Useful for debugging or verbosity. + * + * @note Set the callback before calling reverse_proxy_client_start_proxy(). + * + * @param client The reverse proxy client + * @param callback The log callback function that will be called + * when the reverse proxy logs something. + * @param user_data A pointer that will be passed to the callback function. + */ +void reverse_proxy_client_set_log_callback(reverse_proxy_client_t client, reverse_proxy_log_cb_t callback, void* user_data); + +/** + * Set a data callback function. Useful for debugging or extra verbosity. + * + * @note Set the callback before calling reverse_proxy_client_start_proxy(). + * + * @param client The reverse proxy client + * @param callback The status callback function that will be called + * when the status of the reverse proxy changes. + * @param user_data A pointer that will be passed to the callback function. + */ + +void reverse_proxy_client_set_data_callback(reverse_proxy_client_t client, reverse_proxy_data_cb_t callback, void* user_data); + +/** + * Helper function to return the type of a given reverse proxy client, which + * is either RP_TYPE_CTRL or RP_TYPE_CONN. Useful for callback functions. + * @see reverse_proxy_client_type_t + * + * @param client The reverse proxy client + * + * @return The type of the rerverse proxy client + */ +reverse_proxy_client_type_t reverse_proxy_get_type(reverse_proxy_client_t client); + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.1-32-gdbae