diff options
Diffstat (limited to 'src/lockdown.c')
-rw-r--r-- | src/lockdown.c | 225 |
1 files changed, 135 insertions, 90 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index 49f757c..256bff0 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -34,13 +34,13 @@ #include <ctype.h> #include <unistd.h> #include <plist/plist.h> +#include <libimobiledevice-glue/utils.h> #include "property_list_service.h" #include "lockdown.h" #include "idevice.h" #include "common/debug.h" #include "common/userpref.h" -#include "common/utils.h" #include "asprintf.h" #ifdef WIN32 @@ -152,7 +152,7 @@ static lockdownd_error_t lockdownd_error(property_list_service_error_t err) * LOCKDOWN_E_UNKNOWN_ERROR when the result is 'Failure', * or a specific error code if derieved from the result. */ -static lockdownd_error_t lockdown_check_result(plist_t dict, const char *query_match) +lockdownd_error_t lockdown_check_result(plist_t dict, const char *query_match) { lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; @@ -163,53 +163,40 @@ static lockdownd_error_t lockdown_check_result(plist_t dict, const char *query_m if (plist_get_node_type(query_node) != PLIST_STRING) { return ret; - } else { - char *query_value = NULL; - - plist_get_string_val(query_node, &query_value); - if (!query_value) { - return ret; - } + } - if (query_match && (strcmp(query_value, query_match) != 0)) { - free(query_value); - return ret; - } + const char *query_value = plist_get_string_ptr(query_node, NULL); + if (!query_value) { + return ret; + } - free(query_value); + if (query_match && (strcmp(query_value, query_match) != 0)) { + return ret; } - plist_t result_node = plist_dict_get_item(dict, "Result"); - if (!result_node) { - /* iOS 5: the 'Result' key is not present anymore. - But we need to check for the 'Error' key. */ - plist_t err_node = plist_dict_get_item(dict, "Error"); - if (err_node) { - if (plist_get_node_type(err_node) == PLIST_STRING) { - char *err_value = NULL; - - plist_get_string_val(err_node, &err_value); - if (err_value) { - debug_info("ERROR: %s", err_value); - ret = lockdownd_strtoerr(err_value); - free(err_value); - } else { - debug_info("ERROR: unknown error occurred"); - } + /* Check for 'Error' in reply */ + plist_t err_node = plist_dict_get_item(dict, "Error"); + if (err_node) { + if (plist_get_node_type(err_node) == PLIST_STRING) { + const char *err_value = plist_get_string_ptr(err_node, NULL); + if (err_value) { + debug_info("ERROR: %s", err_value); + ret = lockdownd_strtoerr(err_value); + } else { + debug_info("ERROR: unknown error occurred"); } - return ret; } - - ret = LOCKDOWN_E_SUCCESS; - return ret; } - plist_type result_type = plist_get_node_type(result_node); - if (result_type == PLIST_STRING) { - char *result_value = NULL; - - plist_get_string_val(result_node, &result_value); + plist_t result_node = plist_dict_get_item(dict, "Result"); + if (!result_node) { + /* With iOS 5+ 'Result' is not present anymore. + If there is no 'Error', we can just assume success. */ + return LOCKDOWN_E_SUCCESS; + } + if (plist_get_node_type(result_node) == PLIST_STRING) { + const char *result_value = plist_get_string_ptr(result_node, NULL); if (result_value) { if (!strcmp(result_value, "Success")) { ret = LOCKDOWN_E_SUCCESS; @@ -219,9 +206,6 @@ static lockdownd_error_t lockdown_check_result(plist_t dict, const char *query_m debug_info("ERROR: unknown result value '%s'", result_value); } } - - if (result_value) - free(result_value); } return ret; @@ -242,7 +226,7 @@ static void plist_dict_add_label(plist_t plist, const char *label) } } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *session_id) +lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *session_id) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -311,12 +295,13 @@ static lockdownd_error_t lockdownd_client_free_simple(lockdownd_client_t client) free(client->session_id); client->session_id = NULL; } - if (client->udid) { - free(client->udid); - } if (client->label) { free(client->label); } + if (client->cu_key) { + free(client->cu_key); + client->cu_key = NULL; + } free(client); client = NULL; @@ -324,7 +309,7 @@ static lockdownd_error_t lockdownd_client_free_simple(lockdownd_client_t client) return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) +lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -340,7 +325,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_free(lockdownd_client_t return ret; } -LIBIMOBILEDEVICE_API void lockdownd_client_set_label(lockdownd_client_t client, const char *label) +void lockdownd_client_set_label(lockdownd_client_t client, const char *label) { if (client) { if (client->label) @@ -350,7 +335,7 @@ LIBIMOBILEDEVICE_API void lockdownd_client_set_label(lockdownd_client_t client, } } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_receive(lockdownd_client_t client, plist_t *plist) +lockdownd_error_t lockdownd_receive(lockdownd_client_t client, plist_t *plist) { if (!client || !plist || (plist && *plist)) return LOCKDOWN_E_INVALID_ARG; @@ -358,7 +343,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_receive(lockdownd_client_t clie return lockdownd_error(property_list_service_receive_plist(client->parent, plist)); } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist) +lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist) { if (!client || !plist) return LOCKDOWN_E_INVALID_ARG; @@ -366,7 +351,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_send(lockdownd_client_t client, return lockdownd_error(property_list_service_send_xml_plist(client->parent, plist)); } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_query_type(lockdownd_client_t client, char **type) +lockdownd_error_t lockdownd_query_type(lockdownd_client_t client, char **type) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -411,7 +396,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_query_type(lockdownd_client_t c return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_value(lockdownd_client_t client, const char *domain, const char *key, plist_t *value) +lockdownd_error_t lockdownd_get_value(lockdownd_client_t client, const char *domain, const char *key, plist_t *value) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -465,7 +450,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_value(lockdownd_client_t cl return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_set_value(lockdownd_client_t client, const char *domain, const char *key, plist_t value) +lockdownd_error_t lockdownd_set_value(lockdownd_client_t client, const char *domain, const char *key, plist_t value) { if (!client || !value) return LOCKDOWN_E_INVALID_ARG; @@ -513,7 +498,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_set_value(lockdownd_client_t cl return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_remove_value(lockdownd_client_t client, const char *domain, const char *key) +lockdownd_error_t lockdownd_remove_value(lockdownd_client_t client, const char *domain, const char *key) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -560,7 +545,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_remove_value(lockdownd_client_t return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_device_udid(lockdownd_client_t client, char **udid) +lockdownd_error_t lockdownd_get_device_udid(lockdownd_client_t client, char **udid) { lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; plist_t value = NULL; @@ -606,7 +591,7 @@ static lockdownd_error_t lockdownd_get_device_public_key_as_key_data(lockdownd_c return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_device_name(lockdownd_client_t client, char **device_name) +lockdownd_error_t lockdownd_get_device_name(lockdownd_client_t client, char **device_name) { lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; plist_t value = NULL; @@ -623,7 +608,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_device_name(lockdownd_clien return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, const char *label) +lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, const char *label) { if (!device || !client) return LOCKDOWN_E_INVALID_ARG; @@ -643,12 +628,13 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lo client_loc->parent = plistclient; client_loc->ssl_enabled = 0; client_loc->session_id = NULL; - client_loc->mux_id = device->mux_id; + client_loc->device = device; + client_loc->cu_key = NULL; + client_loc->cu_key_len = 0; - if (idevice_get_udid(device, &client_loc->udid) != IDEVICE_E_SUCCESS) { - debug_info("failed to get device udid."); + if (device->udid) { + debug_info("device udid: %s", device->udid); } - debug_info("device udid: %s", client_loc->udid); client_loc->label = label ? strdup(label) : NULL; @@ -657,7 +643,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lo return LOCKDOWN_E_SUCCESS; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdownd_client_t *client, const char *label) +lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdownd_client_t *client, const char *label) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -678,7 +664,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi ret = lockdownd_query_type(client_loc, &type); if (LOCKDOWN_E_SUCCESS != ret) { debug_info("QueryType failed in the lockdownd client."); - } else if (strcmp("com.apple.mobile.lockdown", type)) { + } else if (strcmp("com.apple.mobile.lockdown", type) != 0) { debug_info("Warning QueryType request returned \"%s\".", type); } free(type); @@ -696,8 +682,37 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi } plist_free(p_version); } + if (device->device_class == 0) { + plist_t p_device_class = NULL; + if (lockdownd_get_value(client_loc, NULL, "DeviceClass", &p_device_class) == LOCKDOWN_E_SUCCESS) { + char* s_device_class = NULL; + plist_get_string_val(p_device_class, &s_device_class); + if (s_device_class != NULL) { + if (!strcmp(s_device_class, "iPhone")) { + device->device_class = DEVICE_CLASS_IPHONE; + } else if (!strcmp(s_device_class, "iPad")) { + device->device_class = DEVICE_CLASS_IPAD; + } else if (!strcmp(s_device_class, "iPod")) { + device->device_class = DEVICE_CLASS_IPOD; + } else if (!strcmp(s_device_class, "Watch")) { + device->device_class = DEVICE_CLASS_WATCH; + } else if (!strcmp(s_device_class, "AppleTV")) { + device->device_class = DEVICE_CLASS_APPLETV; + } else { + device->device_class = DEVICE_CLASS_UNKNOWN; + } + free(s_device_class); + } + } + plist_free(p_device_class); + } - userpref_read_pair_record(client_loc->udid, &pair_record); + userpref_error_t uerr = userpref_read_pair_record(client_loc->device->udid, &pair_record); + if (uerr == USERPREF_E_READ_ERROR) { + debug_info("ERROR: Failed to retrieve pair record for %s", client_loc->device->udid); + lockdownd_client_free(client_loc); + return LOCKDOWN_E_RECEIVE_TIMEOUT; + } if (pair_record) { pair_record_get_host_id(pair_record, &host_id); } @@ -707,13 +722,15 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi if (LOCKDOWN_E_SUCCESS == ret && !pair_record) { /* attempt pairing */ + free(host_id); + host_id = NULL; ret = lockdownd_pair(client_loc, NULL); } plist_free(pair_record); pair_record = NULL; - if (device->version < DEVICE_VERSION(7,0,0)) { + if (device->version < DEVICE_VERSION(7,0,0) && device->device_class != DEVICE_CLASS_WATCH) { /* for older devices, we need to validate pairing to receive trusted host status */ ret = lockdownd_validate_pair(client_loc, NULL); @@ -730,7 +747,20 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi if (LOCKDOWN_E_SUCCESS == ret) { if (!host_id) { - userpref_read_pair_record(client_loc->udid, &pair_record); + uerr = userpref_read_pair_record(client_loc->device->udid, &pair_record); + if (uerr == USERPREF_E_READ_ERROR) { + debug_info("ERROR: Failed to retrieve pair record for %s", client_loc->device->udid); + lockdownd_client_free(client_loc); + return LOCKDOWN_E_RECEIVE_TIMEOUT; + } else if (uerr == USERPREF_E_NOENT) { + debug_info("ERROR: No pair record for %s", client_loc->device->udid); + lockdownd_client_free(client_loc); + return LOCKDOWN_E_INVALID_CONF; + } else if (uerr != USERPREF_E_SUCCESS) { + debug_info("ERROR: Failed to retrieve or parse pair record for %s", client_loc->device->udid); + lockdownd_client_free(client_loc); + return LOCKDOWN_E_INVALID_CONF; + } if (pair_record) { pair_record_get_host_id(pair_record, &host_id); plist_free(pair_record); @@ -894,9 +924,16 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ lockdownd_get_value(client, NULL, "WiFiAddress", &wifi_node); } else { /* use existing pair record */ - userpref_read_pair_record(client->udid, &pair_record_plist); - if (!pair_record_plist) { - return LOCKDOWN_E_INVALID_HOST_ID; + userpref_error_t uerr = userpref_read_pair_record(client->device->udid, &pair_record_plist); + if (uerr == USERPREF_E_READ_ERROR) { + debug_info("ERROR: Failed to retrieve pair record for %s", client->device->udid); + return LOCKDOWN_E_RECEIVE_TIMEOUT; + } else if (uerr == USERPREF_E_NOENT) { + debug_info("ERROR: No pair record for %s", client->device->udid); + return LOCKDOWN_E_INVALID_CONF; + } else if (uerr != USERPREF_E_SUCCESS) { + debug_info("ERROR: Failed to retrieve or parse pair record for %s", client->device->udid); + return LOCKDOWN_E_INVALID_CONF; } } } @@ -959,7 +996,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ debug_info("internal pairing mode"); if (!strcmp("Unpair", verb)) { /* remove public key from config */ - userpref_delete_pair_record(client->udid); + userpref_delete_pair_record(client->device->udid); } else { if (!strcmp("Pair", verb)) { /* add returned escrow bag if available */ @@ -977,7 +1014,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ wifi_node = NULL; } - userpref_save_pair_record(client->udid, client->mux_id, pair_record_plist); + userpref_save_pair_record(client->device->udid, client->device->mux_id, pair_record_plist); } } } else { @@ -1019,7 +1056,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) +lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) { plist_t options = plist_new_dict(); @@ -1032,22 +1069,22 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_pair(lockdownd_client_t client, return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_pair_with_options(lockdownd_client_t client, lockdownd_pair_record_t pair_record, plist_t options, plist_t *response) +lockdownd_error_t lockdownd_pair_with_options(lockdownd_client_t client, lockdownd_pair_record_t pair_record, plist_t options, plist_t *response) { return lockdownd_do_pair(client, pair_record, "Pair", options, response); } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) +lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) { return lockdownd_do_pair(client, pair_record, "ValidatePair", NULL, NULL); } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) +lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) { return lockdownd_do_pair(client, pair_record, "Unpair", NULL, NULL); } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_enter_recovery(lockdownd_client_t client) +lockdownd_error_t lockdownd_enter_recovery(lockdownd_client_t client) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -1077,7 +1114,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_enter_recovery(lockdownd_client return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client) +lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -1111,7 +1148,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_goodbye(lockdownd_client_t clie return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char *host_id, char **session_id, int *ssl_enabled) +lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char *host_id, char **session_id, int *ssl_enabled) { lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; plist_t dict = NULL; @@ -1226,9 +1263,17 @@ static lockdownd_error_t lockdownd_build_start_service_request(lockdownd_client_ if (send_escrow_bag) { /* get the pairing record */ plist_t pair_record = NULL; - userpref_read_pair_record(client->udid, &pair_record); - if (!pair_record) { - debug_info("ERROR: failed to read pair record for device: %s", client->udid); + userpref_error_t uerr = userpref_read_pair_record(client->device->udid, &pair_record); + if (uerr == USERPREF_E_READ_ERROR) { + debug_info("ERROR: Failed to retrieve pair record for %s", client->device->udid); + plist_free(dict); + return LOCKDOWN_E_RECEIVE_TIMEOUT; + } else if (uerr == USERPREF_E_NOENT) { + debug_info("ERROR: No pair record for %s", client->device->udid); + plist_free(dict); + return LOCKDOWN_E_INVALID_CONF; + } else if (uerr != USERPREF_E_SUCCESS) { + debug_info("ERROR: Failed to retrieve or parse pair record for %s", client->device->udid); plist_free(dict); return LOCKDOWN_E_INVALID_CONF; } @@ -1347,17 +1392,17 @@ static lockdownd_error_t lockdownd_do_start_service(lockdownd_client_t client, c return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, const char *identifier, lockdownd_service_descriptor_t *service) +lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, const char *identifier, lockdownd_service_descriptor_t *service) { return lockdownd_do_start_service(client, identifier, 0, service); } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_start_service_with_escrow_bag(lockdownd_client_t client, const char *identifier, lockdownd_service_descriptor_t *service) +lockdownd_error_t lockdownd_start_service_with_escrow_bag(lockdownd_client_t client, const char *identifier, lockdownd_service_descriptor_t *service) { return lockdownd_do_start_service(client, identifier, 1, service); } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_activate(lockdownd_client_t client, plist_t activation_record) +lockdownd_error_t lockdownd_activate(lockdownd_client_t client, plist_t activation_record) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -1396,7 +1441,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_activate(lockdownd_client_t cli return ret; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_deactivate(lockdownd_client_t client) +lockdownd_error_t lockdownd_deactivate(lockdownd_client_t client) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -1443,7 +1488,7 @@ static void str_remove_spaces(char *source) *dest = 0; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_sync_data_classes(lockdownd_client_t client, char ***classes, int *count) +lockdownd_error_t lockdownd_get_sync_data_classes(lockdownd_client_t client, char ***classes, int *count) { if (!client) return LOCKDOWN_E_INVALID_ARG; @@ -1498,7 +1543,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_sync_data_classes(lockdownd return LOCKDOWN_E_SUCCESS; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_data_classes_free(char **classes) +lockdownd_error_t lockdownd_data_classes_free(char **classes) { if (classes) { int i = 0; @@ -1510,7 +1555,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_data_classes_free(char **classe return LOCKDOWN_E_SUCCESS; } -LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_service_descriptor_free(lockdownd_service_descriptor_t service) +lockdownd_error_t lockdownd_service_descriptor_free(lockdownd_service_descriptor_t service) { if (service) { free(service->identifier); @@ -1520,7 +1565,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_service_descriptor_free(lockdow return LOCKDOWN_E_SUCCESS; } -LIBIMOBILEDEVICE_API const char* lockdownd_strerror(lockdownd_error_t err) +const char* lockdownd_strerror(lockdownd_error_t err) { switch (err) { case LOCKDOWN_E_SUCCESS: |