LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, const char *label) { if (!client) return LOCKDOWN_E_INVALID_ARG; static struct lockdownd_service_descriptor service = { 0xf27e, 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to lockdownd (device %s)", device->udid); return LOCKDOWN_E_MUX_ERROR; } lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_private)); client_loc->parent = plistclient; client_loc->ssl_enabled = 0; client_loc->session_id = NULL; if (idevice_get_udid(device, &client_loc->udid) != IDEVICE_E_SUCCESS) { debug_info("failed to get device udid."); } debug_info("device udid: %s", client_loc->udid); client_loc->label = label ? strdup(label) : NULL; *client = client_loc; return LOCKDOWN_E_SUCCESS; }
webinspector_error_t webinspector_client_new(idevice_t device, lockdownd_service_descriptor_t service, webinspector_client_t * client) { *client = NULL; if (!device || !service || service->port == 0 || !client || *client) { debug_info("Incorrect parameter passed to webinspector_client_new."); return WEBINSPECTOR_E_INVALID_ARG; } debug_info("Creating webinspector_client, port = %d.", service->port); property_list_service_client_t plclient = NULL; webinspector_error_t ret = webinspector_error(property_list_service_client_new(device, service, &plclient)); if (ret != WEBINSPECTOR_E_SUCCESS) { debug_info("Creating a property list client failed. Error: %i", ret); return ret; } webinspector_client_t client_loc = (webinspector_client_t) malloc(sizeof(struct webinspector_client_private)); client_loc->parent = plclient; *client = client_loc; debug_info("webinspector_client successfully created."); return 0; }
heartbeat_error_t heartbeat_client_new(idevice_t device, lockdownd_service_descriptor_t service, heartbeat_client_t * client) { *client = NULL; if (!device || !service || service->port == 0 || !client || *client) { debug_info("Incorrect parameter passed to heartbeat_client_new."); return HEARTBEAT_E_INVALID_ARG; } debug_info("Creating heartbeat_client, port = %d.", service->port); property_list_service_client_t plclient = NULL; heartbeat_error_t ret = heartbeat_error(property_list_service_client_new(device, service, &plclient)); if (ret != HEARTBEAT_E_SUCCESS) { debug_info("Creating a property list client failed. Error: %i", ret); return ret; } heartbeat_client_t client_loc = (heartbeat_client_t) malloc(sizeof(struct heartbeat_client_private)); client_loc->parent = plclient; *client = client_loc; debug_info("heartbeat_client successfully created."); return 0; }
LIBIMOBILEDEVICE_API misagent_error_t misagent_client_new(idevice_t device, lockdownd_service_descriptor_t service, misagent_client_t *client) { property_list_service_client_t plistclient = NULL; misagent_error_t err = misagent_error(property_list_service_client_new(device, service, &plistclient)); if (err != MISAGENT_E_SUCCESS) { return err; } misagent_client_t client_loc = (misagent_client_t) malloc(sizeof(struct misagent_client_private)); client_loc->parent = plistclient; client_loc->last_error = 0; *client = client_loc; return MISAGENT_E_SUCCESS; }
LIBIMOBILEDEVICE_API sbservices_error_t sbservices_client_new(idevice_t device, lockdownd_service_descriptor_t service, sbservices_client_t *client) { property_list_service_client_t plistclient = NULL; sbservices_error_t err = sbservices_error(property_list_service_client_new(device, service, &plistclient)); if (err != SBSERVICES_E_SUCCESS) { return err; } sbservices_client_t client_loc = (sbservices_client_t) malloc(sizeof(struct sbservices_client_private)); client_loc->parent = plistclient; mutex_init(&client_loc->mutex); *client = client_loc; return SBSERVICES_E_SUCCESS; }
/** * Connects to the house_arrest service on the specified device. * * @param device The device to connect to. * @param service The service descriptor returned by lockdownd_start_service. * @param client Pointer that will point to a newly allocated * housearrest_client_t upon successful return. * * @return HOUSE_ARREST_E_SUCCESS on success, HOUSE_ARREST_E_INVALID_ARG when * client is NULL, or an HOUSE_ARREST_E_* error code otherwise. */ house_arrest_error_t house_arrest_client_new(idevice_t device, lockdownd_service_descriptor_t service, house_arrest_client_t *client) { property_list_service_client_t plistclient = NULL; house_arrest_error_t err = house_arrest_error(property_list_service_client_new(device, service, &plistclient)); if (err != HOUSE_ARREST_E_SUCCESS) { return err; } house_arrest_client_t client_loc = (house_arrest_client_t) malloc(sizeof(struct house_arrest_client_private)); client_loc->parent = plistclient; client_loc->mode = HOUSE_ARREST_CLIENT_MODE_NORMAL; *client = client_loc; return HOUSE_ARREST_E_SUCCESS; }
/** * Connects to the mobile_image_mounter service on the specified device. * * @param device The device to connect to. * @param service The service descriptor returned by lockdownd_start_service. * @param client Pointer that will be set to a newly allocated * mobile_image_mounter_client_t upon successful return. * * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if device is NULL, * or MOBILE_IMAGE_MOUNTER_E_CONN_FAILED if the connection to the * device could not be established. */ mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, lockdownd_service_descriptor_t service, mobile_image_mounter_client_t *client) { property_list_service_client_t plistclient = NULL; mobile_image_mounter_error_t err = mobile_image_mounter_error(property_list_service_client_new(device, service, &plistclient)); if (err != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { return err; } mobile_image_mounter_client_t client_loc = (mobile_image_mounter_client_t) malloc(sizeof(struct mobile_image_mounter_client_private)); client_loc->parent = plistclient; mutex_init(&client_loc->mutex); *client = client_loc; return MOBILE_IMAGE_MOUNTER_E_SUCCESS; }
/** * Connects to the installation_proxy service on the specified device. * * @param device The device to connect to * @param service The service descriptor returned by lockdownd_start_service. * @param client Pointer that will be set to a newly allocated * instproxy_client_t upon successful return. * * @return INSTPROXY_E_SUCCESS on success, or an INSTPROXY_E_* error value * when an error occured. */ instproxy_error_t instproxy_client_new(idevice_t device, lockdownd_service_descriptor_t service, instproxy_client_t *client) { property_list_service_client_t plistclient = NULL; instproxy_error_t err = instproxy_error(property_list_service_client_new(device, service, &plistclient)); if (err != INSTPROXY_E_SUCCESS) { return err; } instproxy_client_t client_loc = (instproxy_client_t) malloc(sizeof(struct instproxy_client_private)); client_loc->parent = plistclient; mutex_init(&client_loc->mutex); client_loc->status_updater = (thread_t)NULL; *client = client_loc; return INSTPROXY_E_SUCCESS; }
LIBIMOBILEDEVICE_API np_error_t np_client_new(idevice_t device, lockdownd_service_descriptor_t service, np_client_t *client) { property_list_service_client_t plistclient = NULL; np_error_t err = np_error(property_list_service_client_new(device, service, &plistclient)); if (err != NP_E_SUCCESS) { return err; } np_client_t client_loc = (np_client_t) malloc(sizeof(struct np_client_private)); client_loc->parent = plistclient; mutex_init(&client_loc->mutex); client_loc->notifier = (thread_t)NULL; *client = client_loc; return NP_E_SUCCESS; }
LIBIMOBILEDEVICE_API restored_error_t restored_client_new(idevice_t device, restored_client_t *client, const char *label) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_SUCCESS; idevice_error_t idev_ret; static struct lockdownd_service_descriptor service = { /*.port = 0xf27e, .ssl_enabled = 0*/ 0xf27e, 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to restored (device %s)", device->udid); return RESTORE_E_MUX_ERROR; } restored_client_t client_loc = (restored_client_t) malloc(sizeof(struct restored_client_private)); client_loc->parent = plistclient; client_loc->udid = NULL; client_loc->label = NULL; client_loc->info = NULL; if (label != NULL) //client_loc->label = strdup(label); client_loc->label = _strdup(label); idev_ret = idevice_get_udid(device, &client_loc->udid); if (IDEVICE_E_SUCCESS != idev_ret) { debug_info("failed to get device udid."); ret = RESTORE_E_DEVICE_ERROR; } debug_info("device udid: %s", client_loc->udid); if (RESTORE_E_SUCCESS == ret) { *client = client_loc; } else { restored_client_free(client_loc); } return ret; }
/** * Connects to the house_arrest 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 point to a newly allocated * housearrest_client_t upon successful return. * * @return HOUSE_ARREST_E_SUCCESS on success, HOUSE_ARREST_E_INVALID_ARG when * client is NULL, or an HOUSE_ARREST_E_* error code otherwise. */ house_arrest_error_t house_arrest_client_new(idevice_t device, uint16_t port, house_arrest_client_t *client) { if (!device) return HOUSE_ARREST_E_INVALID_ARG; property_list_service_client_t plistclient = NULL; house_arrest_error_t err = house_arrest_error(property_list_service_client_new(device, port, &plistclient)); if (err != HOUSE_ARREST_E_SUCCESS) { return err; } house_arrest_client_t client_loc = (house_arrest_client_t) malloc(sizeof(struct house_arrest_client_private)); client_loc->parent = plistclient; client_loc->mode = HOUSE_ARREST_CLIENT_MODE_NORMAL; *client = client_loc; return HOUSE_ARREST_E_SUCCESS; }
LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_new(idevice_t device, lockdownd_service_descriptor_t service, mobileactivation_client_t *client) { if (!device || !service || service->port == 0 || !client || *client) { return MOBILEACTIVATION_E_INVALID_ARG; } property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return MOBILEACTIVATION_E_MUX_ERROR; } /* create client object */ mobileactivation_client_t client_loc = (mobileactivation_client_t) malloc(sizeof(struct mobileactivation_client_private)); client_loc->parent = plistclient; /* all done, return success */ *client = client_loc; return MOBILEACTIVATION_E_SUCCESS; }
/** * Connects to the diagnostics_relay service on the specified device. * * @param device The device to connect to. * @param service The service descriptor returned by lockdownd_start_service. * @param client Reference that will point to a newly allocated * diagnostics_relay_client_t upon successful return. * * @return DIAGNOSTICS_RELAY_E_SUCCESS on success, * DIAGNOSTICS_RELAY_E_INVALID_ARG when one of the parameters is invalid, * or DIAGNOSTICS_RELAY_E_MUX_ERROR when the connection failed. */ diagnostics_relay_error_t diagnostics_relay_client_new(idevice_t device, lockdownd_service_descriptor_t service, diagnostics_relay_client_t *client) { if (!device || !service || service->port == 0 || !client || *client) { return DIAGNOSTICS_RELAY_E_INVALID_ARG; } property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return DIAGNOSTICS_RELAY_E_MUX_ERROR; } /* create client object */ diagnostics_relay_client_t client_loc = (diagnostics_relay_client_t) malloc(sizeof(struct diagnostics_relay_client_private)); client_loc->parent = plistclient; /* all done, return success */ *client = client_loc; return DIAGNOSTICS_RELAY_E_SUCCESS; }
/** * Connects to the file_relay service on the specified device. * * @param device The device to connect to. * @param port Destination port (usually given by lockdownd_start_service). * @param client Reference that will point to a newly allocated * file_relay_client_t upon successful return. * * @return FILE_RELAY_E_SUCCESS on success, * FILE_RELAY_E_INVALID_ARG when one of the parameters is invalid, * or FILE_RELAY_E_MUX_ERROR when the connection failed. */ file_relay_error_t file_relay_client_new(idevice_t device, uint16_t port, file_relay_client_t *client) { if (!device || port == 0 || !client || *client) { return FILE_RELAY_E_INVALID_ARG; } property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return FILE_RELAY_E_MUX_ERROR; } /* create client object */ file_relay_client_t client_loc = (file_relay_client_t) malloc(sizeof(struct file_relay_client_private)); client_loc->parent = plistclient; /* all done, return success */ *client = client_loc; return FILE_RELAY_E_SUCCESS; }
/** * Connects to the mobile_image_mounter 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 * mobile_image_mounter_client_t upon successful return. * * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if device is NULL, * or MOBILE_IMAGE_MOUNTER_E_CONN_FAILED if the connection to the * device could not be established. */ mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, uint16_t port, mobile_image_mounter_client_t *client) { /* makes sure thread environment is available */ if (!g_thread_supported()) g_thread_init(NULL); if (!device) return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return MOBILE_IMAGE_MOUNTER_E_CONN_FAILED; } mobile_image_mounter_client_t client_loc = (mobile_image_mounter_client_t) malloc(sizeof(struct mobile_image_mounter_client_private)); client_loc->parent = plistclient; client_loc->mutex = g_mutex_new(); *client = client_loc; return MOBILE_IMAGE_MOUNTER_E_SUCCESS; }
/** * Connects to the springboardservices service on the specified device. * * @param device The device to connect to. * @param service The service descriptor returned by lockdownd_start_service. * @param client Pointer that will point to a newly allocated * sbservices_client_t upon successful return. * * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when * client is NULL, or an SBSERVICES_E_* error code otherwise. */ sbservices_error_t sbservices_client_new(idevice_t device, lockdownd_service_descriptor_t service, sbservices_client_t *client) { if (!device) return SBSERVICES_E_INVALID_ARG; property_list_service_client_t plistclient = NULL; sbservices_error_t err = sbservices_error(property_list_service_client_new(device, service, &plistclient)); if (err != SBSERVICES_E_SUCCESS) { return err; } sbservices_client_t client_loc = (sbservices_client_t) malloc(sizeof(struct sbservices_client_private)); client_loc->parent = plistclient; #ifdef WIN32 InitializeCriticalSection(&client_loc->mutex); #else pthread_mutex_init(&client_loc->mutex, NULL); #endif *client = client_loc; return SBSERVICES_E_SUCCESS; }
/** * Connects to the installation_proxy 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 * instproxy_client_t upon successful return. * * @return INSTPROXY_E_SUCCESS on success, or an INSTPROXY_E_* error value * when an error occured. */ instproxy_error_t instproxy_client_new(idevice_t device, uint16_t port, instproxy_client_t *client) { /* makes sure thread environment is available */ if (!g_thread_supported()) g_thread_init(NULL); if (!device) return INSTPROXY_E_INVALID_ARG; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return INSTPROXY_E_CONN_FAILED; } instproxy_client_t client_loc = (instproxy_client_t) malloc(sizeof(struct instproxy_client_private)); client_loc->parent = plistclient; client_loc->mutex = g_mutex_new(); client_loc->status_updater = NULL; *client = client_loc; return INSTPROXY_E_SUCCESS; }
/** * Connects to the notification_proxy on the specified device. * * @param device The device to connect to. * @param service The service descriptor returned by lockdownd_start_service. * @param client Pointer that will be set to a newly allocated np_client_t * upon successful return. * * @return NP_E_SUCCESS on success, NP_E_INVALID_ARG when device is NULL, * or NP_E_CONN_FAILED when the connection to the device could not be * established. */ np_error_t np_client_new(idevice_t device, lockdownd_service_descriptor_t service, np_client_t *client) { property_list_service_client_t plistclient = NULL; np_error_t err = np_error(property_list_service_client_new(device, service, &plistclient)); if (err != NP_E_SUCCESS) { return err; } np_client_t client_loc = (np_client_t) malloc(sizeof(struct np_client_private)); client_loc->parent = plistclient; #ifdef WIN32 InitializeCriticalSection(&client_loc->mutex); client_loc->notifier = NULL; #else pthread_mutex_init(&client_loc->mutex, NULL); client_loc->notifier = (pthread_t)NULL; #endif *client = client_loc; return NP_E_SUCCESS; }
/** * Connects to the installation_proxy 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 * instproxy_client_t upon successful return. * * @return INSTPROXY_E_SUCCESS on success, or an INSTPROXY_E_* error value * when an error occured. */ instproxy_error_t instproxy_client_new(idevice_t device, uint16_t port, instproxy_client_t *client) { if (!device) return INSTPROXY_E_INVALID_ARG; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return INSTPROXY_E_CONN_FAILED; } instproxy_client_t client_loc = (instproxy_client_t) malloc(sizeof(struct instproxy_client_private)); client_loc->parent = plistclient; #ifdef WIN32 InitializeCriticalSection(&client_loc->mutex); client_loc->status_updater = NULL; #else pthread_mutex_init(&client_loc->mutex, NULL); client_loc->status_updater = (pthread_t)NULL; #endif *client = client_loc; return INSTPROXY_E_SUCCESS; }
/** * Creates a new device link service client. * * @param device The device to connect to. * @param service The service descriptor returned by lockdownd_start_service. * @param client Reference that will point to a newly allocated * device_link_service_client_t upon successful return. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG when one of the parameters is invalid, * or DEVICE_LINK_SERVICE_E_MUX_ERROR when the connection failed. */ device_link_service_error_t device_link_service_client_new(idevice_t device, lockdownd_service_descriptor_t service, device_link_service_client_t *client) { if (!device || !service || service->port == 0 || !client || *client) { return DEVICE_LINK_SERVICE_E_INVALID_ARG; } property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return DEVICE_LINK_SERVICE_E_MUX_ERROR; } /* create client object */ device_link_service_client_t client_loc = (device_link_service_client_t) malloc(sizeof(struct device_link_service_client_private)); client_loc->parent = plistclient; /* enable SSL if requested */ if (service->ssl_enabled) property_list_service_enable_ssl(client_loc->parent); /* all done, return success */ *client = client_loc; return DEVICE_LINK_SERVICE_E_SUCCESS; }
/** * Creates a new restored client for the device. * * @param device The device to create a restored client for * @param client The pointer to the location of the new restored_client * @param label The label to use for communication. Usually the program name. * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL */ restored_error_t restored_client_new(idevice_t device, restored_client_t *client, const char *label) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_SUCCESS; static struct lockdownd_service_descriptor service = { .port = 0xf27e, .ssl_enabled = 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to restored (device %s)", device->udid); return RESTORE_E_MUX_ERROR; } restored_client_t client_loc = (restored_client_t) malloc(sizeof(struct restored_client_private)); client_loc->parent = plistclient; client_loc->udid = NULL; client_loc->label = NULL; client_loc->info = NULL; if (label != NULL) client_loc->label = strdup(label); ret = idevice_get_udid(device, &client_loc->udid); if (RESTORE_E_SUCCESS != ret) { debug_info("failed to get device udid."); } debug_info("device udid: %s", client_loc->udid); if (RESTORE_E_SUCCESS == ret) { *client = client_loc; } else { restored_client_free(client_loc); } return ret; } /** * Sends the Goodbye request to restored signaling the end of communication. * * @param client The restore client * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL, * RESTORE_E_PLIST_ERROR if the device did not acknowledge the request */ restored_error_t restored_goodbye(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("Goodbye")); debug_info("called"); ret = restored_send(client, dict); plist_free(dict); dict = NULL; ret = restored_receive(client, &dict); if (!dict) { debug_info("did not get goodbye response back"); return RESTORE_E_PLIST_ERROR; } if (restored_check_result(dict) == RESULT_SUCCESS) { debug_info("success"); ret = RESTORE_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; } /** * Requests to start a restore and retrieve it's port on success. * * @param client The restored client * @param options PLIST_DICT with options for the restore process or NULL * @param version the restore protocol version, see restored_query_type() * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG if a parameter * is NULL, RESTORE_E_START_RESTORE_FAILED if the request fails */ restored_error_t restored_start_restore(restored_client_t client, plist_t options, uint64_t version) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("StartRestore")); if (options) { plist_dict_insert_item(dict, "RestoreOptions", plist_copy(options)); } plist_dict_insert_item(dict,"RestoreProtocolVersion", plist_new_uint(version)); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; return ret; } /** * Requests device to reboot. * * @param client The restored client * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG if a parameter * is NULL */ restored_error_t restored_reboot(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("Reboot")); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; if (RESTORE_E_SUCCESS != ret) return ret; ret = restored_receive(client, &dict); if (RESTORE_E_SUCCESS != ret) return ret; if (!dict) return RESTORE_E_PLIST_ERROR; plist_free(dict); dict = NULL; return ret; }
LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, const char *label) { if (!client) return LOCKDOWN_E_INVALID_ARG; static struct lockdownd_service_descriptor service = { .port = 0xf27e, .ssl_enabled = 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to lockdownd (device %s)", device->udid); return LOCKDOWN_E_MUX_ERROR; } lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_private)); client_loc->parent = plistclient; client_loc->ssl_enabled = 0; client_loc->session_id = NULL; if (idevice_get_udid(device, &client_loc->udid) != IDEVICE_E_SUCCESS) { debug_info("failed to get device udid."); } debug_info("device udid: %s", client_loc->udid); client_loc->label = label ? strdup(label) : NULL; *client = client_loc; return LOCKDOWN_E_SUCCESS; } LIBIMOBILEDEVICE_API 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; lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; lockdownd_client_t client_loc = NULL; char *host_id = NULL; char *type = NULL; ret = lockdownd_client_new(device, &client_loc, label); if (LOCKDOWN_E_SUCCESS != ret) { debug_info("failed to create lockdownd client."); return ret; } /* perform handshake */ if (LOCKDOWN_E_SUCCESS != lockdownd_query_type(client_loc, &type)) { debug_info("QueryType failed in the lockdownd client."); ret = LOCKDOWN_E_NOT_ENOUGH_DATA; } else { if (strcmp("com.apple.mobile.lockdown", type)) { debug_info("Warning QueryType request returned \"%s\".", type); } } if (type) free(type); plist_t pair_record = NULL; userpref_read_pair_record(client_loc->udid, &pair_record); if (pair_record) { pair_record_get_host_id(pair_record, &host_id); } if (LOCKDOWN_E_SUCCESS == ret && !host_id) { ret = LOCKDOWN_E_INVALID_CONF; } if (LOCKDOWN_E_SUCCESS == ret && !pair_record) { /* attempt pairing */ ret = lockdownd_pair(client_loc, NULL); } plist_free(pair_record); pair_record = NULL; /* in any case, we need to validate pairing to receive trusted host status */ ret = lockdownd_validate_pair(client_loc, NULL); /* if not paired yet, let's do it now */ if (LOCKDOWN_E_INVALID_HOST_ID == ret) { ret = lockdownd_pair(client_loc, NULL); if (LOCKDOWN_E_SUCCESS == ret) { ret = lockdownd_validate_pair(client_loc, NULL); } else if (LOCKDOWN_E_PAIRING_DIALOG_PENDING == ret) { debug_info("Device shows the pairing dialog."); } } if (LOCKDOWN_E_SUCCESS == ret) { if (!host_id) { userpref_read_pair_record(client_loc->udid, &pair_record); if (pair_record) { pair_record_get_host_id(pair_record, &host_id); plist_free(pair_record); } } ret = lockdownd_start_session(client_loc, host_id, NULL, NULL); if (LOCKDOWN_E_SUCCESS != ret) { debug_info("Session opening failed."); } if (host_id) { free(host_id); host_id = NULL; } } if (LOCKDOWN_E_SUCCESS == ret) { *client = client_loc; } else { lockdownd_client_free(client_loc); } return ret; } /** * Returns a new plist from the supplied lockdownd pair record. The caller is * responsible for freeing the plist. * * @param pair_record The pair record to create a plist from. * * @return A pair record plist from the device, NULL if pair_record is not set */ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_record) { if (!pair_record) return NULL; /* setup request plist */ plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "DeviceCertificate", plist_new_data(pair_record->device_certificate, strlen(pair_record->device_certificate))); plist_dict_set_item(dict, "HostCertificate", plist_new_data(pair_record->host_certificate, strlen(pair_record->host_certificate))); plist_dict_set_item(dict, "HostID", plist_new_string(pair_record->host_id)); plist_dict_set_item(dict, "RootCertificate", plist_new_data(pair_record->root_certificate, strlen(pair_record->root_certificate))); plist_dict_set_item(dict, "SystemBUID", plist_new_string(pair_record->system_buid)); return dict; } /** * Generates a pair record plist with required certificates for a specific * device. If a pairing exists, it is loaded from the computer instead of being * generated. * * @param pair_record_plist Holds the pair record. * * @return LOCKDOWN_E_SUCCESS on success */ static lockdownd_error_t pair_record_generate(lockdownd_client_t client, plist_t *pair_record) { lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; key_data_t public_key = { NULL, 0 }; char* host_id = NULL; char* system_buid = NULL; /* retrieve device public key */ ret = lockdownd_get_device_public_key_as_key_data(client, &public_key); if (ret != LOCKDOWN_E_SUCCESS) { debug_info("device refused to send public key."); goto leave; } debug_info("device public key follows:\n%.*s", public_key.size, public_key.data); *pair_record = plist_new_dict(); /* generate keys and certificates into pair record */ userpref_error_t uret = USERPREF_E_SUCCESS; uret = pair_record_generate_keys_and_certs(*pair_record, public_key); switch(uret) { case USERPREF_E_INVALID_ARG: ret = LOCKDOWN_E_INVALID_ARG; break; case USERPREF_E_INVALID_CONF: ret = LOCKDOWN_E_INVALID_CONF; break; case USERPREF_E_SSL_ERROR: ret = LOCKDOWN_E_SSL_ERROR; default: break; } /* set SystemBUID */ userpref_read_system_buid(&system_buid); if (system_buid) { plist_dict_set_item(*pair_record, USERPREF_SYSTEM_BUID_KEY, plist_new_string(system_buid)); } /* set HostID */ host_id = generate_uuid(); pair_record_set_host_id(*pair_record, host_id); leave: if (host_id) free(host_id); if (system_buid) free(system_buid); if (public_key.data) free(public_key.data); return ret; }
LIBIMOBILEDEVICE_API restored_error_t restored_client_new(idevice_t device, restored_client_t *client, const char *label) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_SUCCESS; idevice_error_t idev_ret; static struct lockdownd_service_descriptor service = { .port = 0xf27e, .ssl_enabled = 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to restored (device %s)", device->udid); return RESTORE_E_MUX_ERROR; } restored_client_t client_loc = (restored_client_t) malloc(sizeof(struct restored_client_private)); client_loc->parent = plistclient; client_loc->udid = NULL; client_loc->label = NULL; client_loc->info = NULL; if (label != NULL) client_loc->label = strdup(label); idev_ret = idevice_get_udid(device, &client_loc->udid); if (IDEVICE_E_SUCCESS != idev_ret) { debug_info("failed to get device udid."); ret = RESTORE_E_DEVICE_ERROR; } debug_info("device udid: %s", client_loc->udid); if (RESTORE_E_SUCCESS == ret) { *client = client_loc; } else { restored_client_free(client_loc); } return ret; } LIBIMOBILEDEVICE_API restored_error_t restored_goodbye(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("Goodbye")); debug_info("called"); ret = restored_send(client, dict); plist_free(dict); dict = NULL; ret = restored_receive(client, &dict); if (!dict) { debug_info("did not get goodbye response back"); return RESTORE_E_PLIST_ERROR; } if (restored_check_result(dict) == RESULT_SUCCESS) { debug_info("success"); ret = RESTORE_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; } LIBIMOBILEDEVICE_API restored_error_t restored_start_restore(restored_client_t client, plist_t options, uint64_t version) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("StartRestore")); if (options) { plist_dict_set_item(dict, "RestoreOptions", plist_copy(options)); } plist_dict_set_item(dict,"RestoreProtocolVersion", plist_new_uint(version)); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; return ret; } LIBIMOBILEDEVICE_API restored_error_t restored_reboot(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("Reboot")); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; if (RESTORE_E_SUCCESS != ret) return ret; ret = restored_receive(client, &dict); if (RESTORE_E_SUCCESS != ret) return ret; if (!dict) return RESTORE_E_PLIST_ERROR; plist_free(dict); dict = NULL; return ret; }