Skip to content

Commit

Permalink
Add Reverse Proxy implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
nikias committed Nov 24, 2021
1 parent fa8bfb6 commit 2c6121d
Show file tree
Hide file tree
Showing 6 changed files with 1,072 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions include/endianness.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
209 changes: 209 additions & 0 deletions include/libimobiledevice/reverse_proxy.h
Original file line number Diff line number Diff line change
@@ -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 <libimobiledevice/libimobiledevice.h>

#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
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ libimobiledevice_1_0_la_SOURCES = \
mobileactivation.c mobileactivation.h \
preboard.c preboard.h \
companion_proxy.c companion_proxy.h \
reverse_proxy.c reverse_proxy.h \
syslog_relay.c syslog_relay.h

if WIN32
Expand Down
Loading

0 comments on commit 2c6121d

Please sign in to comment.