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