diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile.am | 11 | ||||
-rw-r--r-- | tools/ideviceactivation.c | 297 |
2 files changed, 308 insertions, 0 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000..4eb9a7d --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,11 @@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libimobiledevice_CFLAGS) $(libplist_CFLAGS) +AM_LDFLAGS = $(GLOBAL_LIBS) $(libimobiledevice_LIBS) $(libplist_LIBS) + +bin_PROGRAMS = ideviceactivation + +ideviceactivation_SOURCES = ideviceactivation.c +ideviceactivation_CFLAGS = $(AM_CFLAGS) +ideviceactivation_LDFLAGS = $(AM_LDFLAGS) +ideviceactivation_LDADD = $(top_builddir)/src/libideviceactivation.la diff --git a/tools/ideviceactivation.c b/tools/ideviceactivation.c new file mode 100644 index 0000000..8fd5098 --- /dev/null +++ b/tools/ideviceactivation.c @@ -0,0 +1,297 @@ +/** + * @file ideviceactivate.h + * @brief A command line tool to handle the activation process. + * + * Copyright (c) 2011-2014 Mirell Development, 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 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <plist/plist.h> +#include <libimobiledevice/lockdown.h> +#include <libimobiledevice/libimobiledevice.h> +#include <libideviceactivation.h> + +static void print_usage(int argc, char **argv) +{ + char *name = NULL; + + name = strrchr(argv[0], '/'); + printf("Usage: %s COMMAND [OPTIONS]\n", (name ? name + 1: argv[0])); + printf("Activate or deactivate a device.\n\n"); + printf("Where COMMAND is one of:\n"); + printf(" activate\t\tattempt to activate the device\n"); + printf(" deactivate\t\tdeactivate the device\n"); + printf("\nThe following OPTIONS are accepted:\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +} + +int main(int argc, char *argv[]) +{ + idevice_t device = NULL; + idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; + lockdownd_client_t lockdown = NULL; + idevice_activation_request_t request = NULL; + idevice_activation_response_t response = NULL; + const char* response_title = NULL; + const char* response_description = NULL; + char* field_key = NULL; + char* field_label = NULL; + char input[1024]; + plist_t fields = NULL; + plist_dict_iter iter = NULL; + plist_t record = NULL; + char *udid = NULL; + int i; + int result = EXIT_FAILURE; + + typedef enum { + OP_NONE = 0, OP_ACTIVATE, OP_DEACTIVATE + } op_t; + op_t op = OP_NONE; + + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { + idevice_set_debug_level(1); + idevice_activation_set_debug_level(1); + continue; + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; + if (!argv[i] || (strlen(argv[i]) != 40)) { + print_usage(argc, argv); + return EXIT_FAILURE; + } + udid = argv[i]; + continue; + } + else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + print_usage(argc, argv); + return EXIT_SUCCESS; + } + else if (!strcmp(argv[i], "activate")) { + op = OP_ACTIVATE; + continue; + } + else if (!strcmp(argv[i], "deactivate")) { + op = OP_DEACTIVATE; + continue; + } + else { + print_usage(argc, argv); + return EXIT_SUCCESS; + } + } + + if (op == OP_NONE) { + print_usage(argc, argv); + return EXIT_FAILURE; + } + + if (udid) { + ret = idevice_new(&device, udid); + if (ret != IDEVICE_E_SUCCESS) { + printf("No device found with UDID %s, is it plugged in?\n", udid); + return EXIT_FAILURE; + } + } + else + { + ret = idevice_new(&device, NULL); + if (ret != IDEVICE_E_SUCCESS) { + printf("No device found, is it plugged in?\n"); + return EXIT_FAILURE; + } + } + + if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lockdown, "ideviceactivation")) { + result = EXIT_FAILURE; + goto cleanup; + } + + switch (op) { + case OP_DEACTIVATE: + // deactivate device using lockdown + if (LOCKDOWN_E_SUCCESS != lockdownd_deactivate(lockdown)) { + fprintf(stderr, "Failed to deactivate device.\n"); + result = EXIT_FAILURE; + goto cleanup; + } + + result = EXIT_SUCCESS; + printf("Successfully deactivated device.\n"); + break; + case OP_ACTIVATE: + default: + // create activation request + if (idevice_activation_request_new_from_lockdownd( + IDEVICE_ACTIVATION_CLIENT_MOBILE_ACTIVATION, lockdown, &request) != IDEVICE_ACTIVATION_E_SUCCESS) { + fprintf(stderr, "Failed to create activation request.\n"); + result = EXIT_FAILURE; + goto cleanup; + } + + while(1) { + if (idevice_activation_send_request(request, &response) != IDEVICE_ACTIVATION_E_SUCCESS) { + fprintf(stderr, "Failed to send request or retrieve response.\n"); + // Here response might have some content that could't be correctly interpreted (parsed) + // by the library. Printing out the content could help to identify the cause of the error. + result = EXIT_FAILURE; + goto cleanup; + } + + if (idevice_activation_response_is_activation_acknowledged(response)) { + printf("Activation server reports that device is already activated.\n"); + result = EXIT_SUCCESS; + goto cleanup; + } + + if (idevice_activation_response_has_errors(response)) { + fprintf(stderr, "Activation server repors errors.\n"); + + idevice_activation_response_get_title(response, &response_title); + if (response_title) { + fprintf(stderr, "\t%s\n", response_title); + } + + idevice_activation_response_get_description(response, &response_description); + if (response_description) { + fprintf(stderr, "\t%s\n", response_description); + } + result = EXIT_FAILURE; + goto cleanup; + } + + idevice_activation_response_get_activation_record(response, &record); + + if (record) { + // activate device using lockdown + if (LOCKDOWN_E_SUCCESS != lockdownd_activate(lockdown, record)) { + fprintf(stderr, "Failed to activate device with record.\n"); + result = EXIT_FAILURE; + goto cleanup; + } + + // set ActivationStateAcknowledged if we succeeded + if (LOCKDOWN_E_SUCCESS != lockdownd_set_value(lockdown, NULL, "ActivationStateAcknowledged", plist_new_bool(1))) { + fprintf(stderr, "Failed to set ActivationStateAcknowledged on device.\n"); + result = EXIT_FAILURE; + goto cleanup; + } + break; + } else { + idevice_activation_response_get_title(response, &response_title); + if (response_title) { + fprintf(stderr, "Server reports:\n%s\n", response_title); + } + + idevice_activation_response_get_description(response, &response_description); + if (response_description) { + fprintf(stderr, "Server reports:\n%s\n", response_description); + } + + idevice_activation_response_get_fields(response, &fields); + if (!fields || plist_dict_get_size(fields) == 0) { + // we have no activation record, no reported erros, no acknowledgment and no fields to send + fprintf(stderr, "Unknown error.\n"); + result = EXIT_FAILURE; + goto cleanup; + } + + plist_dict_new_iter(fields, &iter); + if (!iter) { + fprintf(stderr, "Unknown error.\n"); + result = EXIT_FAILURE; + goto cleanup; + } + + idevice_activation_request_free(request); + request = NULL; + if (idevice_activation_request_new( + IDEVICE_ACTIVATION_CLIENT_MOBILE_ACTIVATION, &request) != IDEVICE_ACTIVATION_E_SUCCESS) { + fprintf(stderr, "Could not create new request.\n"); + result = EXIT_FAILURE; + goto cleanup; + } + + idevice_activation_request_set_fields_from_response(request, response); + + do { + field_key = NULL; + plist_dict_next_item(fields, iter, &field_key, NULL); + if (field_key) { + if (idevice_activation_response_field_requires_input(response, field_key)) { + idevice_activation_response_get_label(response, field_key, &field_label); + printf("input %s: ", field_label ? field_label : field_key); + fflush(stdin); + scanf("%1023s", input); + idevice_activation_request_set_field(request, field_key, input); + if (field_label) { + free(field_label); + field_label = NULL; + } + } + } + } while(field_key); + + free(iter); + iter = NULL; + idevice_activation_response_free(response); + response = NULL; + } + + } + + result = EXIT_SUCCESS; + printf("Successfully activated device.\n"); + break; + } + +cleanup: + if (request) + idevice_activation_request_free(request); + + if (response) + idevice_activation_response_free(response); + + if (fields) + plist_free(fields); + + if (field_label) + free(field_label); + + if (iter) + free(iter); + + if (record) + plist_free(record); + + if (lockdown) + lockdownd_client_free(lockdown); + + if (device) + idevice_free(device); + + return result; +} |