summaryrefslogtreecommitdiffstats
path: root/src/mobilebackup2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mobilebackup2.c')
-rw-r--r--src/mobilebackup2.c198
1 files changed, 51 insertions, 147 deletions
diff --git a/src/mobilebackup2.c b/src/mobilebackup2.c
index 4263e1c..a8d673f 100644
--- a/src/mobilebackup2.c
+++ b/src/mobilebackup2.c
@@ -1,36 +1,39 @@
/*
- * mobilebackup2.c
+ * mobilebackup2.c
* Contains functions for the built-in MobileBackup2 client (iOS4+ only)
- *
- * Copyright (c) 2010 Nikias Bassen All Rights Reserved.
+ *
+ * Copyright (c) 2010-2019 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <plist/plist.h>
#include <string.h>
#include <stdlib.h>
#include "mobilebackup2.h"
#include "device_link_service.h"
-#include "debug.h"
+#include "common/debug.h"
-#define MBACKUP2_VERSION_INT1 100
+#define MBACKUP2_VERSION_INT1 400
#define MBACKUP2_VERSION_INT2 0
-#define IS_FLAG_SET(x, y) ((x & y) == y)
+#define IS_FLAG_SET(x, y) (((x) & (y)) == (y))
/**
* Convert an device_link_service_error_t value to an mobilebackup2_error_t value.
@@ -53,6 +56,10 @@ static mobilebackup2_error_t mobilebackup2_error(device_link_service_error_t err
return MOBILEBACKUP2_E_PLIST_ERROR;
case DEVICE_LINK_SERVICE_E_MUX_ERROR:
return MOBILEBACKUP2_E_MUX_ERROR;
+ case DEVICE_LINK_SERVICE_E_SSL_ERROR:
+ return MOBILEBACKUP2_E_SSL_ERROR;
+ case DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT:
+ return MOBILEBACKUP2_E_RECEIVE_TIMEOUT;
case DEVICE_LINK_SERVICE_E_BAD_VERSION:
return MOBILEBACKUP2_E_BAD_VERSION;
default:
@@ -61,26 +68,14 @@ static mobilebackup2_error_t mobilebackup2_error(device_link_service_error_t err
return MOBILEBACKUP2_E_UNKNOWN_ERROR;
}
-/**
- * Connects to the mobilebackup2 service on the specified device.
- *
- * @param device The device to connect to.
- * @param port Destination port (usually given by lockdownd_start_service).
- * @param client Pointer that will be set to a newly allocated
- * mobilebackup2_client_t upon successful return.
- *
- * @return MOBILEBACKUP2_E_SUCCESS on success, MOBILEBACKUP2_E_INVALID ARG
- * if one or more parameter is invalid, or MOBILEBACKUP2_E_BAD_VERSION
- * if the mobilebackup2 version on the device is newer.
- */
-mobilebackup2_error_t mobilebackup2_client_new(idevice_t device, uint16_t port,
+mobilebackup2_error_t mobilebackup2_client_new(idevice_t device, lockdownd_service_descriptor_t service,
mobilebackup2_client_t * client)
{
- if (!device || port == 0 || !client || *client)
+ if (!device || !service || service->port == 0 || !client || *client)
return MOBILEBACKUP2_E_INVALID_ARG;
device_link_service_client_t dlclient = NULL;
- mobilebackup2_error_t ret = mobilebackup2_error(device_link_service_client_new(device, port, &dlclient));
+ mobilebackup2_error_t ret = mobilebackup2_error(device_link_service_client_new(device, service, &dlclient));
if (ret != MOBILEBACKUP2_E_SUCCESS) {
return ret;
}
@@ -101,15 +96,13 @@ mobilebackup2_error_t mobilebackup2_client_new(idevice_t device, uint16_t port,
return ret;
}
-/**
- * Disconnects a mobilebackup2 client from the device and frees up the
- * mobilebackup2 client data.
- *
- * @param client The mobilebackup2 client to disconnect and free.
- *
- * @return MOBILEBACKUP2_E_SUCCESS on success, or MOBILEBACKUP2_E_INVALID_ARG
- * if client is NULL.
- */
+mobilebackup2_error_t mobilebackup2_client_start_service(idevice_t device, mobilebackup2_client_t * client, const char* label)
+{
+ mobilebackup2_error_t err = MOBILEBACKUP2_E_UNKNOWN_ERROR;
+ service_client_factory_start_service(device, MOBILEBACKUP2_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(mobilebackup2_client_new), &err);
+ return err;
+}
+
mobilebackup2_error_t mobilebackup2_client_free(mobilebackup2_client_t client)
{
if (!client)
@@ -123,18 +116,6 @@ mobilebackup2_error_t mobilebackup2_client_free(mobilebackup2_client_t client)
return err;
}
-/**
- * Sends a backup message plist.
- *
- * @param client The connected MobileBackup client to use.
- * @param message The message to send. This will be inserted into the request
- * plist as value for MessageName. If this parameter is NULL,
- * the plist passed in the options parameter will be sent directly.
- * @param options Additional options as PLIST_DICT to add to the request.
- * The MessageName key with the value passed in the message parameter
- * will be inserted into this plist before sending it. This parameter
- * can be NULL if message is not NULL.
- */
mobilebackup2_error_t mobilebackup2_send_message(mobilebackup2_client_t client, const char *message, plist_t options)
{
if (!client || !client->parent || (!message && !options))
@@ -153,7 +134,7 @@ mobilebackup2_error_t mobilebackup2_send_message(mobilebackup2_client_t client,
} else {
dict = plist_new_dict();
}
- plist_dict_insert_item(dict, "MessageName", plist_new_string(message));
+ plist_dict_set_item(dict, "MessageName", plist_new_string(message));
/* send it as DLMessageProcessMessage */
err = mobilebackup2_error(device_link_service_send_process_message(client->parent, dict));
@@ -233,45 +214,11 @@ leave:
return err;
}
-/**
- * Receives a DL* message plist from the device.
- * This function is a wrapper around device_link_service_receive_message.
- *
- * @param client The connected MobileBackup client to use.
- * @param msg_plist Pointer to a plist that will be set to the contents of the
- * message plist upon successful return.
- * @param dlmessage A pointer that will be set to a newly allocated char*
- * containing the DL* string from the given plist. It is up to the caller
- * to free the allocated memory. If this parameter is NULL
- * it will be ignored.
- *
- * @return MOBILEBACKUP2_E_SUCCESS if a DL* message was received,
- * MOBILEBACKUP2_E_INVALID_ARG if client or message is invalid,
- * MOBILEBACKUP2_E_PLIST_ERROR if the received plist is invalid
- * or is not a DL* message plist, or MOBILEBACKUP2_E_MUX_ERROR if
- * receiving from the device failed.
- */
mobilebackup2_error_t mobilebackup2_receive_message(mobilebackup2_client_t client, plist_t *msg_plist, char **dlmessage)
{
return mobilebackup2_error(device_link_service_receive_message(client->parent, msg_plist, dlmessage));
}
-/**
- * Send binary data to the device.
- *
- * @note This function returns MOBILEBACKUP2_E_SUCCESS even if less than the
- * requested length has been sent. The fourth parameter is required and
- * must be checked to ensure if the whole data has been sent.
- *
- * @param client The MobileBackup client to send to.
- * @param data Pointer to the data to send
- * @param length Number of bytes to send
- * @param bytes Number of bytes actually sent
- *
- * @return MOBILEBACKUP2_E_SUCCESS if any data was successfully sent,
- * MOBILEBACKUP2_E_INVALID_ARG if one of the parameters is invalid,
- * or MOBILEBACKUP2_E_MUX_ERROR if sending of the data failed.
- */
mobilebackup2_error_t mobilebackup2_send_raw(mobilebackup2_client_t client, const char *data, uint32_t length, uint32_t *bytes)
{
if (!client || !client->parent || !data || (length == 0) || !bytes)
@@ -279,13 +226,13 @@ mobilebackup2_error_t mobilebackup2_send_raw(mobilebackup2_client_t client, cons
*bytes = 0;
- idevice_connection_t conn = client->parent->parent->connection;
+ service_client_t raw = client->parent->parent->parent;
int bytes_loc = 0;
uint32_t sent = 0;
do {
bytes_loc = 0;
- idevice_connection_send(conn, data+sent, length-sent, (uint32_t*)&bytes_loc);
+ service_send(raw, data+sent, length-sent, (uint32_t*)&bytes_loc);
if (bytes_loc <= 0)
break;
sent += bytes_loc;
@@ -293,35 +240,16 @@ mobilebackup2_error_t mobilebackup2_send_raw(mobilebackup2_client_t client, cons
if (sent > 0) {
*bytes = sent;
return MOBILEBACKUP2_E_SUCCESS;
- } else {
- return MOBILEBACKUP2_E_MUX_ERROR;
}
+ return MOBILEBACKUP2_E_MUX_ERROR;
}
-/**
- * Receive binary from the device.
- *
- * @note This function returns MOBILEBACKUP2_E_SUCCESS even if no data
- * has been received (unless a communication error occured).
- * The fourth parameter is required and must be checked to know how
- * many bytes were actually received.
- *
- * @param client The MobileBackup client to receive from.
- * @param data Pointer to a buffer that will be filled with the received data.
- * @param length Number of bytes to receive. The data buffer needs to be large
- * enough to store this amount of data.
- * @paran bytes Number of bytes actually received.
- *
- * @return MOBILEBACKUP2_E_SUCCESS if any or no data was received,
- * MOBILEBACKUP2_E_INVALID_ARG if one of the parameters is invalid,
- * or MOBILEBACKUP2_E_MUX_ERROR if receiving the data failed.
- */
mobilebackup2_error_t mobilebackup2_receive_raw(mobilebackup2_client_t client, char *data, uint32_t length, uint32_t *bytes)
{
if (!client || !client->parent || !data || (length == 0) || !bytes)
return MOBILEBACKUP2_E_INVALID_ARG;
- idevice_connection_t conn = client->parent->parent->connection;
+ service_client_t raw = client->parent->parent->parent;
*bytes = 0;
@@ -329,31 +257,20 @@ mobilebackup2_error_t mobilebackup2_receive_raw(mobilebackup2_client_t client, c
uint32_t received = 0;
do {
bytes_loc = 0;
- idevice_connection_receive(conn, data+received, length-received, (uint32_t*)&bytes_loc);
+ service_receive(raw, data+received, length-received, (uint32_t*)&bytes_loc);
if (bytes_loc <= 0) break;
received += bytes_loc;
} while (received < length);
if (received > 0) {
*bytes = received;
return MOBILEBACKUP2_E_SUCCESS;
- } else if (received == 0) {
+ }
+ if (received == 0) {
return MOBILEBACKUP2_E_SUCCESS;
- } else {
- return MOBILEBACKUP2_E_MUX_ERROR;
}
+ return MOBILEBACKUP2_E_MUX_ERROR;
}
-/**
- * Performs the mobilebackup2 protocol version exchange.
- *
- * @param client The MobileBackup client to use.
- * @param local_versions An array of supported versions to send to the remote.
- * @param count The number of items in local_versions.
- * @param remote_version Holds the protocol version of the remote on success.
- *
- * @return MOBILEBACKUP2_E_SUCCESS on success, or a MOBILEBACKUP2_E_* error
- * code otherwise.
- */
mobilebackup2_error_t mobilebackup2_version_exchange(mobilebackup2_client_t client, double local_versions[], char count, double *remote_version)
{
int i;
@@ -366,7 +283,7 @@ mobilebackup2_error_t mobilebackup2_version_exchange(mobilebackup2_client_t clie
for (i = 0; i < count; i++) {
plist_array_append_item(array, plist_new_real(local_versions[i]));
}
- plist_dict_insert_item(dict, "SupportedProtocolVersions", array);
+ plist_dict_set_item(dict, "SupportedProtocolVersions", array);
mobilebackup2_error_t err = mobilebackup2_send_message(client, "Hello", dict);
plist_free(dict);
@@ -412,31 +329,30 @@ leave:
return err;
}
-/**
- * Send a request to the connected mobilebackup2 service.
- *
- * @param client
- * @param request The request to send to the backup service.
- * Currently, this is one of "Backup", "Restore", "Info", or "List".
- * @param target_identifier UDID of the target device.
- * @param source_identifier UDID of backup data?
- * @param options Additional options in a plist of type PLIST_DICT.
- *
- * @return MOBILEBACKUP2_E_SUCCESS if the request was successfully sent,
- * or a MOBILEBACKUP2_E_* error value otherwise.
- */
mobilebackup2_error_t mobilebackup2_send_request(mobilebackup2_client_t client, const char *request, const char *target_identifier, const char *source_identifier, plist_t options)
{
if (!client || !client->parent || !request || !target_identifier)
return MOBILEBACKUP2_E_INVALID_ARG;
plist_t dict = plist_new_dict();
- plist_dict_insert_item(dict, "TargetIdentifier", plist_new_string(target_identifier));
+ plist_dict_set_item(dict, "TargetIdentifier", plist_new_string(target_identifier));
if (source_identifier) {
- plist_dict_insert_item(dict, "SourceIdentifier", plist_new_string(source_identifier));
+ plist_dict_set_item(dict, "SourceIdentifier", plist_new_string(source_identifier));
}
if (options) {
- plist_dict_insert_item(dict, "Options", plist_copy(options));
+ plist_dict_set_item(dict, "Options", plist_copy(options));
+ }
+ if (!strcmp(request, "Unback") && options) {
+ plist_t node = plist_dict_get_item(options, "Password");
+ if (node) {
+ plist_dict_set_item(dict, "Password", plist_copy(node));
+ }
+ }
+ if (!strcmp(request, "EnableCloudBackup") && options) {
+ plist_t node = plist_dict_get_item(options, "CloudBackupState");
+ if (node) {
+ plist_dict_set_item(dict, "CloudBackupState", plist_copy(node));
+ }
}
mobilebackup2_error_t err = mobilebackup2_send_message(client, request, dict);
plist_free(dict);
@@ -444,18 +360,6 @@ mobilebackup2_error_t mobilebackup2_send_request(mobilebackup2_client_t client,
return err;
}
-/**
- * Sends a DLMessageStatusResponse to the device.
- *
- * @param client The MobileBackup client to use.
- * @param status_code The status code to send.
- * @param status1 A status message to send. Can be NULL if not required.
- * @param status2 An additional status plist to attach to the response.
- * Can be NULL if not required.
- *
- * @return MOBILEBACKUP2_E_SUCCESS on success, MOBILEBACKUP2_E_INVALID_ARG
- * if client is invalid, or another MOBILEBACKUP2_E_* otherwise.
- */
mobilebackup2_error_t mobilebackup2_send_status_response(mobilebackup2_client_t client, int status_code, const char *status1, plist_t status2)
{
if (!client || !client->parent)