From 0dbe76b4e75eef5d0e033aac99409fb6df36c512 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Mon, 3 Jul 2017 03:09:35 +0200 Subject: mobileactivation: Add new functions required for drmHandshake / session mode device activation --- include/libimobiledevice/mobileactivation.h | 47 +++++++++++++++++- src/mobileactivation.c | 75 ++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 3 deletions(-) diff --git a/include/libimobiledevice/mobileactivation.h b/include/libimobiledevice/mobileactivation.h index bb977fe..bb1f3f4 100644 --- a/include/libimobiledevice/mobileactivation.h +++ b/include/libimobiledevice/mobileactivation.h @@ -3,7 +3,7 @@ * @brief Handle device activation and deactivation. * \internal * - * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2016-2017 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 @@ -103,6 +103,20 @@ mobileactivation_error_t mobileactivation_client_free(mobileactivation_client_t */ mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state); +/** + * Retrieves a session blob required for 'drmHandshake' via albert.apple.com. + * + * @param client The mobileactivation client + * @param blob Pointer to a plist_t variable that will be set to the + * session blob created by the mobielactivation service. The + * consumer is responsible for freeing the returned object using + * plist_free(). + * + * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* + * error code otherwise. + */ +mobileactivation_error_t mobileactivation_create_activation_session_info(mobileactivation_client_t client, plist_t *blob); + /** * Retrieves the activation info required for device activation. * @@ -117,6 +131,24 @@ mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_ */ mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info); +/** + * Retrieves the activation info required for device activation in 'session' + * mode. This function expects a handshake result retrieved from + * https://albert.apple.com/deviceservies/drmHandshake with a blob + * provided by mobileactivation_create_activation_session_info(). + * + * @param client The mobileactivation client + * @aram handshake_result The handshake result returned from drmHandshake + * @param info Pointer to a plist_t variable that will be set to the + * activation info created by the mobileactivation service. The + * consumer is responsible for freeing the returned object using + * plist_free(). + * + * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* + * error code otherwise. + */ +mobileactivation_error_t mobileactivation_create_activation_info_with_session(mobileactivation_client_t client, plist_t handshake_result, plist_t *info); + /** * Activates the device with the given activation record. * The activation record plist dictionary must be obtained using the @@ -130,6 +162,19 @@ mobileactivation_error_t mobileactivation_create_activation_info(mobileactivatio */ mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t client, plist_t activation_record); +/** + * Activates the device with the given activation record in 'session' mode. + * The activation record plist dictionary must be obtained using the + * activation protocol requesting from Apple's https webservice. + * + * @param client The mobileactivation client + * @param activation_record The activation record plist dictionary + * + * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* + * error code otherwise. + */ +mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record); + /** * Deactivates the device. * diff --git a/src/mobileactivation.c b/src/mobileactivation.c index f14eb73..7ae35bb 100644 --- a/src/mobileactivation.c +++ b/src/mobileactivation.c @@ -2,7 +2,7 @@ * mobileactivation.c * com.apple.mobileactivationd service implementation. * - * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2016-2017 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 @@ -89,6 +89,17 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_free(mobil return MOBILEACTIVATION_E_SUCCESS; } +static plist_t plist_data_from_plist(plist_t plist) +{ + plist_t result = NULL; + char *xml = NULL; + uint32_t xml_len = 0; + plist_to_xml(plist, &xml, &xml_len); + result = plist_new_data(xml, xml_len); + free(xml); + return result; +} + static mobileactivation_error_t mobileactivation_check_result(plist_t dict, const char *command) { mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; @@ -104,8 +115,8 @@ static mobileactivation_error_t mobileactivation_check_result(plist_t dict, cons char *errmsg = NULL; plist_get_string_val(err_node, &errmsg); debug_info("ERROR: %s: %s", command, errmsg); - free(errmsg); ret = MOBILEACTIVATION_E_REQUEST_FAILED; + free(errmsg); } return ret; } @@ -160,6 +171,26 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_get_activation_st return ret; } +LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_session_info(mobileactivation_client_t client, plist_t *blob) +{ + if (!client || !blob) + return MOBILEACTIVATION_E_INVALID_ARG; + + plist_t result = NULL; + mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateTunnel1SessionInfoRequest", NULL, &result); + if (ret == MOBILEACTIVATION_E_SUCCESS) { + plist_t node = plist_dict_get_item(result, "Value"); + if (!node) { + debug_info("ERROR: CreateTunnel1SessionInfoRequest command returned success but has no value in reply"); + ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; + } else { + *blob = plist_copy(node); + } + } + + return ret; +} + LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info) { if (!client || !info) @@ -179,6 +210,30 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation plist_free(result); result = NULL; + return ret; +} + +LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info_with_session(mobileactivation_client_t client, plist_t handshake_response, plist_t *info) +{ + if (!client || !info) + return MOBILEACTIVATION_E_INVALID_ARG; + + plist_t result = NULL; + plist_t data = plist_data_from_plist(handshake_response); + mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateTunnel1ActivationInfoRequest", data, &result); + plist_free(data); + if (ret == MOBILEACTIVATION_E_SUCCESS) { + plist_t node = plist_dict_get_item(result, "Value"); + if (!node) { + debug_info("ERROR: CreateTunnel1ActivationInfoRequest command returned success but has no value in reply"); + ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; + } else { + *info = plist_copy(node); + } + } + plist_free(result); + result = NULL; + return ret; } @@ -195,6 +250,22 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate(mobileac return ret; } +LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record) +{ + if (!client || !activation_record) + return MOBILEACTIVATION_E_INVALID_ARG; + + plist_t result = NULL; + plist_t data = plist_data_from_plist(activation_record); + mobileactivation_error_t ret = mobileactivation_send_command(client, "HandleActivationInfoWithSessionRequest", data, &result); + plist_free(data); + plist_free(result); + result = NULL; + + return ret; +} + + LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client) { if (!client) -- cgit v1.1-32-gdbae