summaryrefslogtreecommitdiffstats
path: root/tools/idevicepair.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/idevicepair.c')
-rw-r--r--tools/idevicepair.c473
1 files changed, 345 insertions, 128 deletions
diff --git a/tools/idevicepair.c b/tools/idevicepair.c
index b9676b9..94d3f04 100644
--- a/tools/idevicepair.c
+++ b/tools/idevicepair.c
@@ -1,114 +1,314 @@
1/* 1/*
2 * idevicepair.c 2 * idevicepair.c
3 * Simple utility to pair/unpair an iDevice 3 * Manage pairings with devices and this host
4 * 4 *
5 * Copyright (c) 2010 Nikias Bassen All Rights Reserved. 5 * Copyright (c) 2010-2021 Nikias Bassen, All Rights Reserved.
6 * Copyright (c) 2014 Martin Szulecki, All Rights Reserved.
6 * 7 *
7 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 9 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 11 * version 2.1 of the License, or (at your option) any later version.
11 * 12 *
12 * This library is distributed in the hope that it will be useful, 13 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 16 * Lesser General Public License for more details.
16 * 17 *
17 * You should have received a copy of the GNU Lesser General Public 18 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software 19 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 21 */
21 22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#define TOOL_NAME "idevicepair"
28
22#include <stdio.h> 29#include <stdio.h>
23#include <string.h> 30#include <string.h>
24#include <stdlib.h> 31#include <stdlib.h>
25#include <getopt.h> 32#include <getopt.h>
26#include "userpref.h" 33#include <ctype.h>
34#include <unistd.h>
35#ifdef WIN32
36#include <windows.h>
37#include <conio.h>
38#else
39#include <termios.h>
40#include <signal.h>
41#endif
42
43#include "common/userpref.h"
27 44
28#include <libimobiledevice/libimobiledevice.h> 45#include <libimobiledevice/libimobiledevice.h>
29#include <libimobiledevice/lockdown.h> 46#include <libimobiledevice/lockdown.h>
47#include <plist/plist.h>
48
49static char *udid = NULL;
30 50
31static char *uuid = NULL; 51#ifdef HAVE_WIRELESS_PAIRING
32 52
33static void print_usage(int argc, char **argv) 53#ifdef WIN32
54#define BS_CC '\b'
55#define my_getch getch
56#else
57#define BS_CC 0x7f
58static int my_getch(void)
34{ 59{
35 char *name = NULL; 60 struct termios oldt, newt;
36 61 int ch;
37 name = strrchr(argv[0], '/'); 62 tcgetattr(STDIN_FILENO, &oldt);
38 printf("\n%s - Manage pairings with iPhone/iPod Touch/iPad devices and this host.\n\n", (name ? name + 1: argv[0])); 63 newt = oldt;
39 printf("Usage: %s [OPTIONS] COMMAND\n\n", (name ? name + 1: argv[0])); 64 newt.c_lflag &= ~(ICANON | ECHO);
40 printf(" Where COMMAND is one of:\n"); 65 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
41 printf(" hostid print the host id of this computer\n"); 66 ch = getchar();
42 printf(" pair pair device with this computer\n"); 67 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
43 printf(" validate validate if device is paired with this computer\n"); 68 return ch;
44 printf(" unpair unpair device with this computer\n");
45 printf(" list list devices paired with this computer\n\n");
46 printf(" The following OPTIONS are accepted:\n");
47 printf(" -d, --debug enable communication debugging\n");
48 printf(" -u, --uuid UUID target specific device by its 40-digit device UUID\n");
49 printf(" -h, --help prints usage information\n");
50 printf("\n");
51} 69}
70#endif
52 71
53static void parse_opts(int argc, char **argv) 72static int get_hidden_input(char *buf, int maxlen)
54{ 73{
55 static struct option longopts[] = { 74 int pwlen = 0;
56 {"help", 0, NULL, 'h'},
57 {"uuid", 1, NULL, 'u'},
58 {"debug", 0, NULL, 'd'},
59 {NULL, 0, NULL, 0}
60 };
61 int c; 75 int c;
62 76
63 while (1) { 77 while ((c = my_getch())) {
64 c = getopt_long(argc, argv, "hu:d", longopts, (int*)0); 78 if ((c == '\r') || (c == '\n')) {
65 if (c == -1) {
66 break; 79 break;
80 } else if (isprint(c)) {
81 if (pwlen < maxlen-1)
82 buf[pwlen++] = c;
83 fputc('*', stderr);
84 } else if (c == BS_CC) {
85 if (pwlen > 0) {
86 fputs("\b \b", stderr);
87 pwlen--;
88 }
67 } 89 }
90 }
91 buf[pwlen] = 0;
92 return pwlen;
93}
68 94
69 switch (c) { 95static void pairing_cb(lockdownd_cu_pairing_cb_type_t cb_type, void *user_data, void* data_ptr, unsigned int* data_size)
70 case 'h': 96{
71 print_usage(argc, argv); 97 if (cb_type == LOCKDOWN_CU_PAIRING_PIN_REQUESTED) {
72 exit(EXIT_SUCCESS); 98 printf("Enter PIN: ");
73 case 'u': 99 fflush(stdout);
74 if (strlen(optarg) != 40) { 100
75 printf("%s: invalid UUID specified (length != 40)\n", argv[0]); 101 *data_size = get_hidden_input((char*)data_ptr, *data_size);
76 print_usage(argc, argv); 102
77 exit(2); 103 printf("\n");
78 } 104 } else if (cb_type == LOCKDOWN_CU_PAIRING_DEVICE_INFO) {
79 uuid = strdup(optarg); 105 printf("Device info:\n");
106 plist_write_to_stream((plist_t)data_ptr, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_INDENT | PLIST_OPT_INDENT_BY(2));
107 } else if (cb_type == LOCKDOWN_CU_PAIRING_ERROR) {
108 printf("ERROR: %s\n", (data_ptr) ? (char*)data_ptr : "(unknown)");
109 }
110}
111
112#endif /* HAVE_WIRELESS_PAIRING */
113
114static void print_error_message(lockdownd_error_t err)
115{
116 switch (err) {
117 case LOCKDOWN_E_PASSWORD_PROTECTED:
118 printf("ERROR: Could not validate with device %s because a passcode is set. Please enter the passcode on the device and retry.\n", udid);
80 break; 119 break;
81 case 'd': 120 case LOCKDOWN_E_INVALID_CONF:
82 idevice_set_debug_level(1); 121 case LOCKDOWN_E_INVALID_HOST_ID:
122 printf("ERROR: Device %s is not paired with this host\n", udid);
123 break;
124 case LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING:
125 printf("ERROR: Please accept the trust dialog on the screen of device %s, then attempt to pair again.\n", udid);
126 break;
127 case LOCKDOWN_E_USER_DENIED_PAIRING:
128 printf("ERROR: Device %s said that the user denied the trust dialog.\n", udid);
129 break;
130 case LOCKDOWN_E_PAIRING_FAILED:
131 printf("ERROR: Pairing with device %s failed.\n", udid);
132 break;
133 case LOCKDOWN_E_GET_PROHIBITED:
134 case LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION:
135 printf("ERROR: Pairing is not possible over this connection.\n");
136#ifdef HAVE_WIRELESS_PAIRING
137 printf("To perform a wireless pairing use the -w command line switch. See usage or man page for details.\n");
138#endif
83 break; 139 break;
84 default: 140 default:
85 print_usage(argc, argv); 141 printf("ERROR: Device %s returned unhandled error code %d\n", udid, err);
86 exit(EXIT_SUCCESS); 142 break;
87 }
88 } 143 }
89} 144}
90 145
146static void print_usage(int argc, char **argv, int is_error)
147{
148 char *name = strrchr(argv[0], '/');
149 fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] COMMAND\n", (name ? name + 1: argv[0]));
150 fprintf(is_error ? stderr : stdout,
151 "\n"
152 "Manage host pairings with devices and usbmuxd.\n"
153 "\n"
154 "Where COMMAND is one of:\n"
155 " systembuid print the system buid of the usbmuxd host\n"
156 " hostid print the host id for target device\n"
157 " pair pair device with this host\n"
158 " validate validate if device is paired with this host\n"
159 " unpair unpair device with this host\n"
160 " list list devices paired with this host\n"
161 "\n"
162 "The following OPTIONS are accepted:\n"
163 " -u, --udid UDID target specific device by UDID\n"
164 );
165#ifdef HAVE_WIRELESS_PAIRING
166 fprintf(is_error ? stderr : stdout,
167 " -w, --wireless perform wireless pairing (see NOTE)\n"
168 " -n, --network connect to network device (see NOTE)\n"
169 );
170#endif
171 fprintf(is_error ? stderr : stdout,
172 " -d, --debug enable communication debugging\n"
173 " -h, --help prints usage information\n"
174 " -v, --version prints version information\n"
175 );
176#ifdef HAVE_WIRELESS_PAIRING
177 fprintf(is_error ? stderr : stdout,
178 "\n"
179 "NOTE: Pairing over network (wireless pairing) is only supported by Apple TV\n"
180 "devices. To perform a wireless pairing, you need to use the -w command line\n"
181 "switch. Make sure to put the device into pairing mode first by opening\n"
182 "Settings > Remotes and Devices > Remote App and Devices.\n"
183 );
184#endif
185 fprintf(is_error ? stderr : stdout,
186 "\n"
187 "Homepage: <" PACKAGE_URL ">\n"
188 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
189 );
190}
191
91int main(int argc, char **argv) 192int main(int argc, char **argv)
92{ 193{
194 int c = 0;
195 static struct option longopts[] = {
196 { "help", no_argument, NULL, 'h' },
197 { "udid", required_argument, NULL, 'u' },
198#ifdef HAVE_WIRELESS_PAIRING
199 { "wireless", no_argument, NULL, 'w' },
200 { "network", no_argument, NULL, 'n' },
201 { "hostinfo", required_argument, NULL, 1 },
202#endif
203 { "debug", no_argument, NULL, 'd' },
204 { "version", no_argument, NULL, 'v' },
205 { NULL, 0, NULL, 0}
206 };
207#ifdef HAVE_WIRELESS_PAIRING
208#define SHORT_OPTIONS "hu:wndv"
209#else
210#define SHORT_OPTIONS "hu:dv"
211#endif
93 lockdownd_client_t client = NULL; 212 lockdownd_client_t client = NULL;
94 idevice_t phone = NULL; 213 idevice_t device = NULL;
95 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; 214 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
96 lockdownd_error_t lerr; 215 lockdownd_error_t lerr;
97 int result; 216 int result;
98 217
99 char *type = NULL; 218 char *type = NULL;
219 int use_network = 0;
220 int wireless_pairing = 0;
221#ifdef HAVE_WIRELESS_PAIRING
222 plist_t host_info_plist = NULL;
223#endif
100 char *cmd; 224 char *cmd;
101 typedef enum { 225 typedef enum {
102 OP_NONE = 0, OP_PAIR, OP_VALIDATE, OP_UNPAIR, OP_LIST, OP_HOSTID 226 OP_NONE = 0, OP_PAIR, OP_VALIDATE, OP_UNPAIR, OP_LIST, OP_HOSTID, OP_SYSTEMBUID
103 } op_t; 227 } op_t;
104 op_t op = OP_NONE; 228 op_t op = OP_NONE;
105 229
106 parse_opts(argc, argv); 230 while ((c = getopt_long(argc, argv, SHORT_OPTIONS, longopts, NULL)) != -1) {
231 switch (c) {
232 case 'h':
233 print_usage(argc, argv, 0);
234 exit(EXIT_SUCCESS);
235 case 'u':
236 if (!*optarg) {
237 fprintf(stderr, "ERROR: UDID must not be empty!\n");
238 print_usage(argc, argv, 1);
239 result = EXIT_FAILURE;
240 goto leave;
241 }
242 free(udid);
243 udid = strdup(optarg);
244 break;
245#ifdef HAVE_WIRELESS_PAIRING
246 case 'w':
247 wireless_pairing = 1;
248 break;
249 case 'n':
250 use_network = 1;
251 break;
252 case 1:
253 if (!*optarg) {
254 fprintf(stderr, "ERROR: --hostinfo argument must not be empty!\n");
255 result = EXIT_FAILURE;
256 goto leave;
257 }
258 if (*optarg == '@') {
259 plist_read_from_file(optarg+1, &host_info_plist, NULL);
260 if (!host_info_plist) {
261 fprintf(stderr, "ERROR: Could not read from file '%s'\n", optarg+1);
262 result = EXIT_FAILURE;
263 goto leave;
264 }
265 }
266#ifdef HAVE_PLIST_JSON
267 else if (*optarg == '{') {
268 if (plist_from_json(optarg, strlen(optarg), &host_info_plist) != PLIST_ERR_SUCCESS) {
269 fprintf(stderr, "ERROR: --hostinfo argument not valid. Make sure it is a JSON dictionary.\n");
270 result = EXIT_FAILURE;
271 goto leave;
272 }
273 }
274#endif
275 else {
276 fprintf(stderr, "ERROR: --hostinfo argument not valid. To specify a path prefix with '@'\n");
277 result = EXIT_FAILURE;
278 goto leave;
279 }
280 break;
281#endif
282 case 'd':
283 idevice_set_debug_level(1);
284 break;
285 case 'v':
286 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
287 result = EXIT_SUCCESS;
288 goto leave;
289 default:
290 print_usage(argc, argv, 1);
291 result = EXIT_FAILURE;
292 goto leave;
293 }
294 }
295
296#ifndef WIN32
297 signal(SIGPIPE, SIG_IGN);
298#endif
107 299
108 if ((argc - optind) < 1) { 300 if ((argc - optind) < 1) {
109 printf("ERROR: You need to specify a COMMAND!\n"); 301 fprintf(stderr, "ERROR: You need to specify a COMMAND!\n");
110 print_usage(argc, argv); 302 print_usage(argc, argv, 1);
111 exit(EXIT_FAILURE); 303 result = EXIT_FAILURE;
304 goto leave;
305 }
306
307 if (wireless_pairing && use_network) {
308 fprintf(stderr, "ERROR: You cannot use -w and -n together.\n");
309 print_usage(argc, argv, 1);
310 result = EXIT_FAILURE;
311 goto leave;
112 } 312 }
113 313
114 cmd = (argv+optind)[0]; 314 cmd = (argv+optind)[0];
@@ -123,60 +323,91 @@ int main(int argc, char **argv)
123 op = OP_LIST; 323 op = OP_LIST;
124 } else if (!strcmp(cmd, "hostid")) { 324 } else if (!strcmp(cmd, "hostid")) {
125 op = OP_HOSTID; 325 op = OP_HOSTID;
326 } else if (!strcmp(cmd, "systembuid")) {
327 op = OP_SYSTEMBUID;
126 } else { 328 } else {
127 printf("ERROR: Invalid command '%s' specified\n", cmd); 329 fprintf(stderr, "ERROR: Invalid command '%s' specified\n", cmd);
128 print_usage(argc, argv); 330 print_usage(argc, argv, 1);
129 exit(EXIT_FAILURE); 331 result = EXIT_FAILURE;
332 goto leave;
130 } 333 }
131 334
132 if (op == OP_HOSTID) { 335 if (wireless_pairing) {
133 char *hostid = NULL; 336 if (op == OP_VALIDATE || op == OP_UNPAIR) {
134 userpref_get_host_id(&hostid); 337 fprintf(stderr, "ERROR: Command '%s' is not supported with -w\n", cmd);
338 print_usage(argc, argv, 1);
339 result = EXIT_FAILURE;
340 goto leave;
341 }
342 use_network = 1;
343 }
135 344
136 printf("%s\n", hostid); 345 if (op == OP_SYSTEMBUID) {
346 char *systembuid = NULL;
347 userpref_read_system_buid(&systembuid);
137 348
138 if (hostid) 349 printf("%s\n", systembuid);
139 free(hostid);
140 350
141 return EXIT_SUCCESS; 351 free(systembuid);
352
353 result = EXIT_SUCCESS;
354 goto leave;
142 } 355 }
143 356
144 if (op == OP_LIST) { 357 if (op == OP_LIST) {
145 unsigned int i; 358 unsigned int i;
146 char **uuids = NULL; 359 char **udids = NULL;
147 unsigned int count = 0; 360 unsigned int count = 0;
148 userpref_get_paired_uuids(&uuids, &count); 361 userpref_get_paired_udids(&udids, &count);
149 for (i = 0; i < count; i++) { 362 for (i = 0; i < count; i++) {
150 printf("%s\n", uuids[i]); 363 printf("%s\n", udids[i]);
364 free(udids[i]);
151 } 365 }
152 if (uuids) 366 free(udids);
153 g_strfreev(uuids); 367 result = EXIT_SUCCESS;
154 if (uuid) 368 goto leave;
155 free(uuid);
156 return EXIT_SUCCESS;
157 } 369 }
158 370
159 if (uuid) { 371 ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
160 ret = idevice_new(&phone, uuid); 372 if (ret != IDEVICE_E_SUCCESS) {
161 free(uuid); 373 if (udid) {
162 uuid = NULL; 374 printf("No device found with udid %s.\n", udid);
163 if (ret != IDEVICE_E_SUCCESS) { 375 } else {
164 printf("No device found with uuid %s, is it plugged in?\n", uuid); 376 printf("No device found.\n");
165 return EXIT_FAILURE;
166 } 377 }
167 } else { 378 result = EXIT_FAILURE;
168 ret = idevice_new(&phone, NULL); 379 goto leave;
380 }
381 if (!udid) {
382 ret = idevice_get_udid(device, &udid);
169 if (ret != IDEVICE_E_SUCCESS) { 383 if (ret != IDEVICE_E_SUCCESS) {
170 printf("No device found, is it plugged in?\n"); 384 printf("ERROR: Could not get device udid, error code %d\n", ret);
171 return EXIT_FAILURE; 385 result = EXIT_FAILURE;
386 goto leave;
172 } 387 }
173 } 388 }
174 389
175 lerr = lockdownd_client_new(phone, &client, "idevicepair"); 390 if (op == OP_HOSTID) {
391 plist_t pair_record = NULL;
392 char *hostid = NULL;
393
394 userpref_read_pair_record(udid, &pair_record);
395 pair_record_get_host_id(pair_record, &hostid);
396
397 printf("%s\n", hostid);
398
399 free(hostid);
400 plist_free(pair_record);
401
402 result = EXIT_SUCCESS;
403 goto leave;
404 }
405
406 lerr = lockdownd_client_new(device, &client, TOOL_NAME);
176 if (lerr != LOCKDOWN_E_SUCCESS) { 407 if (lerr != LOCKDOWN_E_SUCCESS) {
177 idevice_free(phone); 408 printf("ERROR: Could not connect to lockdownd, error code %d\n", lerr);
178 printf("ERROR: lockdownd_client_new failed with error code %d\n", lerr); 409 result = EXIT_FAILURE;
179 return EXIT_FAILURE; 410 goto leave;
180 } 411 }
181 412
182 result = EXIT_SUCCESS; 413 result = EXIT_SUCCESS;
@@ -187,76 +418,62 @@ int main(int argc, char **argv)
187 result = EXIT_FAILURE; 418 result = EXIT_FAILURE;
188 goto leave; 419 goto leave;
189 } else { 420 } else {
190 if (strcmp("com.apple.mobile.lockdown", type)) { 421 if (strcmp("com.apple.mobile.lockdown", type) != 0) {
191 printf("WARNING: QueryType request returned '%s'\n", type); 422 printf("WARNING: QueryType request returned '%s'\n", type);
192 } 423 }
193 if (type) { 424 free(type);
194 free(type);
195 }
196 }
197
198 ret = idevice_get_uuid(phone, &uuid);
199 if (ret != IDEVICE_E_SUCCESS) {
200 printf("ERROR: Could not get device uuid, error code %d\n", ret);
201 result = EXIT_FAILURE;
202 goto leave;
203 } 425 }
204 426
205 switch(op) { 427 switch(op) {
206 default: 428 default:
207 case OP_PAIR: 429 case OP_PAIR:
208 lerr = lockdownd_pair(client, NULL); 430#ifdef HAVE_WIRELESS_PAIRING
431 if (wireless_pairing) {
432 lerr = lockdownd_cu_pairing_create(client, pairing_cb, NULL, host_info_plist, NULL);
433 if (lerr == LOCKDOWN_E_SUCCESS) {
434 lerr = lockdownd_pair_cu(client);
435 }
436 } else
437#endif
438 {
439 lerr = lockdownd_pair(client, NULL);
440 }
209 if (lerr == LOCKDOWN_E_SUCCESS) { 441 if (lerr == LOCKDOWN_E_SUCCESS) {
210 printf("SUCCESS: Paired with device %s\n", uuid); 442 printf("SUCCESS: Paired with device %s\n", udid);
211 } else { 443 } else {
212 result = EXIT_FAILURE; 444 result = EXIT_FAILURE;
213 if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { 445 print_error_message(lerr);
214 printf("ERROR: Could not pair with the device because a passcode is set. Please enter the passcode on the device and retry.\n");
215 } else {
216 printf("ERROR: Pairing with device %s failed with unhandled error code %d\n", uuid, lerr);
217 }
218 } 446 }
219 break; 447 break;
220 448
221 case OP_VALIDATE: 449 case OP_VALIDATE:
222 lerr = lockdownd_validate_pair(client, NULL); 450 lockdownd_client_free(client);
451 client = NULL;
452 lerr = lockdownd_client_new_with_handshake(device, &client, TOOL_NAME);
223 if (lerr == LOCKDOWN_E_SUCCESS) { 453 if (lerr == LOCKDOWN_E_SUCCESS) {
224 printf("SUCCESS: Validated pairing with device %s\n", uuid); 454 printf("SUCCESS: Validated pairing with device %s\n", udid);
225 } else { 455 } else {
226 result = EXIT_FAILURE; 456 result = EXIT_FAILURE;
227 if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { 457 print_error_message(lerr);
228 printf("ERROR: Could not validate with the device because a passcode is set. Please enter the passcode on the device and retry.\n");
229 } else if (lerr == LOCKDOWN_E_INVALID_HOST_ID) {
230 printf("ERROR: Device %s is not paired with this host\n", uuid);
231 } else {
232 printf("ERROR: Pairing failed with unhandled error code %d\n", lerr);
233 }
234 } 458 }
235 break; 459 break;
236 460
237 case OP_UNPAIR: 461 case OP_UNPAIR:
238 lerr = lockdownd_unpair(client, NULL); 462 lerr = lockdownd_unpair(client, NULL);
239 if (lerr == LOCKDOWN_E_SUCCESS) { 463 if (lerr == LOCKDOWN_E_SUCCESS) {
240 /* also remove local device public key */ 464 printf("SUCCESS: Unpaired with device %s\n", udid);
241 userpref_remove_device_public_key(uuid);
242 printf("SUCCESS: Unpaired with device %s\n", uuid);
243 } else { 465 } else {
244 result = EXIT_FAILURE; 466 result = EXIT_FAILURE;
245 if (lerr == LOCKDOWN_E_INVALID_HOST_ID) { 467 print_error_message(lerr);
246 printf("ERROR: Device %s is not paired with this host\n", uuid);
247 } else {
248 printf("ERROR: Unpairing with device %s failed with unhandled error code %d\n", uuid, lerr);
249 }
250 } 468 }
251 break; 469 break;
252 } 470 }
253 471
254leave: 472leave:
255 lockdownd_client_free(client); 473 lockdownd_client_free(client);
256 idevice_free(phone); 474 idevice_free(device);
257 if (uuid) { 475 free(udid);
258 free(uuid); 476
259 }
260 return result; 477 return result;
261} 478}
262 479