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; +} | 
