1 /*
2  * idevice.c
3  * Device discovery and communication interface.
4  *
5  * Copyright (c) 2009-2019 Nikias Bassen. All Rights Reserved.
6  * Copyright (c) 2014 Martin Szulecki All Rights Reserved.
7  * Copyright (c) 2008 Zach C. All Rights Reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <time.h>
32 
33 #include <usbmuxd.h>
34 #ifdef HAVE_OPENSSL
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/ssl.h>
38 #else
39 #include <gnutls/gnutls.h>
40 #endif
41 
42 #include "idevice.h"
43 #include "common/userpref.h"
44 #include "common/socket.h"
45 #include "common/thread.h"
46 #include "common/debug.h"
47 
48 #ifdef WIN32
49 #include <windows.h>
50 #endif
51 
52 #ifndef ETIMEDOUT
53 #define ETIMEDOUT 138
54 #endif
55 
56 #ifdef HAVE_OPENSSL
57 
58 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
59 	(defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x20020000L))
60 #define TLS_method TLSv1_method
61 #endif
62 
63 #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
SSL_COMP_free_compression_methods(void)64 static void SSL_COMP_free_compression_methods(void)
65 {
66 	sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
67 }
68 #endif
69 
openssl_remove_thread_state(void)70 static void openssl_remove_thread_state(void)
71 {
72 /*  ERR_remove_thread_state() is available since OpenSSL 1.0.0-beta1, but
73  *  deprecated in OpenSSL 1.1.0 */
74 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
75 #if OPENSSL_VERSION_NUMBER >= 0x10000001L
76 	ERR_remove_thread_state(NULL);
77 #else
78 	ERR_remove_state(0);
79 #endif
80 #endif
81 }
82 
83 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
84 static mutex_t *mutex_buf = NULL;
locking_function(int mode,int n,const char * file,int line)85 static void locking_function(int mode, int n, const char* file, int line)
86 {
87 	if (mode & CRYPTO_LOCK)
88 		mutex_lock(&mutex_buf[n]);
89 	else
90 		mutex_unlock(&mutex_buf[n]);
91 }
92 
93 #if OPENSSL_VERSION_NUMBER < 0x10000000L
id_function(void)94 static unsigned long id_function(void)
95 {
96 	return ((unsigned long)THREAD_ID);
97 }
98 #else
id_function(CRYPTO_THREADID * thread)99 static void id_function(CRYPTO_THREADID *thread)
100 {
101 	CRYPTO_THREADID_set_numeric(thread, (unsigned long)THREAD_ID);
102 }
103 #endif
104 #endif
105 #endif /* HAVE_OPENSSL */
106 
internal_idevice_init(void)107 static void internal_idevice_init(void)
108 {
109 #ifdef HAVE_OPENSSL
110 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
111 	int i;
112 	SSL_library_init();
113 
114 	mutex_buf = malloc(CRYPTO_num_locks() * sizeof(mutex_t));
115 	if (!mutex_buf)
116 		return;
117 	for (i = 0; i < CRYPTO_num_locks(); i++)
118 		mutex_init(&mutex_buf[i]);
119 
120 #if OPENSSL_VERSION_NUMBER < 0x10000000L
121 	CRYPTO_set_id_callback(id_function);
122 #else
123 	CRYPTO_THREADID_set_callback(id_function);
124 #endif
125 	CRYPTO_set_locking_callback(locking_function);
126 #endif
127 #else
128 	gnutls_global_init();
129 #endif
130 }
131 
internal_idevice_deinit(void)132 static void internal_idevice_deinit(void)
133 {
134 #ifdef HAVE_OPENSSL
135 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
136 	int i;
137 	if (mutex_buf) {
138 #if OPENSSL_VERSION_NUMBER < 0x10000000L
139 		CRYPTO_set_id_callback(NULL);
140 #else
141 		CRYPTO_THREADID_set_callback(NULL);
142 #endif
143 		CRYPTO_set_locking_callback(NULL);
144 		for (i = 0; i < CRYPTO_num_locks(); i++)
145 			mutex_destroy(&mutex_buf[i]);
146 		free(mutex_buf);
147 		mutex_buf = NULL;
148 	}
149 
150 	EVP_cleanup();
151 	CRYPTO_cleanup_all_ex_data();
152 	SSL_COMP_free_compression_methods();
153 	openssl_remove_thread_state();
154 #endif
155 #else
156 	gnutls_global_deinit();
157 #endif
158 }
159 
160 static thread_once_t init_once = THREAD_ONCE_INIT;
161 static thread_once_t deinit_once = THREAD_ONCE_INIT;
162 
163 #ifdef WIN32
DllMain(HINSTANCE hModule,DWORD dwReason,LPVOID lpReserved)164 BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
165 {
166 	switch (dwReason) {
167 	case DLL_PROCESS_ATTACH:
168 		thread_once(&init_once,	internal_idevice_init);
169 		break;
170 	case DLL_PROCESS_DETACH:
171 		thread_once(&deinit_once, internal_idevice_deinit);
172 		break;
173 	default:
174 		break;
175 	}
176 	return 1;
177 }
178 #else
libimobiledevice_initialize(void)179 static void __attribute__((constructor)) libimobiledevice_initialize(void)
180 {
181 	thread_once(&init_once, internal_idevice_init);
182 }
183 
libimobiledevice_deinitialize(void)184 static void __attribute__((destructor)) libimobiledevice_deinitialize(void)
185 {
186 	thread_once(&deinit_once, internal_idevice_deinit);
187 }
188 #endif
189 
190 static idevice_event_cb_t event_cb = NULL;
191 
usbmux_event_cb(const usbmuxd_event_t * event,void * user_data)192 static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data)
193 {
194 	idevice_event_t ev;
195 
196 	ev.event = event->event;
197 	ev.udid = event->device.udid;
198 	ev.conn_type = 0;
199 	if (event->device.conn_type == CONNECTION_TYPE_USB) {
200 		ev.conn_type = CONNECTION_USBMUXD;
201 	} else if (event->device.conn_type == CONNECTION_TYPE_NETWORK) {
202 		ev.conn_type = CONNECTION_NETWORK;
203 	} else {
204 		debug_info("Unknown connection type %d", event->device.conn_type);
205 	}
206 
207 	if (event_cb) {
208 		event_cb(&ev, user_data);
209 	}
210 }
211 
idevice_event_subscribe(idevice_event_cb_t callback,void * user_data)212 LIBIMOBILEDEVICE_API idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data)
213 {
214 	event_cb = callback;
215 	int res = usbmuxd_subscribe(usbmux_event_cb, user_data);
216 	if (res != 0) {
217 		event_cb = NULL;
218 		debug_info("ERROR: usbmuxd_subscribe() returned %d!", res);
219 		return IDEVICE_E_UNKNOWN_ERROR;
220 	}
221 	return IDEVICE_E_SUCCESS;
222 }
223 
idevice_event_unsubscribe(void)224 LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe(void)
225 {
226 	event_cb = NULL;
227 	int res = usbmuxd_unsubscribe();
228 	if (res != 0) {
229 		debug_info("ERROR: usbmuxd_unsubscribe() returned %d!", res);
230 		return IDEVICE_E_UNKNOWN_ERROR;
231 	}
232 	return IDEVICE_E_SUCCESS;
233 }
234 
idevice_get_device_list_extended(idevice_info_t ** devices,int * count)235 LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list_extended(idevice_info_t **devices, int *count)
236 {
237 	usbmuxd_device_info_t *dev_list;
238 
239 	*devices = NULL;
240 	*count = 0;
241 
242 	if (usbmuxd_get_device_list(&dev_list) < 0) {
243 		debug_info("ERROR: usbmuxd is not running!", __func__);
244 		return IDEVICE_E_NO_DEVICE;
245 	}
246 
247 	idevice_info_t *newlist = NULL;
248 	int i, newcount = 0;
249 
250 	for (i = 0; dev_list[i].handle > 0; i++) {
251 		newlist = realloc(*devices, sizeof(idevice_info_t) * (newcount+1));
252 		newlist[newcount] = malloc(sizeof(struct idevice_info));
253 		newlist[newcount]->udid = strdup(dev_list[i].udid);
254 		if (dev_list[i].conn_type == CONNECTION_TYPE_USB) {
255 			newlist[newcount]->conn_type = CONNECTION_USBMUXD;
256 			newlist[newcount]->conn_data = NULL;
257 		} else if (dev_list[i].conn_type == CONNECTION_TYPE_NETWORK) {
258 			newlist[newcount]->conn_type = CONNECTION_NETWORK;
259 			size_t addrlen = dev_list[i].conn_data[0];
260 			newlist[newcount]->conn_data = malloc(addrlen);
261 			memcpy(newlist[newcount]->conn_data, dev_list[i].conn_data, addrlen);
262 		}
263 		newcount++;
264 		*devices = newlist;
265 	}
266 	usbmuxd_device_list_free(&dev_list);
267 
268 	*count = newcount;
269 	newlist = realloc(*devices, sizeof(idevice_info_t) * (newcount+1));
270 	newlist[newcount] = NULL;
271 	*devices = newlist;
272 
273 	return IDEVICE_E_SUCCESS;
274 }
275 
idevice_device_list_extended_free(idevice_info_t * devices)276 LIBIMOBILEDEVICE_API idevice_error_t idevice_device_list_extended_free(idevice_info_t *devices)
277 {
278 	if (devices) {
279 		int i = 0;
280 		while (devices[i]) {
281 			free(devices[i]->udid);
282 			free(devices[i]->conn_data);
283 			free(devices[i]);
284 			i++;
285 		}
286 		free(devices);
287 	}
288 	return IDEVICE_E_SUCCESS;
289 }
290 
idevice_get_device_list(char *** devices,int * count)291 LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list(char ***devices, int *count)
292 {
293 	usbmuxd_device_info_t *dev_list;
294 
295 	*devices = NULL;
296 	*count = 0;
297 
298 	if (usbmuxd_get_device_list(&dev_list) < 0) {
299 		debug_info("ERROR: usbmuxd is not running!", __func__);
300 		return IDEVICE_E_NO_DEVICE;
301 	}
302 
303 	char **newlist = NULL;
304 	int i, newcount = 0;
305 
306 	for (i = 0; dev_list[i].handle > 0; i++) {
307 		if (dev_list[i].conn_type == CONNECTION_TYPE_USB) {
308 			newlist = realloc(*devices, sizeof(char*) * (newcount+1));
309 			newlist[newcount++] = strdup(dev_list[i].udid);
310 			*devices = newlist;
311 		}
312 	}
313 	usbmuxd_device_list_free(&dev_list);
314 
315 	*count = newcount;
316 	newlist = realloc(*devices, sizeof(char*) * (newcount+1));
317 	newlist[newcount] = NULL;
318 	*devices = newlist;
319 
320 	return IDEVICE_E_SUCCESS;
321 }
322 
idevice_device_list_free(char ** devices)323 LIBIMOBILEDEVICE_API idevice_error_t idevice_device_list_free(char **devices)
324 {
325 	if (devices) {
326 		int i = 0;
327 		while (devices[i]) {
328 			free(devices[i]);
329 			i++;
330 		}
331 		free(devices);
332 	}
333 	return IDEVICE_E_SUCCESS;
334 }
335 
idevice_set_debug_level(int level)336 LIBIMOBILEDEVICE_API void idevice_set_debug_level(int level)
337 {
338 	internal_set_debug_level(level);
339 }
340 
idevice_from_mux_device(usbmuxd_device_info_t * muxdev)341 static idevice_t idevice_from_mux_device(usbmuxd_device_info_t *muxdev)
342 {
343 	if (!muxdev)
344 		return NULL;
345 
346 	idevice_t device = (idevice_t)malloc(sizeof(struct idevice_private));
347 	if (!device)
348 		return NULL;
349 
350 	device->udid = strdup(muxdev->udid);
351 	device->mux_id = muxdev->handle;
352 	device->version = 0;
353 	switch (muxdev->conn_type) {
354 	case CONNECTION_TYPE_USB:
355 		device->conn_type = CONNECTION_USBMUXD;
356 		device->conn_data = NULL;
357 		break;
358 	case CONNECTION_TYPE_NETWORK:
359 		device->conn_type = CONNECTION_NETWORK;
360 		size_t len = ((uint8_t*)muxdev->conn_data)[0];
361 		device->conn_data = malloc(len);
362 		memcpy(device->conn_data, muxdev->conn_data, len);
363 		break;
364 	default:
365 		device->conn_type = 0;
366 		device->conn_data = NULL;
367 		break;
368 	}
369 	return device;
370 }
371 
idevice_new_with_options(idevice_t * device,const char * udid,enum idevice_options options)372 LIBIMOBILEDEVICE_API idevice_error_t idevice_new_with_options(idevice_t * device, const char *udid, enum idevice_options options)
373 {
374 	usbmuxd_device_info_t muxdev;
375 	int usbmux_options = 0;
376 	if (options & IDEVICE_LOOKUP_USBMUX) {
377 		usbmux_options |= DEVICE_LOOKUP_USBMUX;
378 	}
379 	if (options & IDEVICE_LOOKUP_NETWORK) {
380 		usbmux_options |= DEVICE_LOOKUP_NETWORK;
381 	}
382 	if (options & IDEVICE_LOOKUP_PREFER_NETWORK) {
383 		usbmux_options |= DEVICE_LOOKUP_PREFER_NETWORK;
384 	}
385 	int res = usbmuxd_get_device(udid, &muxdev, usbmux_options);
386 	if (res > 0) {
387 		*device = idevice_from_mux_device(&muxdev);
388 		if (!*device) {
389 			return IDEVICE_E_UNKNOWN_ERROR;
390 		}
391 		return IDEVICE_E_SUCCESS;
392 	}
393 	return IDEVICE_E_NO_DEVICE;
394 }
395 
idevice_new(idevice_t * device,const char * udid)396 LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char *udid)
397 {
398 	return idevice_new_with_options(device, udid, 0);
399 }
400 
idevice_free(idevice_t device)401 LIBIMOBILEDEVICE_API idevice_error_t idevice_free(idevice_t device)
402 {
403 	if (!device)
404 		return IDEVICE_E_INVALID_ARG;
405 	idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
406 
407 	ret = IDEVICE_E_SUCCESS;
408 
409 	free(device->udid);
410 
411 	if (device->conn_data) {
412 		free(device->conn_data);
413 	}
414 	free(device);
415 	return ret;
416 }
417 
idevice_connect(idevice_t device,uint16_t port,idevice_connection_t * connection)418 LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connection_t *connection)
419 {
420 	if (!device) {
421 		return IDEVICE_E_INVALID_ARG;
422 	}
423 
424 	if (device->conn_type == CONNECTION_USBMUXD) {
425 		int sfd = usbmuxd_connect(device->mux_id, port);
426 		if (sfd < 0) {
427 			debug_info("ERROR: Connecting to usbmuxd failed: %d (%s)", sfd, strerror(-sfd));
428 			return IDEVICE_E_UNKNOWN_ERROR;
429 		}
430 		idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private));
431 		new_connection->type = CONNECTION_USBMUXD;
432 		new_connection->data = (void*)(long)sfd;
433 		new_connection->ssl_data = NULL;
434 		new_connection->device = device;
435 		*connection = new_connection;
436 		return IDEVICE_E_SUCCESS;
437 	} else if (device->conn_type == CONNECTION_NETWORK) {
438 		struct sockaddr_storage saddr_storage;
439 		struct sockaddr* saddr = (struct sockaddr*)&saddr_storage;
440 
441 		/* FIXME: Improve handling of this platform/host dependent connection data */
442 		if (((char*)device->conn_data)[1] == 0x02) { // AF_INET
443 			saddr->sa_family = AF_INET;
444 			memcpy(&saddr->sa_data[0], (char*)device->conn_data + 2, 14);
445 		}
446 		else if (((char*)device->conn_data)[1] == 0x1E) { // AF_INET6 (bsd)
447 #ifdef AF_INET6
448 			saddr->sa_family = AF_INET6;
449 			/* copy the address and the host dependent scope id */
450 			memcpy(&saddr->sa_data[0], (char*)device->conn_data + 2, 26);
451 #else
452 			debug_info("ERROR: Got an IPv6 address but this system doesn't support IPv6");
453 			return IDEVICE_E_UNKNOWN_ERROR;
454 #endif
455 		}
456 		else {
457 			debug_info("Unsupported address family 0x%02x", ((char*)device->conn_data)[1]);
458 			return IDEVICE_E_UNKNOWN_ERROR;
459 		}
460 
461 		char addrtxt[48];
462 		addrtxt[0] = '\0';
463 
464 		if (!socket_addr_to_string(saddr, addrtxt, sizeof(addrtxt))) {
465 			debug_info("Failed to convert network address: %d (%s)", errno, strerror(errno));
466 		}
467 
468 		debug_info("Connecting to %s port %d...", addrtxt, port);
469 
470 		int sfd = socket_connect_addr(saddr, port);
471 		if (sfd < 0) {
472 			debug_info("ERROR: Connecting to network device failed: %d (%s)", errno, strerror(errno));
473 			return IDEVICE_E_NO_DEVICE;
474 		}
475 
476 		idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private));
477 		new_connection->type = CONNECTION_NETWORK;
478 		new_connection->data = (void*)(long)sfd;
479 		new_connection->ssl_data = NULL;
480 		new_connection->device = device;
481 
482 		*connection = new_connection;
483 
484 		return IDEVICE_E_SUCCESS;
485 	} else {
486 		debug_info("Unknown connection type %d", device->conn_type);
487 	}
488 
489 	return IDEVICE_E_UNKNOWN_ERROR;
490 }
491 
idevice_disconnect(idevice_connection_t connection)492 LIBIMOBILEDEVICE_API idevice_error_t idevice_disconnect(idevice_connection_t connection)
493 {
494 	if (!connection) {
495 		return IDEVICE_E_INVALID_ARG;
496 	}
497 	/* shut down ssl if enabled */
498 	if (connection->ssl_data) {
499 		idevice_connection_disable_ssl(connection);
500 	}
501 	idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR;
502 	if (connection->type == CONNECTION_USBMUXD) {
503 		usbmuxd_disconnect((int)(long)connection->data);
504 		connection->data = NULL;
505 		result = IDEVICE_E_SUCCESS;
506 	} else if (connection->type == CONNECTION_NETWORK) {
507 		socket_close((int)(long)connection->data);
508 		connection->data = NULL;
509 		result = IDEVICE_E_SUCCESS;
510 	} else {
511 		debug_info("Unknown connection type %d", connection->type);
512 	}
513 
514 	free(connection);
515 	connection = NULL;
516 
517 	return result;
518 }
519 
520 /**
521  * Internally used function to send raw data over the given connection.
522  */
internal_connection_send(idevice_connection_t connection,const char * data,uint32_t len,uint32_t * sent_bytes)523 static idevice_error_t internal_connection_send(idevice_connection_t connection, const char *data, uint32_t len, uint32_t *sent_bytes)
524 {
525 	if (!connection || !data) {
526 		return IDEVICE_E_INVALID_ARG;
527 	}
528 
529 	if (connection->type == CONNECTION_USBMUXD) {
530 		int res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes);
531 		if (res < 0) {
532 			debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res));
533 			return IDEVICE_E_UNKNOWN_ERROR;
534 		}
535 		return IDEVICE_E_SUCCESS;
536 	} else if (connection->type == CONNECTION_NETWORK) {
537 		int s = socket_send((int)(long)connection->data, (void*)data, len);
538 		if (s < 0) {
539 			*sent_bytes = 0;
540 			return IDEVICE_E_UNKNOWN_ERROR;
541 		}
542 		*sent_bytes = s;
543 		return IDEVICE_E_SUCCESS;
544 	} else {
545 		debug_info("Unknown connection type %d", connection->type);
546 	}
547 	return IDEVICE_E_UNKNOWN_ERROR;
548 
549 }
550 
idevice_connection_send(idevice_connection_t connection,const char * data,uint32_t len,uint32_t * sent_bytes)551 LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_t connection, const char *data, uint32_t len, uint32_t *sent_bytes)
552 {
553 	if (!connection || !data || (connection->ssl_data && !connection->ssl_data->session)) {
554 		return IDEVICE_E_INVALID_ARG;
555 	}
556 
557 	if (connection->ssl_data) {
558 		uint32_t sent = 0;
559 		while (sent < len) {
560 #ifdef HAVE_OPENSSL
561 			int c = socket_check_fd((int)(long)connection->data, FDM_WRITE, 100);
562 			if (c == 0 || c == -ETIMEDOUT || c == -EAGAIN) {
563 				continue;
564 			} else if (c < 0) {
565 				break;
566 			}
567 			int s = SSL_write(connection->ssl_data->session, (const void*)(data+sent), (int)(len-sent));
568 			if (s <= 0) {
569 				int sslerr = SSL_get_error(connection->ssl_data->session, s);
570 				if (sslerr == SSL_ERROR_WANT_WRITE) {
571 					continue;
572 				}
573 				break;
574 			}
575 #else
576 			ssize_t s = gnutls_record_send(connection->ssl_data->session, (void*)(data+sent), (size_t)(len-sent));
577 #endif
578 			if (s < 0) {
579 				break;
580 			}
581 			sent += s;
582 		}
583 		debug_info("SSL_write %d, sent %d", len, sent);
584 		if (sent < len) {
585 			*sent_bytes = 0;
586 			return IDEVICE_E_SSL_ERROR;
587 		}
588 		*sent_bytes = sent;
589 		return IDEVICE_E_SUCCESS;
590 	} else {
591 		uint32_t sent = 0;
592 		while (sent < len) {
593 			uint32_t bytes = 0;
594 			int s = internal_connection_send(connection, data+sent, len-sent, &bytes);
595 			if (s < 0) {
596 				break;
597 			}
598 			sent += bytes;
599 		}
600 		debug_info("internal_connection_send %d, sent %d", len, sent);
601 		if (sent < len) {
602 			*sent_bytes = 0;
603 			return IDEVICE_E_NOT_ENOUGH_DATA;
604 		}
605 		*sent_bytes = sent;
606 		return IDEVICE_E_SUCCESS;
607 	}
608 }
609 
socket_recv_to_idevice_error(int conn_error,uint32_t len,uint32_t received)610 static idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received)
611 {
612 	if (conn_error < 0) {
613 		switch (conn_error) {
614 			case -EAGAIN:
615 				debug_info("ERROR: received partial data %d/%d (%s)", received, len, strerror(-conn_error));
616 				return IDEVICE_E_NOT_ENOUGH_DATA;
617 			case -ETIMEDOUT:
618 				return IDEVICE_E_TIMEOUT;
619 			default:
620 				return IDEVICE_E_UNKNOWN_ERROR;
621 		}
622 	}
623 
624 	return IDEVICE_E_SUCCESS;
625 }
626 
627 /**
628  * Internally used function for receiving raw data over the given connection
629  * using a timeout.
630  */
internal_connection_receive_timeout(idevice_connection_t connection,char * data,uint32_t len,uint32_t * recv_bytes,unsigned int timeout)631 static idevice_error_t internal_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
632 {
633 	if (!connection) {
634 		return IDEVICE_E_INVALID_ARG;
635 	}
636 
637 	if (connection->type == CONNECTION_USBMUXD) {
638 		int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout);
639 		idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes);
640 
641 		if (error == IDEVICE_E_UNKNOWN_ERROR) {
642 			debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", conn_error, strerror(-conn_error));
643 		}
644 
645 		return error;
646 	} else if (connection->type == CONNECTION_NETWORK) {
647 		int res = socket_receive_timeout((int)(long)connection->data, data, len, 0, timeout);
648 		if (res < 0) {
649 			debug_info("ERROR: socket_receive_timeout failed: %d (%s)", res, strerror(-res));
650 			return (res == -EAGAIN ? IDEVICE_E_NOT_ENOUGH_DATA : IDEVICE_E_UNKNOWN_ERROR);
651 		}
652 		*recv_bytes = (uint32_t)res;
653 		return IDEVICE_E_SUCCESS;
654 	} else {
655 		debug_info("Unknown connection type %d", connection->type);
656 	}
657 	return IDEVICE_E_UNKNOWN_ERROR;
658 }
659 
idevice_connection_receive_timeout(idevice_connection_t connection,char * data,uint32_t len,uint32_t * recv_bytes,unsigned int timeout)660 LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
661 {
662 	if (!connection || (connection->ssl_data && !connection->ssl_data->session) || len == 0) {
663 		return IDEVICE_E_INVALID_ARG;
664 	}
665 
666 	if (connection->ssl_data) {
667 		uint32_t received = 0;
668 		int do_select = 1;
669 
670 		while (received < len) {
671 #ifdef HAVE_OPENSSL
672 			do_select = (SSL_pending(connection->ssl_data->session) == 0);
673 #endif
674 			if (do_select) {
675 				int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout);
676 				idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, received);
677 
678 				switch (error) {
679 					case IDEVICE_E_SUCCESS:
680 						break;
681 					case IDEVICE_E_UNKNOWN_ERROR:
682 					default:
683 						debug_info("ERROR: socket_check_fd returned %d (%s)", conn_error, strerror(-conn_error));
684 						return error;
685 				}
686 			}
687 
688 #ifdef HAVE_OPENSSL
689 			int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received);
690 			if (r > 0) {
691 				received += r;
692 			} else {
693 				int sslerr = SSL_get_error(connection->ssl_data->session, r);
694 				if (sslerr == SSL_ERROR_WANT_READ) {
695 					continue;
696 				}
697 				break;
698 			}
699 #else
700 			ssize_t r = gnutls_record_recv(connection->ssl_data->session, (void*)(data+received), (size_t)len-received);
701 			if (r > 0) {
702 				received += r;
703 			} else {
704 				break;
705 			}
706 #endif
707 		}
708 
709 		debug_info("SSL_read %d, received %d", len, received);
710 		if (received < len) {
711 			*recv_bytes = 0;
712 			return IDEVICE_E_SSL_ERROR;
713 		}
714 
715 		*recv_bytes = received;
716 		return IDEVICE_E_SUCCESS;
717 	}
718 	return internal_connection_receive_timeout(connection, data, len, recv_bytes, timeout);
719 }
720 
721 /**
722  * Internally used function for receiving raw data over the given connection.
723  */
internal_connection_receive(idevice_connection_t connection,char * data,uint32_t len,uint32_t * recv_bytes)724 static idevice_error_t internal_connection_receive(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes)
725 {
726 	if (!connection) {
727 		return IDEVICE_E_INVALID_ARG;
728 	}
729 
730 	if (connection->type == CONNECTION_USBMUXD) {
731 		int res = usbmuxd_recv((int)(long)connection->data, data, len, recv_bytes);
732 		if (res < 0) {
733 			debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res));
734 			return IDEVICE_E_UNKNOWN_ERROR;
735 		}
736 		return IDEVICE_E_SUCCESS;
737 	} else if (connection->type == CONNECTION_NETWORK) {
738 		int res = socket_receive((int)(long)connection->data, data, len);
739 		if (res < 0) {
740 			debug_info("ERROR: socket_receive returned %d (%s)", res, strerror(-res));
741 			return IDEVICE_E_UNKNOWN_ERROR;
742 		}
743 		*recv_bytes = (uint32_t)res;
744 		return IDEVICE_E_SUCCESS;
745 	} else {
746 		debug_info("Unknown connection type %d", connection->type);
747 	}
748 	return IDEVICE_E_UNKNOWN_ERROR;
749 }
750 
idevice_connection_receive(idevice_connection_t connection,char * data,uint32_t len,uint32_t * recv_bytes)751 LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes)
752 {
753 	if (!connection || (connection->ssl_data && !connection->ssl_data->session)) {
754 		return IDEVICE_E_INVALID_ARG;
755 	}
756 
757 	if (connection->ssl_data) {
758 #ifdef HAVE_OPENSSL
759 		int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len);
760 		debug_info("SSL_read %d, received %d", len, received);
761 #else
762 		ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len);
763 #endif
764 		if (received > 0) {
765 			*recv_bytes = received;
766 			return IDEVICE_E_SUCCESS;
767 		}
768 		*recv_bytes = 0;
769 		return IDEVICE_E_SSL_ERROR;
770 	}
771 	return internal_connection_receive(connection, data, len, recv_bytes);
772 }
773 
idevice_connection_get_fd(idevice_connection_t connection,int * fd)774 LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int *fd)
775 {
776 	if (!connection || !fd) {
777 		return IDEVICE_E_INVALID_ARG;
778 	}
779 
780 	idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR;
781 	if (connection->type == CONNECTION_USBMUXD) {
782 		*fd = (int)(long)connection->data;
783 		result = IDEVICE_E_SUCCESS;
784 	} else if (connection->type == CONNECTION_NETWORK) {
785 		*fd = (int)(long)connection->data;
786 		result = IDEVICE_E_SUCCESS;
787 	} else {
788 		debug_info("Unknown connection type %d", connection->type);
789 	}
790 	return result;
791 }
792 
idevice_get_handle(idevice_t device,uint32_t * handle)793 LIBIMOBILEDEVICE_API idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle)
794 {
795 	if (!device || !handle)
796 		return IDEVICE_E_INVALID_ARG;
797 
798 	*handle = device->mux_id;
799 	return IDEVICE_E_SUCCESS;
800 }
801 
idevice_get_udid(idevice_t device,char ** udid)802 LIBIMOBILEDEVICE_API idevice_error_t idevice_get_udid(idevice_t device, char **udid)
803 {
804 	if (!device || !udid)
805 		return IDEVICE_E_INVALID_ARG;
806 
807 	*udid = strdup(device->udid);
808 	return IDEVICE_E_SUCCESS;
809 }
810 
811 #ifndef HAVE_OPENSSL
812 /**
813  * Internally used gnutls callback function for receiving encrypted data.
814  */
internal_ssl_read(gnutls_transport_ptr_t transport,char * buffer,size_t length)815 static ssize_t internal_ssl_read(gnutls_transport_ptr_t transport, char *buffer, size_t length)
816 {
817 	int bytes = 0, pos_start_fill = 0;
818 	size_t tbytes = 0;
819 	int this_len = length;
820 	idevice_error_t res;
821 	idevice_connection_t connection = (idevice_connection_t)transport;
822 	char *recv_buffer;
823 
824 	debug_info("pre-read client wants %zi bytes", length);
825 
826 	recv_buffer = (char *)malloc(sizeof(char) * this_len);
827 
828 	/* repeat until we have the full data or an error occurs */
829 	do {
830 		if ((res = internal_connection_receive(connection, recv_buffer, this_len, (uint32_t*)&bytes)) != IDEVICE_E_SUCCESS) {
831 			debug_info("ERROR: idevice_connection_receive returned %d", res);
832 			return res;
833 		}
834 		debug_info("post-read we got %i bytes", bytes);
835 
836 		/* increase read count */
837 		tbytes += bytes;
838 
839 		/* fill the buffer with what we got right now */
840 		memcpy(buffer + pos_start_fill, recv_buffer, bytes);
841 		pos_start_fill += bytes;
842 
843 		if (tbytes >= length) {
844 			break;
845 		}
846 
847 		this_len = length - tbytes;
848 		debug_info("re-read trying to read missing %i bytes", this_len);
849 	} while (tbytes < length);
850 
851 	if (recv_buffer) {
852 		free(recv_buffer);
853 	}
854 	return tbytes;
855 }
856 
857 /**
858  * Internally used gnutls callback function for sending encrypted data.
859  */
internal_ssl_write(gnutls_transport_ptr_t transport,char * buffer,size_t length)860 static ssize_t internal_ssl_write(gnutls_transport_ptr_t transport, char *buffer, size_t length)
861 {
862 	uint32_t bytes = 0;
863 	idevice_error_t res;
864 	idevice_connection_t connection = (idevice_connection_t)transport;
865 	debug_info("pre-send length = %zi", length);
866 	if ((res = internal_connection_send(connection, buffer, length, &bytes)) != IDEVICE_E_SUCCESS) {
867 		debug_info("ERROR: internal_connection_send returned %d", res);
868 		return -1;
869 	}
870 	debug_info("post-send sent %i bytes", bytes);
871 	return bytes;
872 }
873 #endif
874 
875 /**
876  * Internally used function for cleaning up SSL stuff.
877  */
internal_ssl_cleanup(ssl_data_t ssl_data)878 static void internal_ssl_cleanup(ssl_data_t ssl_data)
879 {
880 	if (!ssl_data)
881 		return;
882 
883 #ifdef HAVE_OPENSSL
884 	if (ssl_data->session) {
885 		SSL_free(ssl_data->session);
886 	}
887 	if (ssl_data->ctx) {
888 		SSL_CTX_free(ssl_data->ctx);
889 	}
890 #else
891 	if (ssl_data->session) {
892 		gnutls_deinit(ssl_data->session);
893 	}
894 	if (ssl_data->certificate) {
895 		gnutls_certificate_free_credentials(ssl_data->certificate);
896 	}
897 	if (ssl_data->root_cert) {
898 		gnutls_x509_crt_deinit(ssl_data->root_cert);
899 	}
900 	if (ssl_data->host_cert) {
901 		gnutls_x509_crt_deinit(ssl_data->host_cert);
902 	}
903 	if (ssl_data->root_privkey) {
904 		gnutls_x509_privkey_deinit(ssl_data->root_privkey);
905 	}
906 	if (ssl_data->host_privkey) {
907 		gnutls_x509_privkey_deinit(ssl_data->host_privkey);
908 	}
909 #endif
910 }
911 
912 #ifdef HAVE_OPENSSL
ssl_verify_callback(int ok,X509_STORE_CTX * ctx)913 static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx)
914 {
915 	return 1;
916 }
917 
918 #ifndef STRIP_DEBUG_CODE
ssl_error_to_string(int e)919 static const char *ssl_error_to_string(int e)
920 {
921 	switch(e) {
922 		case SSL_ERROR_NONE:
923 			return "SSL_ERROR_NONE";
924 		case SSL_ERROR_SSL:
925 			return ERR_error_string(ERR_get_error(), NULL);
926 		case SSL_ERROR_WANT_READ:
927 			return "SSL_ERROR_WANT_READ";
928 		case SSL_ERROR_WANT_WRITE:
929 			return "SSL_ERROR_WANT_WRITE";
930 		case SSL_ERROR_WANT_X509_LOOKUP:
931 			return "SSL_ERROR_WANT_X509_LOOKUP";
932 		case SSL_ERROR_SYSCALL:
933 			return "SSL_ERROR_SYSCALL";
934 		case SSL_ERROR_ZERO_RETURN:
935 			return "SSL_ERROR_ZERO_RETURN";
936 		case SSL_ERROR_WANT_CONNECT:
937 			return "SSL_ERROR_WANT_CONNECT";
938 		case SSL_ERROR_WANT_ACCEPT:
939 			return "SSL_ERROR_WANT_ACCEPT";
940 		default:
941 			return "UNKOWN_ERROR_VALUE";
942 	}
943 }
944 #endif
945 #endif
946 
947 #ifndef HAVE_OPENSSL
948 /**
949  * Internally used gnutls callback function that gets called during handshake.
950  */
951 #if GNUTLS_VERSION_NUMBER >= 0x020b07
internal_cert_callback(gnutls_session_t session,const gnutls_datum_t * req_ca_rdn,int nreqs,const gnutls_pk_algorithm_t * sign_algos,int sign_algos_length,gnutls_retr2_st * st)952 static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr2_st * st)
953 #else
954 static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr_st * st)
955 #endif
956 {
957 	int res = -1;
958 	gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
959 	if (type == GNUTLS_CRT_X509) {
960 		ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr(session);
961 		if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) {
962 			debug_info("Passing certificate");
963 #if GNUTLS_VERSION_NUMBER >= 0x020b07
964 			st->cert_type = type;
965 			st->key_type = GNUTLS_PRIVKEY_X509;
966 #else
967 			st->type = type;
968 #endif
969 			st->ncerts = 1;
970 			st->cert.x509 = &ssl_data->host_cert;
971 			st->key.x509 = ssl_data->host_privkey;
972 			st->deinit_all = 0;
973 			res = 0;
974 		}
975 	}
976 	return res;
977 }
978 #endif
979 
idevice_connection_enable_ssl(idevice_connection_t connection)980 LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
981 {
982 	if (!connection || connection->ssl_data)
983 		return IDEVICE_E_INVALID_ARG;
984 
985 	idevice_error_t ret = IDEVICE_E_SSL_ERROR;
986 	plist_t pair_record = NULL;
987 
988 	userpref_read_pair_record(connection->device->udid, &pair_record);
989 	if (!pair_record) {
990 		debug_info("ERROR: Failed enabling SSL. Unable to read pair record for udid %s.", connection->device->udid);
991 		return ret;
992 	}
993 
994 #ifdef HAVE_OPENSSL
995 	key_data_t root_cert = { NULL, 0 };
996 	key_data_t root_privkey = { NULL, 0 };
997 
998 	pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert);
999 	pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_privkey);
1000 
1001 	if (pair_record)
1002 		plist_free(pair_record);
1003 
1004 	BIO *ssl_bio = BIO_new(BIO_s_socket());
1005 	if (!ssl_bio) {
1006 		debug_info("ERROR: Could not create SSL bio.");
1007 		return ret;
1008 	}
1009 	BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE);
1010 
1011 	SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
1012 	if (ssl_ctx == NULL) {
1013 		debug_info("ERROR: Could not create SSL context.");
1014 		BIO_free(ssl_bio);
1015 		return ret;
1016 	}
1017 
1018 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
1019 	SSL_CTX_set_security_level(ssl_ctx, 0);
1020 #endif
1021 
1022 #if OPENSSL_VERSION_NUMBER < 0x10100002L || \
1023 	(defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2060000fL))
1024 	/* force use of TLSv1 for older devices */
1025 	if (connection->device->version < DEVICE_VERSION(10,0,0)) {
1026 #ifdef SSL_OP_NO_TLSv1_1
1027 		long opts = SSL_CTX_get_options(ssl_ctx);
1028 		opts |= SSL_OP_NO_TLSv1_1;
1029 #ifdef SSL_OP_NO_TLSv1_2
1030 		opts |= SSL_OP_NO_TLSv1_2;
1031 #endif
1032 #ifdef SSL_OP_NO_TLSv1_3
1033 		opts |= SSL_OP_NO_TLSv1_3;
1034 #endif
1035 		SSL_CTX_set_options(ssl_ctx, opts);
1036 #endif
1037 	}
1038 #else
1039 	SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION);
1040 	if (connection->device->version < DEVICE_VERSION(10,0,0)) {
1041 		SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_VERSION);
1042 	}
1043 #endif
1044 
1045 	BIO* membp;
1046 	X509* rootCert = NULL;
1047 	membp = BIO_new_mem_buf(root_cert.data, root_cert.size);
1048 	PEM_read_bio_X509(membp, &rootCert, NULL, NULL);
1049 	BIO_free(membp);
1050 	if (SSL_CTX_use_certificate(ssl_ctx, rootCert) != 1) {
1051 		debug_info("WARNING: Could not load RootCertificate");
1052 	}
1053 	X509_free(rootCert);
1054 	free(root_cert.data);
1055 
1056 	RSA* rootPrivKey = NULL;
1057 	membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
1058 	PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL);
1059 	BIO_free(membp);
1060 	if (SSL_CTX_use_RSAPrivateKey(ssl_ctx, rootPrivKey) != 1) {
1061 		debug_info("WARNING: Could not load RootPrivateKey");
1062 	}
1063 	RSA_free(rootPrivKey);
1064 	free(root_privkey.data);
1065 
1066 	SSL *ssl = SSL_new(ssl_ctx);
1067 	if (!ssl) {
1068 		debug_info("ERROR: Could not create SSL object");
1069 		BIO_free(ssl_bio);
1070 		SSL_CTX_free(ssl_ctx);
1071 		return ret;
1072 	}
1073 	SSL_set_connect_state(ssl);
1074 	SSL_set_verify(ssl, 0, ssl_verify_callback);
1075 	SSL_set_bio(ssl, ssl_bio, ssl_bio);
1076 
1077 	debug_info("Performing SSL handshake");
1078 	int ssl_error = 0;
1079 	do {
1080 		ssl_error = SSL_get_error(ssl, SSL_do_handshake(ssl));
1081 		if (ssl_error == 0 || ssl_error != SSL_ERROR_WANT_READ) {
1082 			break;
1083 		}
1084 #ifdef WIN32
1085 		Sleep(100);
1086 #else
1087 		struct timespec ts = { 0, 100000000 };
1088 		nanosleep(&ts, NULL);
1089 #endif
1090 	} while (1);
1091 	if (ssl_error != 0) {
1092 		debug_info("ERROR during SSL handshake: %s", ssl_error_to_string(ssl_error));
1093 		SSL_free(ssl);
1094 		SSL_CTX_free(ssl_ctx);
1095 	} else {
1096 		ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
1097 		ssl_data_loc->session = ssl;
1098 		ssl_data_loc->ctx = ssl_ctx;
1099 		connection->ssl_data = ssl_data_loc;
1100 		ret = IDEVICE_E_SUCCESS;
1101 		debug_info("SSL mode enabled, %s, cipher: %s", SSL_get_version(ssl), SSL_get_cipher(ssl));
1102 	}
1103 	/* required for proper multi-thread clean up to prevent leaks */
1104 	openssl_remove_thread_state();
1105 #else
1106 	ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
1107 
1108 	/* Set up GnuTLS... */
1109 	debug_info("enabling SSL mode");
1110 	errno = 0;
1111 	gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate);
1112 #if GNUTLS_VERSION_NUMBER >= 0x020b07
1113 	gnutls_certificate_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback);
1114 #else
1115 	gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback);
1116 #endif
1117 	gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT);
1118 	gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-TLS1.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL);
1119 	gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate);
1120 	gnutls_session_set_ptr(ssl_data_loc->session, ssl_data_loc);
1121 
1122 	gnutls_x509_crt_init(&ssl_data_loc->root_cert);
1123 	gnutls_x509_crt_init(&ssl_data_loc->host_cert);
1124 	gnutls_x509_privkey_init(&ssl_data_loc->root_privkey);
1125 	gnutls_x509_privkey_init(&ssl_data_loc->host_privkey);
1126 
1127 	pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, ssl_data_loc->root_cert);
1128 	pair_record_import_crt_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, ssl_data_loc->host_cert);
1129 	pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, ssl_data_loc->root_privkey);
1130 	pair_record_import_key_with_name(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, ssl_data_loc->host_privkey);
1131 
1132 	if (pair_record)
1133 		plist_free(pair_record);
1134 
1135 	debug_info("GnuTLS step 1...");
1136 	gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection);
1137 	debug_info("GnuTLS step 2...");
1138 	gnutls_transport_set_push_function(ssl_data_loc->session, (gnutls_push_func) & internal_ssl_write);
1139 	debug_info("GnuTLS step 3...");
1140 	gnutls_transport_set_pull_function(ssl_data_loc->session, (gnutls_pull_func) & internal_ssl_read);
1141 	debug_info("GnuTLS step 4 -- now handshaking...");
1142 	if (errno) {
1143 		debug_info("WARNING: errno says %s before handshake!", strerror(errno));
1144 	}
1145 
1146 	int return_me = 0;
1147 	do {
1148 		return_me = gnutls_handshake(ssl_data_loc->session);
1149 	} while(return_me == GNUTLS_E_AGAIN || return_me == GNUTLS_E_INTERRUPTED);
1150 
1151 	debug_info("GnuTLS handshake done...");
1152 
1153 	if (return_me != GNUTLS_E_SUCCESS) {
1154 		internal_ssl_cleanup(ssl_data_loc);
1155 		free(ssl_data_loc);
1156 		debug_info("GnuTLS reported something wrong: %s", gnutls_strerror(return_me));
1157 		debug_info("oh.. errno says %s", strerror(errno));
1158 	} else {
1159 		connection->ssl_data = ssl_data_loc;
1160 		ret = IDEVICE_E_SUCCESS;
1161 		debug_info("SSL mode enabled");
1162 	}
1163 #endif
1164 	return ret;
1165 }
1166 
idevice_connection_disable_ssl(idevice_connection_t connection)1167 LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection)
1168 {
1169 	return idevice_connection_disable_bypass_ssl(connection, 0);
1170 }
1171 
idevice_connection_disable_bypass_ssl(idevice_connection_t connection,uint8_t sslBypass)1172 LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_disable_bypass_ssl(idevice_connection_t connection, uint8_t sslBypass)
1173 {
1174 	if (!connection)
1175 		return IDEVICE_E_INVALID_ARG;
1176 	if (!connection->ssl_data) {
1177 		/* ignore if ssl is not enabled */
1178 		return IDEVICE_E_SUCCESS;
1179 	}
1180 
1181 	// some services require plain text communication after SSL handshake
1182 	// sending out SSL_shutdown will cause bytes
1183 	if (!sslBypass) {
1184 #ifdef HAVE_OPENSSL
1185 		if (connection->ssl_data->session) {
1186 			/* see: https://www.openssl.org/docs/ssl/SSL_shutdown.html#RETURN_VALUES */
1187 			if (SSL_shutdown(connection->ssl_data->session) == 0) {
1188 				/* Only try bidirectional shutdown if we know it can complete */
1189 				int ssl_error;
1190 				if ((ssl_error = SSL_get_error(connection->ssl_data->session, 0)) == SSL_ERROR_NONE) {
1191 					SSL_shutdown(connection->ssl_data->session);
1192 				} else  {
1193 					debug_info("Skipping bidirectional SSL shutdown. SSL error code: %i\n", ssl_error);
1194 				}
1195 			}
1196 		}
1197 #else
1198 		if (connection->ssl_data->session) {
1199 			gnutls_bye(connection->ssl_data->session, GNUTLS_SHUT_RDWR);
1200 		}
1201 #endif
1202 	}
1203 
1204 	internal_ssl_cleanup(connection->ssl_data);
1205 	free(connection->ssl_data);
1206 	connection->ssl_data = NULL;
1207 
1208 	debug_info("SSL mode disabled");
1209 
1210 	return IDEVICE_E_SUCCESS;
1211 }
1212