diff options
Diffstat (limited to 'tools/idevicepair.c')
-rw-r--r-- | tools/idevicepair.c | 185 |
1 files changed, 179 insertions, 6 deletions
diff --git a/tools/idevicepair.c b/tools/idevicepair.c index 0dcd45f..a2dc944 100644 --- a/tools/idevicepair.c +++ b/tools/idevicepair.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * idevicepair.c | 2 | * idevicepair.c |
3 | * Manage pairings with devices and this host | 3 | * Manage pairings with devices and this host |
4 | * | 4 | * |
5 | * Copyright (c) 2010-2019 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 | * Copyright (c) 2014 Martin Szulecki, All Rights Reserved. |
7 | * | 7 | * |
8 | * This library is free software; you can redistribute it and/or | 8 | * This library is free software; you can redistribute it and/or |
@@ -30,16 +30,88 @@ | |||
30 | #include <string.h> | 30 | #include <string.h> |
31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
32 | #include <getopt.h> | 32 | #include <getopt.h> |
33 | #ifndef WIN32 | 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> | ||
34 | #include <signal.h> | 40 | #include <signal.h> |
35 | #endif | 41 | #endif |
42 | |||
36 | #include "common/userpref.h" | 43 | #include "common/userpref.h" |
44 | #include <libimobiledevice-glue/utils.h> | ||
37 | 45 | ||
38 | #include <libimobiledevice/libimobiledevice.h> | 46 | #include <libimobiledevice/libimobiledevice.h> |
39 | #include <libimobiledevice/lockdown.h> | 47 | #include <libimobiledevice/lockdown.h> |
48 | #include <plist/plist.h> | ||
40 | 49 | ||
41 | static char *udid = NULL; | 50 | static char *udid = NULL; |
42 | 51 | ||
52 | #ifdef HAVE_WIRELESS_PAIRING | ||
53 | |||
54 | #ifdef WIN32 | ||
55 | #define BS_CC '\b' | ||
56 | #define my_getch getch | ||
57 | #else | ||
58 | #define BS_CC 0x7f | ||
59 | static int my_getch(void) | ||
60 | { | ||
61 | struct termios oldt, newt; | ||
62 | int ch; | ||
63 | tcgetattr(STDIN_FILENO, &oldt); | ||
64 | newt = oldt; | ||
65 | newt.c_lflag &= ~(ICANON | ECHO); | ||
66 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); | ||
67 | ch = getchar(); | ||
68 | tcsetattr(STDIN_FILENO, TCSANOW, &oldt); | ||
69 | return ch; | ||
70 | } | ||
71 | #endif | ||
72 | |||
73 | static int get_hidden_input(char *buf, int maxlen) | ||
74 | { | ||
75 | int pwlen = 0; | ||
76 | int c; | ||
77 | |||
78 | while ((c = my_getch())) { | ||
79 | if ((c == '\r') || (c == '\n')) { | ||
80 | break; | ||
81 | } else if (isprint(c)) { | ||
82 | if (pwlen < maxlen-1) | ||
83 | buf[pwlen++] = c; | ||
84 | fputc('*', stderr); | ||
85 | } else if (c == BS_CC) { | ||
86 | if (pwlen > 0) { | ||
87 | fputs("\b \b", stderr); | ||
88 | pwlen--; | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | buf[pwlen] = 0; | ||
93 | return pwlen; | ||
94 | } | ||
95 | |||
96 | static void pairing_cb(lockdownd_cu_pairing_cb_type_t cb_type, void *user_data, void* data_ptr, unsigned int* data_size) | ||
97 | { | ||
98 | if (cb_type == LOCKDOWN_CU_PAIRING_PIN_REQUESTED) { | ||
99 | printf("Enter PIN: "); | ||
100 | fflush(stdout); | ||
101 | |||
102 | *data_size = get_hidden_input((char*)data_ptr, *data_size); | ||
103 | |||
104 | printf("\n"); | ||
105 | } else if (cb_type == LOCKDOWN_CU_PAIRING_DEVICE_INFO) { | ||
106 | printf("Device info:\n"); | ||
107 | plist_print_to_stream_with_indentation((plist_t)data_ptr, stdout, 2); | ||
108 | } else if (cb_type == LOCKDOWN_CU_PAIRING_ERROR) { | ||
109 | printf("ERROR: %s\n", (data_ptr) ? (char*)data_ptr : "(unknown)"); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | #endif /* HAVE_WIRELESS_PAIRING */ | ||
114 | |||
43 | static void print_error_message(lockdownd_error_t err) | 115 | static void print_error_message(lockdownd_error_t err) |
44 | { | 116 | { |
45 | switch (err) { | 117 | switch (err) { |
@@ -56,6 +128,16 @@ static void print_error_message(lockdownd_error_t err) | |||
56 | case LOCKDOWN_E_USER_DENIED_PAIRING: | 128 | case LOCKDOWN_E_USER_DENIED_PAIRING: |
57 | printf("ERROR: Device %s said that the user denied the trust dialog.\n", udid); | 129 | printf("ERROR: Device %s said that the user denied the trust dialog.\n", udid); |
58 | break; | 130 | break; |
131 | case LOCKDOWN_E_PAIRING_FAILED: | ||
132 | printf("ERROR: Pairing with device %s failed.\n", udid); | ||
133 | break; | ||
134 | case LOCKDOWN_E_GET_PROHIBITED: | ||
135 | case LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION: | ||
136 | printf("ERROR: Pairing is not possible over this connection.\n"); | ||
137 | #ifdef HAVE_WIRELESS_PAIRING | ||
138 | printf("To perform a wireless pairing use the -w command line switch. See usage or man page for details.\n"); | ||
139 | #endif | ||
140 | break; | ||
59 | default: | 141 | default: |
60 | printf("ERROR: Device %s returned unhandled error code %d\n", udid, err); | 142 | printf("ERROR: Device %s returned unhandled error code %d\n", udid, err); |
61 | break; | 143 | break; |
@@ -81,9 +163,20 @@ static void print_usage(int argc, char **argv) | |||
81 | printf("\n"); | 163 | printf("\n"); |
82 | printf("The following OPTIONS are accepted:\n"); | 164 | printf("The following OPTIONS are accepted:\n"); |
83 | printf(" -u, --udid UDID target specific device by UDID\n"); | 165 | printf(" -u, --udid UDID target specific device by UDID\n"); |
166 | #ifdef HAVE_WIRELESS_PAIRING | ||
167 | printf(" -w, --wireless perform wireless pairing (see NOTE)\n"); | ||
168 | printf(" -n, --network connect to network device (see NOTE)\n"); | ||
169 | #endif | ||
84 | printf(" -d, --debug enable communication debugging\n"); | 170 | printf(" -d, --debug enable communication debugging\n"); |
85 | printf(" -h, --help prints usage information\n"); | 171 | printf(" -h, --help prints usage information\n"); |
86 | printf(" -v, --version prints version information\n"); | 172 | printf(" -v, --version prints version information\n"); |
173 | #ifdef HAVE_WIRELESS_PAIRING | ||
174 | printf("\n"); | ||
175 | printf("NOTE: Pairing over network (wireless pairing) is only supported by Apple TV\n"); | ||
176 | printf("devices. To perform a wireless pairing, you need to use the -w command line\n"); | ||
177 | printf("switch. Make sure to put the device into pairing mode first by opening\n"); | ||
178 | printf("Settings > Remotes and Devices > Remote App and Devices.\n"); | ||
179 | #endif | ||
87 | printf("\n"); | 180 | printf("\n"); |
88 | printf("Homepage: <" PACKAGE_URL ">\n"); | 181 | printf("Homepage: <" PACKAGE_URL ">\n"); |
89 | printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n"); | 182 | printf("Bug Reports: <" PACKAGE_BUGREPORT ">\n"); |
@@ -95,10 +188,20 @@ int main(int argc, char **argv) | |||
95 | static struct option longopts[] = { | 188 | static struct option longopts[] = { |
96 | { "help", no_argument, NULL, 'h' }, | 189 | { "help", no_argument, NULL, 'h' }, |
97 | { "udid", required_argument, NULL, 'u' }, | 190 | { "udid", required_argument, NULL, 'u' }, |
191 | #ifdef HAVE_WIRELESS_PAIRING | ||
192 | { "wireless", no_argument, NULL, 'w' }, | ||
193 | { "network", no_argument, NULL, 'n' }, | ||
194 | { "hostinfo", required_argument, NULL, 1 }, | ||
195 | #endif | ||
98 | { "debug", no_argument, NULL, 'd' }, | 196 | { "debug", no_argument, NULL, 'd' }, |
99 | { "version", no_argument, NULL, 'v' }, | 197 | { "version", no_argument, NULL, 'v' }, |
100 | { NULL, 0, NULL, 0} | 198 | { NULL, 0, NULL, 0} |
101 | }; | 199 | }; |
200 | #ifdef HAVE_WIRELESS_PAIRING | ||
201 | #define SHORT_OPTIONS "hu:wndv" | ||
202 | #else | ||
203 | #define SHORT_OPTIONS "hu:dv" | ||
204 | #endif | ||
102 | lockdownd_client_t client = NULL; | 205 | lockdownd_client_t client = NULL; |
103 | idevice_t device = NULL; | 206 | idevice_t device = NULL; |
104 | idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; | 207 | idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; |
@@ -106,13 +209,18 @@ int main(int argc, char **argv) | |||
106 | int result; | 209 | int result; |
107 | 210 | ||
108 | char *type = NULL; | 211 | char *type = NULL; |
212 | int use_network = 0; | ||
213 | int wireless_pairing = 0; | ||
214 | #ifdef HAVE_WIRELESS_PAIRING | ||
215 | plist_t host_info_plist = NULL; | ||
216 | #endif | ||
109 | char *cmd; | 217 | char *cmd; |
110 | typedef enum { | 218 | typedef enum { |
111 | OP_NONE = 0, OP_PAIR, OP_VALIDATE, OP_UNPAIR, OP_LIST, OP_HOSTID, OP_SYSTEMBUID | 219 | OP_NONE = 0, OP_PAIR, OP_VALIDATE, OP_UNPAIR, OP_LIST, OP_HOSTID, OP_SYSTEMBUID |
112 | } op_t; | 220 | } op_t; |
113 | op_t op = OP_NONE; | 221 | op_t op = OP_NONE; |
114 | 222 | ||
115 | while ((c = getopt_long(argc, argv, "hu:dv", longopts, NULL)) != -1) { | 223 | while ((c = getopt_long(argc, argv, SHORT_OPTIONS, longopts, NULL)) != -1) { |
116 | switch (c) { | 224 | switch (c) { |
117 | case 'h': | 225 | case 'h': |
118 | print_usage(argc, argv); | 226 | print_usage(argc, argv); |
@@ -127,6 +235,43 @@ int main(int argc, char **argv) | |||
127 | free(udid); | 235 | free(udid); |
128 | udid = strdup(optarg); | 236 | udid = strdup(optarg); |
129 | break; | 237 | break; |
238 | #ifdef HAVE_WIRELESS_PAIRING | ||
239 | case 'w': | ||
240 | wireless_pairing = 1; | ||
241 | break; | ||
242 | case 'n': | ||
243 | use_network = 1; | ||
244 | break; | ||
245 | case 1: | ||
246 | if (!*optarg) { | ||
247 | fprintf(stderr, "ERROR: --hostinfo argument must not be empty!\n"); | ||
248 | result = EXIT_FAILURE; | ||
249 | goto leave; | ||
250 | } | ||
251 | if (*optarg == '@') { | ||
252 | plist_read_from_filename(&host_info_plist, optarg+1); | ||
253 | if (!host_info_plist) { | ||
254 | fprintf(stderr, "ERROR: Could not read from file '%s'\n", optarg+1); | ||
255 | result = EXIT_FAILURE; | ||
256 | goto leave; | ||
257 | } | ||
258 | } | ||
259 | #ifdef HAVE_PLIST_JSON | ||
260 | else if (*optarg == '{') { | ||
261 | if (plist_from_json(optarg, strlen(optarg), &host_info_plist) != PLIST_ERR_SUCCESS) { | ||
262 | fprintf(stderr, "ERROR: --hostinfo argument not valid. Make sure it is a JSON dictionary.\n"); | ||
263 | result = EXIT_FAILURE; | ||
264 | goto leave; | ||
265 | } | ||
266 | } | ||
267 | #endif | ||
268 | else { | ||
269 | fprintf(stderr, "ERROR: --hostinfo argument not valid. To specify a path prefix with '@'\n"); | ||
270 | result = EXIT_FAILURE; | ||
271 | goto leave; | ||
272 | } | ||
273 | break; | ||
274 | #endif | ||
130 | case 'd': | 275 | case 'd': |
131 | idevice_set_debug_level(1); | 276 | idevice_set_debug_level(1); |
132 | break; | 277 | break; |
@@ -152,6 +297,13 @@ int main(int argc, char **argv) | |||
152 | goto leave; | 297 | goto leave; |
153 | } | 298 | } |
154 | 299 | ||
300 | if (wireless_pairing && use_network) { | ||
301 | printf("ERROR: You cannot use -w and -n together.\n"); | ||
302 | print_usage(argc, argv); | ||
303 | result = EXIT_FAILURE; | ||
304 | goto leave; | ||
305 | } | ||
306 | |||
155 | cmd = (argv+optind)[0]; | 307 | cmd = (argv+optind)[0]; |
156 | 308 | ||
157 | if (!strcmp(cmd, "pair")) { | 309 | if (!strcmp(cmd, "pair")) { |
@@ -169,7 +321,18 @@ int main(int argc, char **argv) | |||
169 | } else { | 321 | } else { |
170 | printf("ERROR: Invalid command '%s' specified\n", cmd); | 322 | printf("ERROR: Invalid command '%s' specified\n", cmd); |
171 | print_usage(argc, argv); | 323 | print_usage(argc, argv); |
172 | exit(EXIT_FAILURE); | 324 | result = EXIT_FAILURE; |
325 | goto leave; | ||
326 | } | ||
327 | |||
328 | if (wireless_pairing) { | ||
329 | if (op == OP_VALIDATE || op == OP_UNPAIR) { | ||
330 | printf("ERROR: Command '%s' is not supported with -w\n", cmd); | ||
331 | print_usage(argc, argv); | ||
332 | result = EXIT_FAILURE; | ||
333 | goto leave; | ||
334 | } | ||
335 | use_network = 1; | ||
173 | } | 336 | } |
174 | 337 | ||
175 | if (op == OP_SYSTEMBUID) { | 338 | if (op == OP_SYSTEMBUID) { |
@@ -198,7 +361,7 @@ int main(int argc, char **argv) | |||
198 | goto leave; | 361 | goto leave; |
199 | } | 362 | } |
200 | 363 | ||
201 | ret = idevice_new(&device, udid); | 364 | ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); |
202 | if (ret != IDEVICE_E_SUCCESS) { | 365 | if (ret != IDEVICE_E_SUCCESS) { |
203 | if (udid) { | 366 | if (udid) { |
204 | printf("No device found with udid %s.\n", udid); | 367 | printf("No device found with udid %s.\n", udid); |
@@ -257,7 +420,17 @@ int main(int argc, char **argv) | |||
257 | switch(op) { | 420 | switch(op) { |
258 | default: | 421 | default: |
259 | case OP_PAIR: | 422 | case OP_PAIR: |
260 | lerr = lockdownd_pair(client, NULL); | 423 | #ifdef HAVE_WIRELESS_PAIRING |
424 | if (wireless_pairing) { | ||
425 | lerr = lockdownd_cu_pairing_create(client, pairing_cb, NULL, host_info_plist, NULL); | ||
426 | if (lerr == LOCKDOWN_E_SUCCESS) { | ||
427 | lerr = lockdownd_pair_cu(client); | ||
428 | } | ||
429 | } else | ||
430 | #endif | ||
431 | { | ||
432 | lerr = lockdownd_pair(client, NULL); | ||
433 | } | ||
261 | if (lerr == LOCKDOWN_E_SUCCESS) { | 434 | if (lerr == LOCKDOWN_E_SUCCESS) { |
262 | printf("SUCCESS: Paired with device %s\n", udid); | 435 | printf("SUCCESS: Paired with device %s\n", udid); |
263 | } else { | 436 | } else { |