summaryrefslogtreecommitdiffstats
path: root/tools/idevicepair.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/idevicepair.c')
-rw-r--r--tools/idevicepair.c185
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
41static char *udid = NULL; 50static 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
59static 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
73static 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
96static 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
43static void print_error_message(lockdownd_error_t err) 115static 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 {