diff options
Diffstat (limited to 'src/lockdown.c')
-rw-r--r-- | src/lockdown.c | 385 |
1 files changed, 223 insertions, 162 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index 23f2782..256bff0 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -33,23 +33,14 @@ #include <stdio.h> #include <ctype.h> #include <unistd.h> -#ifdef HAVE_OPENSSL -#include <openssl/pem.h> -#include <openssl/x509.h> -#include <openssl/x509v3.h> -#else -#include <libtasn1.h> -#include <gnutls/x509.h> -#include <gnutls/crypto.h> -#endif #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 @@ -57,6 +48,46 @@ #define sleep(x) Sleep(x*1000) #endif +struct st_lockdownd_error_str_map { + const char *lockdown_errstr; + const char *errstr; + lockdownd_error_t errcode; +}; + +static struct st_lockdownd_error_str_map lockdownd_error_str_map[] = { + { "InvalidResponse", "Invalid response", LOCKDOWN_E_INVALID_RESPONSE }, + { "MissingKey", "Missing key", LOCKDOWN_E_MISSING_KEY }, + { "MissingValue", "Missing value", LOCKDOWN_E_MISSING_VALUE }, + { "GetProhibited", "Get value prohibited", LOCKDOWN_E_GET_PROHIBITED }, + { "SetProhibited", "Set value prohibited", LOCKDOWN_E_SET_PROHIBITED }, + { "RemoveProhibited", "Remove value prohibited", LOCKDOWN_E_REMOVE_PROHIBITED }, + { "ImmutableValue", "Immutable value", LOCKDOWN_E_IMMUTABLE_VALUE }, + { "PasswordProtected", "Password protected", LOCKDOWN_E_PASSWORD_PROTECTED }, + { "UserDeniedPairing", "User denied pairing", LOCKDOWN_E_USER_DENIED_PAIRING }, + { "PairingDialogResponsePending", "Pairing dialog response pending", LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING }, + { "MissingHostID", "Missing HostID", LOCKDOWN_E_MISSING_HOST_ID }, + { "InvalidHostID", "Invalid HostID", LOCKDOWN_E_INVALID_HOST_ID }, + { "SessionActive", "Session active", LOCKDOWN_E_SESSION_ACTIVE }, + { "SessionInactive", "Session inactive", LOCKDOWN_E_SESSION_INACTIVE }, + { "MissingSessionID", "Missing session ID", LOCKDOWN_E_MISSING_SESSION_ID }, + { "InvalidSessionID", "Invalid session ID", LOCKDOWN_E_INVALID_SESSION_ID }, + { "MissingService", "Missing service", LOCKDOWN_E_MISSING_SERVICE }, + { "InvalidService", "Invalid service", LOCKDOWN_E_INVALID_SERVICE }, + { "ServiceLimit", "Service limit reached", LOCKDOWN_E_SERVICE_LIMIT }, + { "MissingPairRecord", "Missing pair record", LOCKDOWN_E_MISSING_PAIR_RECORD }, + { "SavePairRecordFailed", "Saving pair record failed", LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED }, + { "InvalidPairRecord", "Invalid pair record", LOCKDOWN_E_INVALID_PAIR_RECORD }, + { "InvalidActivationRecord", "Invalid activation record", LOCKDOWN_E_INVALID_ACTIVATION_RECORD }, + { "MissingActivationRecord", "Missing activation record", LOCKDOWN_E_MISSING_ACTIVATION_RECORD }, + { "ServiceProhibited", "Service prohibited", LOCKDOWN_E_SERVICE_PROHIBITED }, + { "EscrowLocked", "Escrow lockded", LOCKDOWN_E_ESCROW_LOCKED }, + { "PairingProhibitedOverThisConnection", "Pairing prohibited over this connection", LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION }, + { "FMiPProtected", "Find My iPhone/iPod/iPad protected", LOCKDOWN_E_FMIP_PROTECTED }, + { "MCProtected", "MC protected" , LOCKDOWN_E_MC_PROTECTED }, + { "MCChallengeRequired", "MC challenge required", LOCKDOWN_E_MC_CHALLENGE_REQUIRED }, + { NULL, NULL, 0 } +}; + /** * Convert an error string identifier to a lockdownd_error_t value. * Used internally to get correct error codes from a response. @@ -69,69 +100,13 @@ static lockdownd_error_t lockdownd_strtoerr(const char* name) { lockdownd_error_t err = LOCKDOWN_E_UNKNOWN_ERROR; - - if (strcmp(name, "InvalidResponse") == 0) { - err = LOCKDOWN_E_INVALID_RESPONSE; - } else if (strcmp(name, "MissingKey") == 0) { - err = LOCKDOWN_E_MISSING_KEY; - } else if (strcmp(name, "MissingValue") == 0) { - err = LOCKDOWN_E_MISSING_VALUE; - } else if (strcmp(name, "GetProhibited") == 0) { - err = LOCKDOWN_E_GET_PROHIBITED; - } else if (strcmp(name, "SetProhibited") == 0) { - err = LOCKDOWN_E_SET_PROHIBITED; - } else if (strcmp(name, "RemoveProhibited") == 0) { - err = LOCKDOWN_E_REMOVE_PROHIBITED; - } else if (strcmp(name, "ImmutableValue") == 0) { - err = LOCKDOWN_E_IMMUTABLE_VALUE; - } else if (strcmp(name, "PasswordProtected") == 0) { - err = LOCKDOWN_E_PASSWORD_PROTECTED; - } else if (strcmp(name, "UserDeniedPairing") == 0) { - err = LOCKDOWN_E_USER_DENIED_PAIRING; - } else if (strcmp(name, "PairingDialogResponsePending") == 0) { - err = LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING; - } else if (strcmp(name, "MissingHostID") == 0) { - err = LOCKDOWN_E_MISSING_HOST_ID; - } else if (strcmp(name, "InvalidHostID") == 0) { - err = LOCKDOWN_E_INVALID_HOST_ID; - } else if (strcmp(name, "SessionActive") == 0) { - err = LOCKDOWN_E_SESSION_ACTIVE; - } else if (strcmp(name, "SessionInactive") == 0) { - err = LOCKDOWN_E_SESSION_INACTIVE; - } else if (strcmp(name, "MissingSessionID") == 0) { - err = LOCKDOWN_E_MISSING_SESSION_ID; - } else if (strcmp(name, "InvalidSessionID") == 0) { - err = LOCKDOWN_E_INVALID_SESSION_ID; - } else if (strcmp(name, "MissingService") == 0) { - err = LOCKDOWN_E_MISSING_SERVICE; - } else if (strcmp(name, "InvalidService") == 0) { - err = LOCKDOWN_E_INVALID_SERVICE; - } else if (strcmp(name, "ServiceLimit") == 0) { - err = LOCKDOWN_E_SERVICE_LIMIT; - } else if (strcmp(name, "MissingPairRecord") == 0) { - err = LOCKDOWN_E_MISSING_PAIR_RECORD; - } else if (strcmp(name, "SavePairRecordFailed") == 0) { - err = LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED; - } else if (strcmp(name, "InvalidPairRecord") == 0) { - err = LOCKDOWN_E_INVALID_PAIR_RECORD; - } else if (strcmp(name, "InvalidActivationRecord") == 0) { - err = LOCKDOWN_E_INVALID_ACTIVATION_RECORD; - } else if (strcmp(name, "MissingActivationRecord") == 0) { - err = LOCKDOWN_E_MISSING_ACTIVATION_RECORD; - } else if (strcmp(name, "ServiceProhibited") == 0) { - err = LOCKDOWN_E_SERVICE_PROHIBITED; - } else if (strcmp(name, "EscrowLocked") == 0) { - err = LOCKDOWN_E_ESCROW_LOCKED; - } else if (strcmp(name, "PairingProhibitedOverThisConnection") == 0) { - err = LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION; - } else if (strcmp(name, "FMiPProtected") == 0) { - err = LOCKDOWN_E_FMIP_PROTECTED; - } else if (strcmp(name, "MCProtected") == 0) { - err = LOCKDOWN_E_MC_PROTECTED; - } else if (strcmp(name, "MCChallengeRequired") == 0) { - err = LOCKDOWN_E_MC_CHALLENGE_REQUIRED; + int i = 0; + while (lockdownd_error_str_map[i].lockdown_errstr) { + if (strcmp(lockdownd_error_str_map[i].lockdown_errstr, name) == 0) { + return lockdownd_error_str_map[i].errcode; + } + i++; } - return err; } @@ -177,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; @@ -188,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; @@ -244,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; @@ -267,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; @@ -336,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; @@ -349,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; @@ -365,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) @@ -375,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; @@ -383,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; @@ -391,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; @@ -436,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; @@ -490,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; @@ -538,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; @@ -585,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; @@ -631,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; @@ -648,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; @@ -668,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; @@ -682,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; @@ -703,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); @@ -715,14 +676,43 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi char *s_version = NULL; plist_get_string_val(p_version, &s_version); if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { - device->version = ((vers[0] & 0xFF) << 16) | ((vers[1] & 0xFF) << 8) | (vers[2] & 0xFF); + device->version = DEVICE_VERSION(vers[0], vers[1], vers[2]); } free(s_version); } 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); } @@ -732,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 < 0x070000) { + 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); @@ -755,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); @@ -919,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; } } } @@ -984,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 */ @@ -1002,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 { @@ -1044,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(); @@ -1057,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; @@ -1102,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; @@ -1136,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; @@ -1251,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; } @@ -1332,6 +1352,7 @@ static lockdownd_error_t lockdownd_do_start_service(lockdownd_client_t client, c *service = (lockdownd_service_descriptor_t)malloc(sizeof(struct lockdownd_service_descriptor)); (*service)->port = 0; (*service)->ssl_enabled = 0; + (*service)->identifier = strdup(identifier); /* read service port number */ plist_t node = plist_dict_get_item(dict, "Port"); @@ -1371,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; @@ -1420,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; @@ -1467,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; @@ -1522,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; @@ -1534,10 +1555,50 @@ 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) + if (service) { + free(service->identifier); free(service); + } return LOCKDOWN_E_SUCCESS; } + +const char* lockdownd_strerror(lockdownd_error_t err) +{ + switch (err) { + case LOCKDOWN_E_SUCCESS: + return "Success"; + case LOCKDOWN_E_INVALID_ARG: + return "Invalid argument"; + case LOCKDOWN_E_INVALID_CONF: + return "Invalid configuration"; + case LOCKDOWN_E_PLIST_ERROR: + return "PropertyList error"; + case LOCKDOWN_E_PAIRING_FAILED: + return "Pairing failed"; + case LOCKDOWN_E_SSL_ERROR: + return "SSL error"; + case LOCKDOWN_E_DICT_ERROR: + return "Invalid dictionary"; + case LOCKDOWN_E_RECEIVE_TIMEOUT: + return "Receive timeout"; + case LOCKDOWN_E_MUX_ERROR: + return "Mux error"; + case LOCKDOWN_E_NO_RUNNING_SESSION: + return "No running session"; + case LOCKDOWN_E_UNKNOWN_ERROR: + return "Unknown Error"; + default: { + int i = 0; + while (lockdownd_error_str_map[i].lockdown_errstr) { + if (lockdownd_error_str_map[i].errcode == err) { + return lockdownd_error_str_map[i].errstr; + } + i++; + } + } break; + } + return "Unknown Error"; +} |