summaryrefslogtreecommitdiffstats
path: root/src/idevice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/idevice.c')
-rw-r--r--src/idevice.c1434
1 files changed, 1155 insertions, 279 deletions
diff --git a/src/idevice.c b/src/idevice.c
index 5a9d49b..b9bbb1f 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -1,98 +1,387 @@
1/* 1/*
2 * idevice.c 2 * idevice.c
3 * Device discovery and communication interface. 3 * Device discovery and communication interface.
4 * 4 *
5 * Copyright (c) 2009-2021 Nikias Bassen. All Rights Reserved.
6 * Copyright (c) 2014 Martin Szulecki All Rights Reserved.
5 * Copyright (c) 2008 Zach C. All Rights Reserved. 7 * Copyright (c) 2008 Zach C. All Rights Reserved.
6 * Copyright (c) 2009 Nikias Bassen. All Rights Reserved.
7 * 8 *
8 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public 10 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either 11 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version. 12 * version 2.1 of the License, or (at your option) any later version.
12 * 13 *
13 * This library is distributed in the hope that it will be useful, 14 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details. 17 * Lesser General Public License for more details.
17 * 18 *
18 * You should have received a copy of the GNU Lesser General Public 19 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software 20 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */ 22 */
22 23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
23#include <stdlib.h> 28#include <stdlib.h>
24#include <string.h> 29#include <string.h>
25#include <errno.h> 30#include <errno.h>
31#include <time.h>
32
33#ifdef WIN32
34#include <winsock2.h>
35#include <ws2tcpip.h>
36#include <windows.h>
37#else
38#include <sys/socket.h>
39#include <netinet/in.h>
40#endif
26 41
27#include <usbmuxd.h> 42#include <usbmuxd.h>
43
44#if defined(HAVE_OPENSSL)
45#include <openssl/err.h>
46#include <openssl/rsa.h>
47#include <openssl/ssl.h>
48#elif defined(HAVE_GNUTLS)
28#include <gnutls/gnutls.h> 49#include <gnutls/gnutls.h>
50#elif defined(HAVE_MBEDTLS)
51#include <mbedtls/rsa.h>
52#include <mbedtls/ssl.h>
53#include <mbedtls/entropy.h>
54#include <mbedtls/ctr_drbg.h>
55#include <mbedtls/debug.h>
56#else
57#error No supported TLS/SSL library enabled
58#endif
59
60#include <libimobiledevice-glue/socket.h>
61#include <libimobiledevice-glue/thread.h>
62
29#include "idevice.h" 63#include "idevice.h"
30#include "userpref.h" 64#include "lockdown.h"
31#include "debug.h" 65#include "common/userpref.h"
66#include "common/debug.h"
67
68#ifndef ECONNREFUSED
69#define ECONNREFUSED 107
70#endif
71#ifndef ETIMEDOUT
72#define ETIMEDOUT 138
73#endif
74
75
76#ifdef HAVE_OPENSSL
77
78#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
79 (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x20020000L))
80#define TLS_method TLSv1_method
81#endif
82
83#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
84static void SSL_COMP_free_compression_methods(void)
85{
86 sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
87}
88#endif
89
90static void openssl_remove_thread_state(void)
91{
92/* ERR_remove_thread_state() is available since OpenSSL 1.0.0-beta1, but
93 * deprecated in OpenSSL 1.1.0 */
94#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
95#if OPENSSL_VERSION_NUMBER >= 0x10000001L
96 ERR_remove_thread_state(NULL);
97#else
98 ERR_remove_state(0);
99#endif
100#endif
101}
102
103#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
104static mutex_t *mutex_buf = NULL;
105static void locking_function(int mode, int n, const char* file, int line)
106{
107 if (mode & CRYPTO_LOCK)
108 mutex_lock(&mutex_buf[n]);
109 else
110 mutex_unlock(&mutex_buf[n]);
111}
112
113#if OPENSSL_VERSION_NUMBER < 0x10000000L
114static unsigned long id_function(void)
115{
116 return ((unsigned long)THREAD_ID);
117}
118#else
119static void id_function(CRYPTO_THREADID *thread)
120{
121 CRYPTO_THREADID_set_numeric(thread, (unsigned long)THREAD_ID);
122}
123#endif
124#endif
125#endif /* HAVE_OPENSSL */
126
127static void internal_idevice_init(void)
128{
129#if defined(HAVE_OPENSSL)
130#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
131 int i;
132 SSL_library_init();
133
134 mutex_buf = malloc(CRYPTO_num_locks() * sizeof(mutex_t));
135 if (!mutex_buf)
136 return;
137 for (i = 0; i < CRYPTO_num_locks(); i++)
138 mutex_init(&mutex_buf[i]);
139
140#if OPENSSL_VERSION_NUMBER < 0x10000000L
141 CRYPTO_set_id_callback(id_function);
142#else
143 CRYPTO_THREADID_set_callback(id_function);
144#endif
145 CRYPTO_set_locking_callback(locking_function);
146#endif
147#elif defined(HAVE_GNUTLS)
148 gnutls_global_init();
149#elif defined(HAVE_MBEDTLS)
150 // NO-OP
151#endif
152}
153
154static void internal_idevice_deinit(void)
155{
156#if defined(HAVE_OPENSSL)
157#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
158 int i;
159 if (mutex_buf) {
160#if OPENSSL_VERSION_NUMBER < 0x10000000L
161 CRYPTO_set_id_callback(NULL);
162#else
163 CRYPTO_THREADID_set_callback(NULL);
164#endif
165 CRYPTO_set_locking_callback(NULL);
166 for (i = 0; i < CRYPTO_num_locks(); i++)
167 mutex_destroy(&mutex_buf[i]);
168 free(mutex_buf);
169 mutex_buf = NULL;
170 }
171
172 EVP_cleanup();
173 CRYPTO_cleanup_all_ex_data();
174 SSL_COMP_free_compression_methods();
175 openssl_remove_thread_state();
176#endif
177#elif defined(HAVE_GNUTLS)
178 gnutls_global_deinit();
179#elif defined(HAVE_MBEDTLS)
180 // NO-OP
181#endif
182}
183
184static thread_once_t init_once = THREAD_ONCE_INIT;
185static thread_once_t deinit_once = THREAD_ONCE_INIT;
186
187#ifndef HAVE_ATTRIBUTE_CONSTRUCTOR
188 #if defined(__llvm__) || defined(__GNUC__)
189 #define HAVE_ATTRIBUTE_CONSTRUCTOR
190 #endif
191#endif
192
193#ifdef HAVE_ATTRIBUTE_CONSTRUCTOR
194static void __attribute__((constructor)) libimobiledevice_initialize(void)
195{
196 thread_once(&init_once, internal_idevice_init);
197}
198
199static void __attribute__((destructor)) libimobiledevice_deinitialize(void)
200{
201 thread_once(&deinit_once, internal_idevice_deinit);
202}
203#elif defined(WIN32)
204BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
205{
206 switch (dwReason) {
207 case DLL_PROCESS_ATTACH:
208 thread_once(&init_once, internal_idevice_init);
209 break;
210 case DLL_PROCESS_DETACH:
211 thread_once(&deinit_once, internal_idevice_deinit);
212 break;
213 default:
214 break;
215 }
216 return 1;
217}
218#else
219#warning No compiler support for constructor/destructor attributes, some features might not be available.
220#endif
221
222const char* libimobiledevice_version()
223{
224#ifndef PACKAGE_VERSION
225#error PACKAGE_VERSION is not defined!
226#endif
227 return PACKAGE_VERSION;
228}
229
230struct idevice_subscription_context {
231 idevice_event_cb_t callback;
232 void *user_data;
233 usbmuxd_subscription_context_t ctx;
234};
32 235
33static idevice_event_cb_t event_cb = NULL; 236static idevice_subscription_context_t event_ctx = NULL;
34 237
35static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data) 238static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data)
36{ 239{
240 idevice_subscription_context_t context = (idevice_subscription_context_t)user_data;
37 idevice_event_t ev; 241 idevice_event_t ev;
38 242
39 ev.event = event->event; 243 ev.event = event->event;
40 ev.uuid = event->device.uuid; 244 ev.udid = event->device.udid;
41 ev.conn_type = CONNECTION_USBMUXD; 245 ev.conn_type = 0;
246 if (event->device.conn_type == CONNECTION_TYPE_USB) {
247 ev.conn_type = CONNECTION_USBMUXD;
248 } else if (event->device.conn_type == CONNECTION_TYPE_NETWORK) {
249 ev.conn_type = CONNECTION_NETWORK;
250 } else {
251 debug_info("Unknown connection type %d", event->device.conn_type);
252 }
42 253
43 if (event_cb) { 254 if (context->callback) {
44 event_cb(&ev, user_data); 255 context->callback(&ev, context->user_data);
45 } 256 }
46} 257}
47 258
48/** 259idevice_error_t idevice_events_subscribe(idevice_subscription_context_t *context, idevice_event_cb_t callback, void *user_data)
49 * Register a callback function that will be called when device add/remove
50 * events occur.
51 *
52 * @param callback Callback function to call.
53 * @param user_data Application-specific data passed as parameter
54 * to the registered callback function.
55 *
56 * @return IDEVICE_E_SUCCESS on success or an error value when an error occured.
57 */
58idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data)
59{ 260{
60 event_cb = callback; 261 if (!context || !callback) {
61 int res = usbmuxd_subscribe(usbmux_event_cb, user_data); 262 return IDEVICE_E_INVALID_ARG;
62 if (res != 0) { 263 }
63 event_cb = NULL; 264 *context = malloc(sizeof(struct idevice_subscription_context));
64 debug_info("Error %d when subscribing usbmux event callback!", res); 265 if (!*context) {
266 debug_info("ERROR: %s: Failed to allocate subscription context\n", __func__);
267 return IDEVICE_E_UNKNOWN_ERROR;
268 }
269 (*context)->callback = callback;
270 (*context)->user_data = user_data;
271 int res = usbmuxd_events_subscribe(&(*context)->ctx, usbmux_event_cb, *context);
272 if (res != 0) {
273 free(*context);
274 *context = NULL;
275 debug_info("ERROR: usbmuxd_subscribe() returned %d!", res);
65 return IDEVICE_E_UNKNOWN_ERROR; 276 return IDEVICE_E_UNKNOWN_ERROR;
66 } 277 }
67 return IDEVICE_E_SUCCESS; 278 return IDEVICE_E_SUCCESS;
68} 279}
69 280
70/** 281idevice_error_t idevice_events_unsubscribe(idevice_subscription_context_t context)
71 * Release the event callback function that has been registered with
72 * idevice_event_subscribe().
73 *
74 * @return IDEVICE_E_SUCCESS on success or an error value when an error occured.
75 */
76idevice_error_t idevice_event_unsubscribe()
77{ 282{
78 event_cb = NULL; 283 if (!context) {
79 int res = usbmuxd_unsubscribe(); 284 return IDEVICE_E_INVALID_ARG;
285 }
286 int res = usbmuxd_events_unsubscribe(context->ctx);
80 if (res != 0) { 287 if (res != 0) {
81 debug_info("Error %d when unsubscribing usbmux event callback!", res); 288 debug_info("ERROR: usbmuxd_unsubscribe() returned %d!", res);
82 return IDEVICE_E_UNKNOWN_ERROR; 289 return IDEVICE_E_UNKNOWN_ERROR;
83 } 290 }
291 if (context == event_ctx) {
292 event_ctx = NULL;
293 }
294 free(context);
295 return IDEVICE_E_SUCCESS;
296}
297
298idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data)
299{
300 if (event_ctx) {
301 idevice_events_unsubscribe(event_ctx);
302 }
303 return idevice_events_subscribe(&event_ctx, callback, user_data);
304}
305
306idevice_error_t idevice_event_unsubscribe(void)
307{
308 if (!event_ctx) {
309 return IDEVICE_E_SUCCESS;
310 }
311 event_ctx->callback = NULL;
312 return idevice_events_unsubscribe(event_ctx);
313}
314
315idevice_error_t idevice_get_device_list_extended(idevice_info_t **devices, int *count)
316{
317 usbmuxd_device_info_t *dev_list;
318
319 *devices = NULL;
320 *count = 0;
321
322 if (usbmuxd_get_device_list(&dev_list) < 0) {
323 debug_info("ERROR: usbmuxd is not running!", __func__);
324 return IDEVICE_E_NO_DEVICE;
325 }
326
327 idevice_info_t *newlist = NULL;
328 int i, newcount = 0;
329
330 for (i = 0; dev_list[i].handle > 0; i++) {
331 newlist = realloc(*devices, sizeof(idevice_info_t) * (newcount+1));
332 newlist[newcount] = malloc(sizeof(struct idevice_info));
333 newlist[newcount]->udid = strdup(dev_list[i].udid);
334 if (dev_list[i].conn_type == CONNECTION_TYPE_USB) {
335 newlist[newcount]->conn_type = CONNECTION_USBMUXD;
336 newlist[newcount]->conn_data = NULL;
337 } else if (dev_list[i].conn_type == CONNECTION_TYPE_NETWORK) {
338 newlist[newcount]->conn_type = CONNECTION_NETWORK;
339 struct sockaddr* saddr = (struct sockaddr*)(dev_list[i].conn_data);
340 size_t addrlen = 0;
341 switch (saddr->sa_family) {
342 case AF_INET:
343 addrlen = sizeof(struct sockaddr_in);
344 break;
345#ifdef AF_INET6
346 case AF_INET6:
347 addrlen = sizeof(struct sockaddr_in6);
348 break;
349#endif
350 default:
351 debug_info("Unsupported address family 0x%02x\n", saddr->sa_family);
352 continue;
353 }
354 newlist[newcount]->conn_data = malloc(addrlen);
355 memcpy(newlist[newcount]->conn_data, dev_list[i].conn_data, addrlen);
356 }
357 newcount++;
358 *devices = newlist;
359 }
360 usbmuxd_device_list_free(&dev_list);
361
362 *count = newcount;
363 newlist = realloc(*devices, sizeof(idevice_info_t) * (newcount+1));
364 newlist[newcount] = NULL;
365 *devices = newlist;
366
367 return IDEVICE_E_SUCCESS;
368}
369
370idevice_error_t idevice_device_list_extended_free(idevice_info_t *devices)
371{
372 if (devices) {
373 int i = 0;
374 while (devices[i]) {
375 free(devices[i]->udid);
376 free(devices[i]->conn_data);
377 free(devices[i]);
378 i++;
379 }
380 free(devices);
381 }
84 return IDEVICE_E_SUCCESS; 382 return IDEVICE_E_SUCCESS;
85} 383}
86 384
87/**
88 * Get a list of currently available devices.
89 *
90 * @param devices List of uuids of devices that are currently available.
91 * This list is terminated by a NULL pointer.
92 * @param count Number of devices found.
93 *
94 * @return IDEVICE_E_SUCCESS on success or an error value when an error occured.
95 */
96idevice_error_t idevice_get_device_list(char ***devices, int *count) 385idevice_error_t idevice_get_device_list(char ***devices, int *count)
97{ 386{
98 usbmuxd_device_info_t *dev_list; 387 usbmuxd_device_info_t *dev_list;
@@ -101,7 +390,7 @@ idevice_error_t idevice_get_device_list(char ***devices, int *count)
101 *count = 0; 390 *count = 0;
102 391
103 if (usbmuxd_get_device_list(&dev_list) < 0) { 392 if (usbmuxd_get_device_list(&dev_list) < 0) {
104 debug_info("ERROR: usbmuxd is not running!\n", __func__); 393 debug_info("ERROR: usbmuxd is not running!", __func__);
105 return IDEVICE_E_NO_DEVICE; 394 return IDEVICE_E_NO_DEVICE;
106 } 395 }
107 396
@@ -109,9 +398,11 @@ idevice_error_t idevice_get_device_list(char ***devices, int *count)
109 int i, newcount = 0; 398 int i, newcount = 0;
110 399
111 for (i = 0; dev_list[i].handle > 0; i++) { 400 for (i = 0; dev_list[i].handle > 0; i++) {
112 newlist = realloc(*devices, sizeof(char*) * (newcount+1)); 401 if (dev_list[i].conn_type == CONNECTION_TYPE_USB) {
113 newlist[newcount++] = strdup(dev_list[i].uuid); 402 newlist = realloc(*devices, sizeof(char*) * (newcount+1));
114 *devices = newlist; 403 newlist[newcount++] = strdup(dev_list[i].udid);
404 *devices = newlist;
405 }
115 } 406 }
116 usbmuxd_device_list_free(&dev_list); 407 usbmuxd_device_list_free(&dev_list);
117 408
@@ -123,62 +414,101 @@ idevice_error_t idevice_get_device_list(char ***devices, int *count)
123 return IDEVICE_E_SUCCESS; 414 return IDEVICE_E_SUCCESS;
124} 415}
125 416
126/**
127 * Free a list of device uuids.
128 *
129 * @param devices List of uuids to free.
130 *
131 * @return Always returnes IDEVICE_E_SUCCESS.
132 */
133idevice_error_t idevice_device_list_free(char **devices) 417idevice_error_t idevice_device_list_free(char **devices)
134{ 418{
135 if (devices) { 419 if (devices) {
136 int i = 0; 420 int i = 0;
137 while (devices[i++]) { 421 while (devices[i]) {
138 free(devices[i]); 422 free(devices[i]);
423 i++;
139 } 424 }
140 free(devices); 425 free(devices);
141 } 426 }
142 return IDEVICE_E_SUCCESS; 427 return IDEVICE_E_SUCCESS;
143} 428}
144 429
145/** 430void idevice_set_debug_level(int level)
146 * Creates an idevice_t structure for the device specified by uuid, 431{
147 * if the device is available. 432 internal_set_debug_level(level);
148 * 433}
149 * @note The resulting idevice_t structure has to be freed with 434
150 * idevice_free() if it is no longer used. 435static idevice_t idevice_from_mux_device(usbmuxd_device_info_t *muxdev)
151 * 436{
152 * @param device Upon calling this function, a pointer to a location of type 437 if (!muxdev)
153 * idevice_t. On successful return, this location will be populated. 438 return NULL;
154 * @param uuid The UUID to match. 439
155 * 440 idevice_t device = (idevice_t)malloc(sizeof(struct idevice_private));
156 * @return IDEVICE_E_SUCCESS if ok, otherwise an error code. 441 if (!device)
157 */ 442 return NULL;
158idevice_error_t idevice_new(idevice_t * device, const char *uuid) 443
444 device->udid = strdup(muxdev->udid);
445 device->mux_id = muxdev->handle;
446 device->version = 0;
447 device->device_class = 0;
448 switch (muxdev->conn_type) {
449 case CONNECTION_TYPE_USB:
450 device->conn_type = CONNECTION_USBMUXD;
451 device->conn_data = NULL;
452 break;
453 case CONNECTION_TYPE_NETWORK:
454 device->conn_type = CONNECTION_NETWORK;
455 struct sockaddr* saddr = (struct sockaddr*)(muxdev->conn_data);
456 size_t addrlen = 0;
457 switch (saddr->sa_family) {
458 case AF_INET:
459 addrlen = sizeof(struct sockaddr_in);
460 break;
461#ifdef AF_INET6
462 case AF_INET6:
463 addrlen = sizeof(struct sockaddr_in6);
464 break;
465#endif
466 default:
467 debug_info("Unsupported address family 0x%02x\n", saddr->sa_family);
468 free(device->udid);
469 free(device);
470 return NULL;
471 }
472 device->conn_data = malloc(addrlen);
473 memcpy(device->conn_data, muxdev->conn_data, addrlen);
474 break;
475 default:
476 device->conn_type = 0;
477 device->conn_data = NULL;
478 break;
479 }
480 return device;
481}
482
483idevice_error_t idevice_new_with_options(idevice_t * device, const char *udid, enum idevice_options options)
159{ 484{
160 usbmuxd_device_info_t muxdev; 485 usbmuxd_device_info_t muxdev;
161 int res = usbmuxd_get_device_by_uuid(uuid, &muxdev); 486 int usbmux_options = 0;
487 if (options & IDEVICE_LOOKUP_USBMUX) {
488 usbmux_options |= DEVICE_LOOKUP_USBMUX;
489 }
490 if (options & IDEVICE_LOOKUP_NETWORK) {
491 usbmux_options |= DEVICE_LOOKUP_NETWORK;
492 }
493 if (options & IDEVICE_LOOKUP_PREFER_NETWORK) {
494 usbmux_options |= DEVICE_LOOKUP_PREFER_NETWORK;
495 }
496 int res = usbmuxd_get_device(udid, &muxdev, usbmux_options);
162 if (res > 0) { 497 if (res > 0) {
163 idevice_t phone = (idevice_t) malloc(sizeof(struct idevice_private)); 498 *device = idevice_from_mux_device(&muxdev);
164 phone->uuid = strdup(muxdev.uuid); 499 if (!*device) {
165 phone->conn_type = CONNECTION_USBMUXD; 500 return IDEVICE_E_UNKNOWN_ERROR;
166 phone->conn_data = (void*)(long)muxdev.handle; 501 }
167 *device = phone;
168 return IDEVICE_E_SUCCESS; 502 return IDEVICE_E_SUCCESS;
169 } 503 }
170 /* other connection types could follow here */
171
172 return IDEVICE_E_NO_DEVICE; 504 return IDEVICE_E_NO_DEVICE;
173} 505}
174 506
175/** 507idevice_error_t idevice_new(idevice_t * device, const char *udid)
176 * Cleans up an idevice structure, then frees the structure itself. 508{
177 * This is a library-level function; deals directly with the device to tear 509 return idevice_new_with_options(device, udid, 0);
178 * down relations, but otherwise is mostly internal. 510}
179 * 511
180 * @param device idevice_t to free.
181 */
182idevice_error_t idevice_free(idevice_t device) 512idevice_error_t idevice_free(idevice_t device)
183{ 513{
184 if (!device) 514 if (!device)
@@ -187,11 +517,8 @@ idevice_error_t idevice_free(idevice_t device)
187 517
188 ret = IDEVICE_E_SUCCESS; 518 ret = IDEVICE_E_SUCCESS;
189 519
190 free(device->uuid); 520 free(device->udid);
191 521
192 if (device->conn_type == CONNECTION_USBMUXD) {
193 device->conn_data = 0;
194 }
195 if (device->conn_data) { 522 if (device->conn_data) {
196 free(device->conn_data); 523 free(device->conn_data);
197 } 524 }
@@ -199,16 +526,6 @@ idevice_error_t idevice_free(idevice_t device)
199 return ret; 526 return ret;
200} 527}
201 528
202/**
203 * Set up a connection to the given device.
204 *
205 * @param device The device to connect to.
206 * @param port The destination port to connect to.
207 * @param connection Pointer to an idevice_connection_t that will be filled
208 * with the necessary data of the connection.
209 *
210 * @return IDEVICE_E_SUCCESS if ok, otherwise an error code.
211 */
212idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connection_t *connection) 529idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connection_t *connection)
213{ 530{
214 if (!device) { 531 if (!device) {
@@ -216,31 +533,80 @@ idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connect
216 } 533 }
217 534
218 if (device->conn_type == CONNECTION_USBMUXD) { 535 if (device->conn_type == CONNECTION_USBMUXD) {
219 int sfd = usbmuxd_connect((uint32_t)(long)device->conn_data, port); 536 int sfd = usbmuxd_connect(device->mux_id, port);
220 if (sfd < 0) { 537 if (sfd < 0) {
221 debug_info("ERROR: Connecting to usbmuxd failed: %d (%s)", sfd, strerror(-sfd)); 538 debug_info("ERROR: Connecting to usbmux device failed: %d (%s)", sfd, strerror(-sfd));
539 switch (-sfd) {
540 case ECONNREFUSED:
541 return IDEVICE_E_CONNREFUSED;
542 case ENODEV:
543 return IDEVICE_E_NO_DEVICE;
544 default:
545 break;
546 }
222 return IDEVICE_E_UNKNOWN_ERROR; 547 return IDEVICE_E_UNKNOWN_ERROR;
223 } 548 }
224 idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private)); 549 idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private));
225 new_connection->type = CONNECTION_USBMUXD; 550 new_connection->type = CONNECTION_USBMUXD;
226 new_connection->data = (void*)(long)sfd; 551 new_connection->data = (void*)(long)sfd;
227 new_connection->ssl_data = NULL; 552 new_connection->ssl_data = NULL;
553 new_connection->device = device;
554 new_connection->ssl_recv_timeout = (unsigned int)-1;
555 new_connection->status = IDEVICE_E_SUCCESS;
228 *connection = new_connection; 556 *connection = new_connection;
229 return IDEVICE_E_SUCCESS; 557 return IDEVICE_E_SUCCESS;
230 } else { 558 }
231 debug_info("Unknown connection type %d", device->conn_type); 559 if (device->conn_type == CONNECTION_NETWORK) {
560 struct sockaddr* saddr = (struct sockaddr*)(device->conn_data);
561 switch (saddr->sa_family) {
562 case AF_INET:
563#ifdef AF_INET6
564 case AF_INET6:
565#endif
566 break;
567 default:
568 debug_info("Unsupported address family 0x%02x", saddr->sa_family);
569 return IDEVICE_E_UNKNOWN_ERROR;
570 }
571
572 char addrtxt[48];
573 addrtxt[0] = '\0';
574
575 if (!socket_addr_to_string(saddr, addrtxt, sizeof(addrtxt))) {
576 debug_info("Failed to convert network address: %d (%s)", errno, strerror(errno));
577 }
578
579 debug_info("Connecting to %s port %d...", addrtxt, port);
580
581 int sfd = socket_connect_addr(saddr, port);
582 if (sfd < 0) {
583 int result = errno;
584 debug_info("ERROR: Connecting to network device failed: %d (%s)", result, strerror(result));
585 switch (result) {
586 case ECONNREFUSED:
587 return IDEVICE_E_CONNREFUSED;
588 default:
589 break;
590 }
591 return IDEVICE_E_NO_DEVICE;
592 }
593
594 idevice_connection_t new_connection = (idevice_connection_t)malloc(sizeof(struct idevice_connection_private));
595 new_connection->type = CONNECTION_NETWORK;
596 new_connection->data = (void*)(long)sfd;
597 new_connection->ssl_data = NULL;
598 new_connection->device = device;
599 new_connection->ssl_recv_timeout = (unsigned int)-1;
600
601 *connection = new_connection;
602
603 return IDEVICE_E_SUCCESS;
232 } 604 }
233 605
606 debug_info("Unknown connection type %d", device->conn_type);
234 return IDEVICE_E_UNKNOWN_ERROR; 607 return IDEVICE_E_UNKNOWN_ERROR;
235} 608}
236 609
237/**
238 * Disconnect from the device and clean up the connection structure.
239 *
240 * @param connection The connection to close.
241 *
242 * @return IDEVICE_E_SUCCESS if ok, otherwise an error code.
243 */
244idevice_error_t idevice_disconnect(idevice_connection_t connection) 610idevice_error_t idevice_disconnect(idevice_connection_t connection)
245{ 611{
246 if (!connection) { 612 if (!connection) {
@@ -253,11 +619,19 @@ idevice_error_t idevice_disconnect(idevice_connection_t connection)
253 idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; 619 idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR;
254 if (connection->type == CONNECTION_USBMUXD) { 620 if (connection->type == CONNECTION_USBMUXD) {
255 usbmuxd_disconnect((int)(long)connection->data); 621 usbmuxd_disconnect((int)(long)connection->data);
622 connection->data = NULL;
623 result = IDEVICE_E_SUCCESS;
624 } else if (connection->type == CONNECTION_NETWORK) {
625 socket_close((int)(long)connection->data);
626 connection->data = NULL;
256 result = IDEVICE_E_SUCCESS; 627 result = IDEVICE_E_SUCCESS;
257 } else { 628 } else {
258 debug_info("Unknown connection type %d", connection->type); 629 debug_info("Unknown connection type %d", connection->type);
259 } 630 }
631
260 free(connection); 632 free(connection);
633 connection = NULL;
634
261 return result; 635 return result;
262} 636}
263 637
@@ -271,46 +645,111 @@ static idevice_error_t internal_connection_send(idevice_connection_t connection,
271 } 645 }
272 646
273 if (connection->type == CONNECTION_USBMUXD) { 647 if (connection->type == CONNECTION_USBMUXD) {
274 int res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes); 648 int res;
649 do {
650 res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes);
651 } while (res == -EAGAIN);
275 if (res < 0) { 652 if (res < 0) {
276 debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res)); 653 debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res));
277 return IDEVICE_E_UNKNOWN_ERROR; 654 return IDEVICE_E_UNKNOWN_ERROR;
278 } 655 }
279 return IDEVICE_E_SUCCESS; 656 return IDEVICE_E_SUCCESS;
280 } else {
281 debug_info("Unknown connection type %d", connection->type);
282 } 657 }
658 if (connection->type == CONNECTION_NETWORK) {
659 int s = socket_send((int)(long)connection->data, (void*)data, len);
660 if (s < 0) {
661 *sent_bytes = 0;
662 return IDEVICE_E_UNKNOWN_ERROR;
663 }
664 *sent_bytes = s;
665 return IDEVICE_E_SUCCESS;
666 }
667
668 debug_info("Unknown connection type %d", connection->type);
283 return IDEVICE_E_UNKNOWN_ERROR; 669 return IDEVICE_E_UNKNOWN_ERROR;
284 670
285} 671}
286 672
287/**
288 * Send data to a device via the given connection.
289 *
290 * @param connection The connection to send data over.
291 * @param data Buffer with data to send.
292 * @param len Size of the buffer to send.
293 * @param sent_bytes Pointer to an uint32_t that will be filled
294 * with the number of bytes actually sent.
295 *
296 * @return IDEVICE_E_SUCCESS if ok, otherwise an error code.
297 */
298idevice_error_t idevice_connection_send(idevice_connection_t connection, const char *data, uint32_t len, uint32_t *sent_bytes) 673idevice_error_t idevice_connection_send(idevice_connection_t connection, const char *data, uint32_t len, uint32_t *sent_bytes)
299{ 674{
300 if (!connection || !data || (connection->ssl_data && !connection->ssl_data->session)) { 675 if (!connection || !data
676#if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS)
677 || (connection->ssl_data && !connection->ssl_data->session)
678#endif
679 ) {
301 return IDEVICE_E_INVALID_ARG; 680 return IDEVICE_E_INVALID_ARG;
302 } 681 }
303 682
304 if (connection->ssl_data) { 683 if (connection->ssl_data) {
305 ssize_t sent = gnutls_record_send(connection->ssl_data->session, (void*)data, (size_t)len); 684 connection->status = IDEVICE_E_SUCCESS;
306 if ((uint32_t)sent == (uint32_t)len) { 685 uint32_t sent = 0;
307 *sent_bytes = sent; 686 while (sent < len) {
308 return IDEVICE_E_SUCCESS; 687#if defined(HAVE_OPENSSL)
688 int s = SSL_write(connection->ssl_data->session, (const void*)(data+sent), (int)(len-sent));
689 if (s <= 0) {
690 int sslerr = SSL_get_error(connection->ssl_data->session, s);
691 if (sslerr == SSL_ERROR_WANT_WRITE) {
692 continue;
693 }
694 break;
695 }
696#elif defined(HAVE_GNUTLS)
697 ssize_t s = gnutls_record_send(connection->ssl_data->session, (void*)(data+sent), (size_t)(len-sent));
698#elif defined(HAVE_MBEDTLS)
699 int s = mbedtls_ssl_write(&connection->ssl_data->ctx, (const unsigned char*)(data+sent), (size_t)(len-sent));
700#endif
701 if (s < 0) {
702 break;
703 }
704 sent += s;
705 }
706 debug_info("SSL_write %d, sent %d", len, sent);
707 if (sent < len) {
708 *sent_bytes = 0;
709 return connection->status == IDEVICE_E_SUCCESS ? IDEVICE_E_SSL_ERROR : connection->status;
710 }
711 *sent_bytes = sent;
712 return IDEVICE_E_SUCCESS;
713 }
714 uint32_t sent = 0;
715 while (sent < len) {
716 uint32_t bytes = 0;
717 int s = internal_connection_send(connection, data+sent, len-sent, &bytes);
718 if (s < 0) {
719 break;
720 }
721 sent += bytes;
722 }
723 debug_info("internal_connection_send %d, sent %d", len, sent);
724 if (sent < len) {
725 *sent_bytes = sent;
726 if (sent == 0) {
727 return IDEVICE_E_UNKNOWN_ERROR;
728 }
729 return IDEVICE_E_NOT_ENOUGH_DATA;
730 }
731 *sent_bytes = sent;
732 return IDEVICE_E_SUCCESS;
733}
734
735static inline idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received)
736{
737 if (conn_error < 0) {
738 switch (conn_error) {
739 case -EAGAIN:
740 if (len) {
741 debug_info("ERROR: received partial data %d/%d (%s)", received, len, strerror(-conn_error));
742 } else {
743 debug_info("ERROR: received partial data (%s)", strerror(-conn_error));
744 }
745 return IDEVICE_E_NOT_ENOUGH_DATA;
746 case -ETIMEDOUT:
747 return IDEVICE_E_TIMEOUT;
748 default:
749 return IDEVICE_E_UNKNOWN_ERROR;
309 } 750 }
310 *sent_bytes = 0;
311 return IDEVICE_E_SSL_ERROR;
312 } 751 }
313 return internal_connection_send(connection, data, len, sent_bytes); 752 return IDEVICE_E_SUCCESS;
314} 753}
315 754
316/** 755/**
@@ -324,47 +763,92 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t
324 } 763 }
325 764
326 if (connection->type == CONNECTION_USBMUXD) { 765 if (connection->type == CONNECTION_USBMUXD) {
327 int res = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); 766 int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout);
328 if (res < 0) { 767 idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes);
329 debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", res, strerror(-res)); 768 if (error == IDEVICE_E_UNKNOWN_ERROR) {
330 return IDEVICE_E_UNKNOWN_ERROR; 769 debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", conn_error, strerror(-conn_error));
331 } 770 }
332 return IDEVICE_E_SUCCESS; 771 return error;
333 } else {
334 debug_info("Unknown connection type %d", connection->type);
335 } 772 }
773 if (connection->type == CONNECTION_NETWORK) {
774 int res = socket_receive_timeout((int)(long)connection->data, data, len, 0, timeout);
775 idevice_error_t error = socket_recv_to_idevice_error(res, 0, 0);
776 if (error == IDEVICE_E_SUCCESS) {
777 *recv_bytes = (uint32_t)res;
778 } else if (error == IDEVICE_E_UNKNOWN_ERROR) {
779 debug_info("ERROR: socket_receive_timeout returned %d (%s)", res, strerror(-res));
780 }
781 return error;
782 }
783
784 debug_info("Unknown connection type %d", connection->type);
336 return IDEVICE_E_UNKNOWN_ERROR; 785 return IDEVICE_E_UNKNOWN_ERROR;
337} 786}
338 787
339/**
340 * Receive data from a device via the given connection.
341 * This function will return after the given timeout even if no data has been
342 * received.
343 *
344 * @param connection The connection to receive data from.
345 * @param data Buffer that will be filled with the received data.
346 * This buffer has to be large enough to hold len bytes.
347 * @param len Buffer size or number of bytes to receive.
348 * @param recv_bytes Number of bytes actually received.
349 * @param timeout Timeout in milliseconds after which this function should
350 * return even if no data has been received.
351 *
352 * @return IDEVICE_E_SUCCESS if ok, otherwise an error code.
353 */
354idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout) 788idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
355{ 789{
356 if (!connection || (connection->ssl_data && !connection->ssl_data->session)) { 790 if (!connection
791#if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS)
792 || (connection->ssl_data && !connection->ssl_data->session)
793#endif
794 || len == 0
795 ) {
357 return IDEVICE_E_INVALID_ARG; 796 return IDEVICE_E_INVALID_ARG;
358 } 797 }
359 798
360 if (connection->ssl_data) { 799 if (connection->ssl_data) {
361 ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); 800 uint32_t received = 0;
362 if (received > 0) { 801
802 if (connection->ssl_recv_timeout != (unsigned int)-1) {
803 debug_info("WARNING: ssl_recv_timeout was not properly reset in idevice_connection_receive_timeout");
804 }
805
806 // this should be reset after the SSL_read call on all codepaths, as
807 // the supplied timeout should only apply to the current read.
808 connection->ssl_recv_timeout = timeout;
809 connection->status = IDEVICE_E_SUCCESS;
810 while (received < len) {
811#if defined(HAVE_OPENSSL)
812 int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received);
813 if (r > 0) {
814 received += r;
815 } else {
816 int sslerr = SSL_get_error(connection->ssl_data->session, r);
817 if (sslerr == SSL_ERROR_WANT_READ) {
818 continue;
819 } else if (sslerr == SSL_ERROR_ZERO_RETURN) {
820 if (connection->status == IDEVICE_E_TIMEOUT) {
821 SSL_set_shutdown(connection->ssl_data->session, 0);
822 }
823 }
824 break;
825 }
826#elif defined(HAVE_GNUTLS)
827 ssize_t r = gnutls_record_recv(connection->ssl_data->session, (void*)(data+received), (size_t)len-received);
828 if (r > 0) {
829 received += r;
830 } else {
831 break;
832 }
833#elif defined(HAVE_MBEDTLS)
834 int r = mbedtls_ssl_read(&connection->ssl_data->ctx, (void*)(data+received), (size_t)len-received);
835 if (r > 0) {
836 received += r;
837 } else {
838 break;
839 }
840#endif
841 }
842 connection->ssl_recv_timeout = (unsigned int)-1;
843
844 debug_info("SSL_read %d, received %d", len, received);
845 if (received < len) {
363 *recv_bytes = received; 846 *recv_bytes = received;
364 return IDEVICE_E_SUCCESS; 847 return connection->status == IDEVICE_E_SUCCESS ? IDEVICE_E_SSL_ERROR : connection->status;
365 } 848 }
366 *recv_bytes = 0; 849
367 return IDEVICE_E_SSL_ERROR; 850 *recv_bytes = received;
851 return IDEVICE_E_SUCCESS;
368 } 852 }
369 return internal_connection_receive_timeout(connection, data, len, recv_bytes, timeout); 853 return internal_connection_receive_timeout(connection, data, len, recv_bytes, timeout);
370} 854}
@@ -384,35 +868,45 @@ static idevice_error_t internal_connection_receive(idevice_connection_t connecti
384 debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res)); 868 debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res));
385 return IDEVICE_E_UNKNOWN_ERROR; 869 return IDEVICE_E_UNKNOWN_ERROR;
386 } 870 }
387
388 return IDEVICE_E_SUCCESS; 871 return IDEVICE_E_SUCCESS;
389 } else {
390 debug_info("Unknown connection type %d", connection->type);
391 } 872 }
873 if (connection->type == CONNECTION_NETWORK) {
874 int res = socket_receive((int)(long)connection->data, data, len);
875 if (res < 0) {
876 debug_info("ERROR: socket_receive returned %d (%s)", res, strerror(-res));
877 return IDEVICE_E_UNKNOWN_ERROR;
878 }
879 *recv_bytes = (uint32_t)res;
880 return IDEVICE_E_SUCCESS;
881 }
882
883 debug_info("Unknown connection type %d", connection->type);
392 return IDEVICE_E_UNKNOWN_ERROR; 884 return IDEVICE_E_UNKNOWN_ERROR;
393} 885}
394 886
395/**
396 * Receive data from a device via the given connection.
397 * This function is like idevice_connection_receive_timeout, but with a
398 * predefined reasonable timeout.
399 *
400 * @param connection The connection to receive data from.
401 * @param data Buffer that will be filled with the received data.
402 * This buffer has to be large enough to hold len bytes.
403 * @param len Buffer size or number of bytes to receive.
404 * @param recv_bytes Number of bytes actually received.
405 *
406 * @return IDEVICE_E_SUCCESS if ok, otherwise an error code.
407 */
408idevice_error_t idevice_connection_receive(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes) 887idevice_error_t idevice_connection_receive(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes)
409{ 888{
410 if (!connection || (connection->ssl_data && !connection->ssl_data->session)) { 889 if (!connection
890#if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS)
891 || (connection->ssl_data && !connection->ssl_data->session)
892#endif
893 ) {
411 return IDEVICE_E_INVALID_ARG; 894 return IDEVICE_E_INVALID_ARG;
412 } 895 }
413 896
414 if (connection->ssl_data) { 897 if (connection->ssl_data) {
898 if (connection->ssl_recv_timeout != (unsigned int)-1) {
899 debug_info("WARNING: ssl_recv_timeout was not properly reset in idevice_connection_receive_timeout");
900 connection->ssl_recv_timeout = (unsigned int)-1;
901 }
902#if defined(HAVE_OPENSSL)
903 int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len);
904 debug_info("SSL_read %d, received %d", len, received);
905#elif defined(HAVE_GNUTLS)
415 ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); 906 ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len);
907#elif defined(HAVE_MBEDTLS)
908 int received = mbedtls_ssl_read(&connection->ssl_data->ctx, (unsigned char*)data, (size_t)len);
909#endif
416 if (received > 0) { 910 if (received > 0) {
417 *recv_bytes = received; 911 *recv_bytes = received;
418 return IDEVICE_E_SUCCESS; 912 return IDEVICE_E_SUCCESS;
@@ -423,89 +917,105 @@ idevice_error_t idevice_connection_receive(idevice_connection_t connection, char
423 return internal_connection_receive(connection, data, len, recv_bytes); 917 return internal_connection_receive(connection, data, len, recv_bytes);
424} 918}
425 919
426/** 920idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int *fd)
427 * Gets the handle of the device. Depends on the connection type.
428 */
429idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle)
430{ 921{
431 if (!device) 922 if (!connection || !fd) {
432 return IDEVICE_E_INVALID_ARG; 923 return IDEVICE_E_INVALID_ARG;
924 }
433 925
434 if (device->conn_type == CONNECTION_USBMUXD) { 926 if (connection->type == CONNECTION_USBMUXD) {
435 *handle = (uint32_t)(long)device->conn_data; 927 *fd = (int)(long)connection->data;
928 return IDEVICE_E_SUCCESS;
929 }
930 if (connection->type == CONNECTION_NETWORK) {
931 *fd = (int)(long)connection->data;
436 return IDEVICE_E_SUCCESS; 932 return IDEVICE_E_SUCCESS;
437 } else {
438 debug_info("Unknown connection type %d", device->conn_type);
439 } 933 }
934
935 debug_info("Unknown connection type %d", connection->type);
440 return IDEVICE_E_UNKNOWN_ERROR; 936 return IDEVICE_E_UNKNOWN_ERROR;
441} 937}
442 938
443/** 939idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle)
444 * Gets the unique id for the device. 940{
445 */ 941 if (!device || !handle)
446idevice_error_t idevice_get_uuid(idevice_t device, char **uuid) 942 return IDEVICE_E_INVALID_ARG;
943
944 *handle = device->mux_id;
945 return IDEVICE_E_SUCCESS;
946}
947
948idevice_error_t idevice_get_udid(idevice_t device, char **udid)
447{ 949{
448 if (!device || !uuid) 950 if (!device || !udid)
449 return IDEVICE_E_INVALID_ARG; 951 return IDEVICE_E_INVALID_ARG;
450 952
451 *uuid = strdup(device->uuid); 953 if (device->udid) {
954 *udid = strdup(device->udid);
955 }
452 return IDEVICE_E_SUCCESS; 956 return IDEVICE_E_SUCCESS;
453} 957}
454 958
959#if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS)
960typedef ssize_t ssl_cb_ret_type_t;
961#elif defined(HAVE_MBEDTLS)
962typedef int ssl_cb_ret_type_t;
963#endif
964
455/** 965/**
456 * Internally used gnutls callback function for receiving encrypted data. 966 * Internally used SSL callback function for receiving encrypted data.
457 */ 967 */
458static ssize_t internal_ssl_read(gnutls_transport_ptr_t transport, char *buffer, size_t length) 968static ssl_cb_ret_type_t internal_ssl_read(idevice_connection_t connection, char *buffer, size_t length)
459{ 969{
460 int bytes = 0, pos_start_fill = 0; 970 uint32_t bytes = 0;
461 size_t tbytes = 0; 971 uint32_t pos = 0;
462 int this_len = length;
463 idevice_error_t res; 972 idevice_error_t res;
464 idevice_connection_t connection = (idevice_connection_t)transport; 973 unsigned int timeout = connection->ssl_recv_timeout;
465 char *recv_buffer;
466
467 debug_info("pre-read client wants %zi bytes", length);
468 974
469 recv_buffer = (char *) malloc(sizeof(char) * this_len); 975 debug_info("pre-read length = %zi bytes", length);
470 976
471 /* repeat until we have the full data or an error occurs */ 977 /* repeat until we have the full data or an error occurs */
472 do { 978 do {
473 if ((res = internal_connection_receive(connection, recv_buffer, this_len, (uint32_t*)&bytes)) != IDEVICE_E_SUCCESS) { 979 bytes = 0;
474 debug_info("ERROR: idevice_connection_receive returned %d", res); 980 if (timeout == (unsigned int)-1) {
475 return res; 981 res = internal_connection_receive(connection, buffer + pos, (uint32_t)length - pos, &bytes);
982 } else {
983 res = internal_connection_receive_timeout(connection, buffer + pos, (uint32_t)length - pos, &bytes, (unsigned int)timeout);
476 } 984 }
477 debug_info("post-read we got %i bytes", bytes); 985 if (res != IDEVICE_E_SUCCESS) {
986 if (res != IDEVICE_E_TIMEOUT) {
987 debug_info("ERROR: %s returned %d", (timeout == (unsigned int)-1) ? "internal_connection_receive" : "internal_connection_receive_timeout", res);
988 }
989 connection->status = res;
990 return -1;
991 }
992 debug_info("read %i bytes", bytes);
478 993
479 /* increase read count */ 994 /* increase read count */
480 tbytes += bytes; 995 pos += bytes;
481 996 if (pos < (uint32_t)length) {
482 /* fill the buffer with what we got right now */ 997 debug_info("re-read trying to read missing %i bytes", (uint32_t)length - pos);
483 memcpy(buffer + pos_start_fill, recv_buffer, bytes);
484 pos_start_fill += bytes;
485
486 if (tbytes >= length) {
487 break;
488 } 998 }
999 } while (pos < (uint32_t)length);
489 1000
490 this_len = length - tbytes; 1001 debug_info("post-read received %i bytes", pos);
491 debug_info("re-read trying to read missing %i bytes", this_len);
492 } while (tbytes < length);
493 1002
494 if (recv_buffer) { 1003 return pos;
495 free(recv_buffer);
496 }
497 return tbytes;
498} 1004}
499 1005
500/** 1006/**
501 * Internally used gnutls callback function for sending encrypted data. 1007 * Internally used SSL callback function for sending encrypted data.
502 */ 1008 */
503static ssize_t internal_ssl_write(gnutls_transport_ptr_t transport, char *buffer, size_t length) 1009static ssl_cb_ret_type_t internal_ssl_write(idevice_connection_t connection, const char *buffer, size_t length)
504{ 1010{
505 uint32_t bytes = 0; 1011 uint32_t bytes = 0;
506 idevice_connection_t connection = (idevice_connection_t)transport; 1012 idevice_error_t res;
507 debug_info("pre-send length = %zi", length); 1013 debug_info("pre-send length = %zi bytes", length);
508 internal_connection_send(connection, buffer, length, &bytes); 1014 if ((res = internal_connection_send(connection, buffer, length, &bytes)) != IDEVICE_E_SUCCESS) {
1015 debug_info("ERROR: internal_connection_send returned %d", res);
1016 connection->status = res;
1017 return -1;
1018 }
509 debug_info("post-send sent %i bytes", bytes); 1019 debug_info("post-send sent %i bytes", bytes);
510 return bytes; 1020 return bytes;
511} 1021}
@@ -518,6 +1028,14 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)
518 if (!ssl_data) 1028 if (!ssl_data)
519 return; 1029 return;
520 1030
1031#if defined(HAVE_OPENSSL)
1032 if (ssl_data->session) {
1033 SSL_free(ssl_data->session);
1034 }
1035 if (ssl_data->ctx) {
1036 SSL_CTX_free(ssl_data->ctx);
1037 }
1038#elif defined(HAVE_GNUTLS)
521 if (ssl_data->session) { 1039 if (ssl_data->session) {
522 gnutls_deinit(ssl_data->session); 1040 gnutls_deinit(ssl_data->session);
523 } 1041 }
@@ -536,20 +1054,118 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)
536 if (ssl_data->host_privkey) { 1054 if (ssl_data->host_privkey) {
537 gnutls_x509_privkey_deinit(ssl_data->host_privkey); 1055 gnutls_x509_privkey_deinit(ssl_data->host_privkey);
538 } 1056 }
1057#elif defined(HAVE_MBEDTLS)
1058 mbedtls_pk_free(&ssl_data->root_privkey);
1059 mbedtls_x509_crt_free(&ssl_data->certificate);
1060 mbedtls_entropy_free(&ssl_data->entropy);
1061 mbedtls_ctr_drbg_free(&ssl_data->ctr_drbg);
1062 mbedtls_ssl_config_free(&ssl_data->config);
1063 mbedtls_ssl_free(&ssl_data->ctx);
1064#endif
1065}
1066
1067#ifdef HAVE_OPENSSL
1068#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1069static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, size_t len, int argi, long argl, int retvalue, size_t *processed)
1070#else
1071static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, int argi, long argl, long retvalue)
1072#endif
1073{
1074 ssize_t bytes = 0;
1075 idevice_connection_t conn = (idevice_connection_t)BIO_get_callback_arg(b);
1076#if OPENSSL_VERSION_NUMBER < 0x30000000L
1077 size_t len = (size_t)argi;
1078 size_t *processed = (size_t*)&bytes;
1079#endif
1080 switch (oper) {
1081 case (BIO_CB_READ|BIO_CB_RETURN):
1082 if (argp) {
1083 bytes = internal_ssl_read(conn, (char *)argp, len);
1084 *processed = bytes;
1085 return (long)bytes;
1086 }
1087 return 0;
1088 case (BIO_CB_PUTS|BIO_CB_RETURN):
1089 len = strlen(argp);
1090 // fallthrough
1091 case (BIO_CB_WRITE|BIO_CB_RETURN):
1092 bytes = internal_ssl_write(conn, argp, len);
1093 *processed = bytes;
1094 return (long)bytes;
1095 default:
1096 return retvalue;
1097 }
1098}
1099
1100static BIO *ssl_idevice_bio_new(idevice_connection_t conn)
1101{
1102 BIO *b = BIO_new(BIO_s_null());
1103 if (!b) return NULL;
1104 BIO_set_callback_arg(b, (char *)conn);
1105#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1106 BIO_set_callback_ex(b, ssl_idevice_bio_callback);
1107#else
1108 BIO_set_callback(b, ssl_idevice_bio_callback);
1109#endif
1110 return b;
1111}
1112
1113static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx)
1114{
1115 return 1;
1116}
1117
1118#ifndef STRIP_DEBUG_CODE
1119static const char *ssl_error_to_string(int e)
1120{
1121 switch(e) {
1122 case SSL_ERROR_NONE:
1123 return "SSL_ERROR_NONE";
1124 case SSL_ERROR_SSL:
1125 return ERR_error_string(ERR_get_error(), NULL);
1126 case SSL_ERROR_WANT_READ:
1127 return "SSL_ERROR_WANT_READ";
1128 case SSL_ERROR_WANT_WRITE:
1129 return "SSL_ERROR_WANT_WRITE";
1130 case SSL_ERROR_WANT_X509_LOOKUP:
1131 return "SSL_ERROR_WANT_X509_LOOKUP";
1132 case SSL_ERROR_SYSCALL:
1133 return "SSL_ERROR_SYSCALL";
1134 case SSL_ERROR_ZERO_RETURN:
1135 return "SSL_ERROR_ZERO_RETURN";
1136 case SSL_ERROR_WANT_CONNECT:
1137 return "SSL_ERROR_WANT_CONNECT";
1138 case SSL_ERROR_WANT_ACCEPT:
1139 return "SSL_ERROR_WANT_ACCEPT";
1140 default:
1141 return "UNKOWN_ERROR_VALUE";
1142 }
539} 1143}
1144#endif
1145#endif
540 1146
1147#if defined(HAVE_GNUTLS)
541/** 1148/**
542 * Internally used gnutls callback function that gets called during handshake. 1149 * Internally used gnutls callback function that gets called during handshake.
543 */ 1150 */
544static 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) 1151#if GNUTLS_VERSION_NUMBER >= 0x020b07
1152static 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)
1153#else
1154static 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)
1155#endif
545{ 1156{
546 int res = -1; 1157 int res = -1;
547 gnutls_certificate_type_t type = gnutls_certificate_type_get (session); 1158 gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
548 if (type == GNUTLS_CRT_X509) { 1159 if (type == GNUTLS_CRT_X509) {
549 ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr (session); 1160 ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr(session);
550 if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) { 1161 if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) {
551 debug_info("Passing certificate"); 1162 debug_info("Passing certificate");
1163#if GNUTLS_VERSION_NUMBER >= 0x020b07
1164 st->cert_type = type;
1165 st->key_type = GNUTLS_PRIVKEY_X509;
1166#else
552 st->type = type; 1167 st->type = type;
1168#endif
553 st->ncerts = 1; 1169 st->ncerts = 1;
554 st->cert.x509 = &ssl_data->host_cert; 1170 st->cert.x509 = &ssl_data->host_cert;
555 st->key.x509 = ssl_data->host_privkey; 1171 st->key.x509 = ssl_data->host_privkey;
@@ -559,46 +1175,204 @@ static int internal_cert_callback (gnutls_session_t session, const gnutls_datum_
559 } 1175 }
560 return res; 1176 return res;
561} 1177}
1178#elif defined(HAVE_MBEDTLS)
1179static void _mbedtls_log_cb(void* ctx, int level, const char* filename, int line, const char* message)
1180{
1181 fprintf(stderr, "[mbedtls][%d] %s:%d => %s", level, filename, line, message);
1182}
1183
1184static int cert_verify_cb(void* ctx, mbedtls_x509_crt* cert, int depth, uint32_t *flags)
1185{
1186 *flags = 0;
1187 return 0;
1188}
1189
1190static int _mbedtls_f_rng(void* p_rng, unsigned char* buf, size_t len)
1191{
1192 memset(buf, 4, len);
1193 return 0;
1194}
1195#endif
562 1196
563/**
564 * Enables SSL for the given connection.
565 *
566 * @param connection The connection to enable SSL for.
567 *
568 * @return IDEVICE_E_SUCCESS on success, IDEVICE_E_INVALID_ARG when connection
569 * is NULL or connection->ssl_data is non-NULL, or IDEVICE_E_SSL_ERROR when
570 * SSL initialization, setup, or handshake fails.
571 */
572idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) 1197idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
573{ 1198{
574 if (!connection || connection->ssl_data) 1199 if (!connection || connection->ssl_data)
575 return IDEVICE_E_INVALID_ARG; 1200 return IDEVICE_E_INVALID_ARG;
576 1201
577 idevice_error_t ret = IDEVICE_E_SSL_ERROR; 1202 idevice_error_t ret = IDEVICE_E_SSL_ERROR;
578 uint32_t return_me = 0; 1203 plist_t pair_record = NULL;
1204
1205 userpref_error_t uerr = userpref_read_pair_record(connection->device->udid, &pair_record);
1206 if (uerr != USERPREF_E_SUCCESS) {
1207 debug_info("ERROR: Failed enabling SSL. Unable to read pair record for udid %s (%d)", connection->device->udid, uerr);
1208 return ret;
1209 }
1210
1211#if defined(HAVE_OPENSSL)
1212 key_data_t root_cert = { NULL, 0 };
1213 key_data_t root_privkey = { NULL, 0 };
1214
1215 pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert);
1216 pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_privkey);
579 1217
1218 if (pair_record)
1219 plist_free(pair_record);
1220
1221 BIO *ssl_bio = ssl_idevice_bio_new(connection);
1222 if (!ssl_bio) {
1223 debug_info("ERROR: Could not create SSL bio.");
1224 return ret;
1225 }
1226
1227 SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
1228 if (ssl_ctx == NULL) {
1229 debug_info("ERROR: Could not create SSL context.");
1230 BIO_free(ssl_bio);
1231 return ret;
1232 }
1233
1234#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) || \
1235 (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x3060000fL))
1236 SSL_CTX_set_security_level(ssl_ctx, 0);
1237#endif
1238
1239#if OPENSSL_VERSION_NUMBER < 0x10100002L || \
1240 (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2060000fL))
1241 /* force use of TLSv1 for older devices */
1242 if (connection->device->version < DEVICE_VERSION(10,0,0)) {
1243#ifdef SSL_OP_NO_TLSv1_1
1244 SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1);
1245#endif
1246#ifdef SSL_OP_NO_TLSv1_2
1247 SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2);
1248#endif
1249#ifdef SSL_OP_NO_TLSv1_3
1250 SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3);
1251#endif
1252 }
1253#else
1254 SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION);
1255 if (connection->device->version < DEVICE_VERSION(10,0,0)) {
1256 SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_VERSION);
1257 if (connection->device->version == 0) {
1258 /*
1259 iOS 1 doesn't understand TLS1_VERSION, it can only speak SSL3_VERSION.
1260 However, modern OpenSSL is usually compiled without SSLv3 support.
1261 So if we set min_proto_version to SSL3_VERSION on an OpenSSL instance which doesn't support it,
1262 it will just ignore min_proto_version altogether and fall back to an even higher version.
1263 To avoid accidentally breaking iOS 2.0+, we set min version to 0 instead.
1264 Here is what documentation says:
1265 Setting the minimum or maximum version to 0,
1266 will enable protocol versions down to the lowest version,
1267 or up to the highest version supported by the library, respectively.
1268 */
1269 SSL_CTX_set_min_proto_version(ssl_ctx, 0);
1270 }
1271 }
1272#endif
1273#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1274#if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
1275 /*
1276 * For OpenSSL 3 and later, mark close_notify alerts as optional.
1277 * For prior versions of OpenSSL we check for SSL_ERROR_SYSCALL when
1278 * reading instead (this error changes to SSL_ERROR_SSL in OpenSSL 3).
1279 */
1280 SSL_CTX_set_options(ssl_ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
1281#endif
1282#if defined(SSL_OP_LEGACY_SERVER_CONNECT)
1283 /*
1284 * Without setting SSL_OP_LEGACY_SERVER_CONNECT, OpenSSL 3 fails with
1285 * error "unsafe legacy renegotiation disabled" when talking to iOS 5
1286 */
1287 SSL_CTX_set_options(ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
1288#endif
1289#endif
1290
1291 BIO* membp;
1292 X509* rootCert = NULL;
1293 membp = BIO_new_mem_buf(root_cert.data, root_cert.size);
1294 PEM_read_bio_X509(membp, &rootCert, NULL, NULL);
1295 BIO_free(membp);
1296 if (SSL_CTX_use_certificate(ssl_ctx, rootCert) != 1) {
1297 debug_info("WARNING: Could not load RootCertificate");
1298 }
1299 X509_free(rootCert);
1300 free(root_cert.data);
1301
1302#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1303 EVP_PKEY* rootPrivKey = NULL;
1304 membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
1305 PEM_read_bio_PrivateKey(membp, &rootPrivKey, NULL, NULL);
1306 BIO_free(membp);
1307 if (SSL_CTX_use_PrivateKey(ssl_ctx, rootPrivKey) != 1) {
1308 debug_info("WARNING: Could not load RootPrivateKey");
1309 }
1310 EVP_PKEY_free(rootPrivKey);
1311#else
1312 RSA* rootPrivKey = NULL;
1313 membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
1314 PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL);
1315 BIO_free(membp);
1316 if (SSL_CTX_use_RSAPrivateKey(ssl_ctx, rootPrivKey) != 1) {
1317 debug_info("WARNING: Could not load RootPrivateKey");
1318 }
1319 RSA_free(rootPrivKey);
1320#endif
1321 free(root_privkey.data);
1322
1323 SSL *ssl = SSL_new(ssl_ctx);
1324 if (!ssl) {
1325 debug_info("ERROR: Could not create SSL object");
1326 BIO_free(ssl_bio);
1327 SSL_CTX_free(ssl_ctx);
1328 return ret;
1329 }
1330 SSL_set_connect_state(ssl);
1331 SSL_set_verify(ssl, 0, ssl_verify_callback);
1332 SSL_set_bio(ssl, ssl_bio, ssl_bio);
1333
1334 debug_info("Performing SSL handshake");
1335 int ssl_error = 0;
1336 do {
1337 ssl_error = SSL_get_error(ssl, SSL_do_handshake(ssl));
1338 if (ssl_error == 0 || ssl_error != SSL_ERROR_WANT_READ) {
1339 break;
1340 }
1341#ifdef WIN32
1342 Sleep(100);
1343#else
1344 struct timespec ts = { 0, 100000000 };
1345 nanosleep(&ts, NULL);
1346#endif
1347 } while (1);
1348 if (ssl_error != 0) {
1349 debug_info("ERROR during SSL handshake: %s", ssl_error_to_string(ssl_error));
1350 SSL_free(ssl);
1351 SSL_CTX_free(ssl_ctx);
1352 } else {
1353 ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
1354 ssl_data_loc->session = ssl;
1355 ssl_data_loc->ctx = ssl_ctx;
1356 connection->ssl_data = ssl_data_loc;
1357 ret = IDEVICE_E_SUCCESS;
1358 debug_info("SSL mode enabled, %s, cipher: %s", SSL_get_version(ssl), SSL_get_cipher(ssl));
1359 }
1360 /* required for proper multi-thread clean up to prevent leaks */
1361 openssl_remove_thread_state();
1362#elif defined(HAVE_GNUTLS)
580 ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private)); 1363 ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
581 1364
582 /* Set up GnuTLS... */ 1365 /* Set up GnuTLS... */
583 debug_info("enabling SSL mode"); 1366 debug_info("enabling SSL mode");
584 errno = 0; 1367 errno = 0;
585 gnutls_global_init();
586 gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate); 1368 gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate);
587 gnutls_certificate_client_set_retrieve_function (ssl_data_loc->certificate, internal_cert_callback); 1369#if GNUTLS_VERSION_NUMBER >= 0x020b07
1370 gnutls_certificate_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback);
1371#else
1372 gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback);
1373#endif
588 gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); 1374 gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT);
589 { 1375 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);
590 int protocol_priority[16] = { GNUTLS_SSL3, 0 };
591 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 };
592 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 };
593 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 };
594 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
595
596 gnutls_cipher_set_priority(ssl_data_loc->session, cipher_priority);
597 gnutls_compression_set_priority(ssl_data_loc->session, comp_priority);
598 gnutls_kx_set_priority(ssl_data_loc->session, kx_priority);
599 gnutls_protocol_set_priority(ssl_data_loc->session, protocol_priority);
600 gnutls_mac_set_priority(ssl_data_loc->session, mac_priority);
601 }
602 gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); 1376 gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate);
603 gnutls_session_set_ptr(ssl_data_loc->session, ssl_data_loc); 1377 gnutls_session_set_ptr(ssl_data_loc->session, ssl_data_loc);
604 1378
@@ -607,10 +1381,13 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
607 gnutls_x509_privkey_init(&ssl_data_loc->root_privkey); 1381 gnutls_x509_privkey_init(&ssl_data_loc->root_privkey);
608 gnutls_x509_privkey_init(&ssl_data_loc->host_privkey); 1382 gnutls_x509_privkey_init(&ssl_data_loc->host_privkey);
609 1383
610 userpref_error_t uerr = userpref_get_keys_and_certs(ssl_data_loc->root_privkey, ssl_data_loc->root_cert, ssl_data_loc->host_privkey, ssl_data_loc->host_cert); 1384 pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, ssl_data_loc->root_cert);
611 if (uerr != USERPREF_E_SUCCESS) { 1385 pair_record_import_crt_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, ssl_data_loc->host_cert);
612 debug_info("Error %d when loading keys and certificates! %d", uerr); 1386 pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, ssl_data_loc->root_privkey);
613 } 1387 pair_record_import_key_with_name(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, ssl_data_loc->host_privkey);
1388
1389 if (pair_record)
1390 plist_free(pair_record);
614 1391
615 debug_info("GnuTLS step 1..."); 1392 debug_info("GnuTLS step 1...");
616 gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection); 1393 gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection);
@@ -619,46 +1396,146 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
619 debug_info("GnuTLS step 3..."); 1396 debug_info("GnuTLS step 3...");
620 gnutls_transport_set_pull_function(ssl_data_loc->session, (gnutls_pull_func) & internal_ssl_read); 1397 gnutls_transport_set_pull_function(ssl_data_loc->session, (gnutls_pull_func) & internal_ssl_read);
621 debug_info("GnuTLS step 4 -- now handshaking..."); 1398 debug_info("GnuTLS step 4 -- now handshaking...");
622 if (errno) 1399 if (errno) {
623 debug_info("WARN: errno says %s before handshake!", strerror(errno)); 1400 debug_info("WARNING: errno says %s before handshake!", strerror(errno));
624 return_me = gnutls_handshake(ssl_data_loc->session); 1401 }
1402
1403 int return_me = 0;
1404 do {
1405 return_me = gnutls_handshake(ssl_data_loc->session);
1406 } while(return_me == GNUTLS_E_AGAIN || return_me == GNUTLS_E_INTERRUPTED);
1407
625 debug_info("GnuTLS handshake done..."); 1408 debug_info("GnuTLS handshake done...");
626 1409
627 if (return_me != GNUTLS_E_SUCCESS) { 1410 if (return_me != GNUTLS_E_SUCCESS) {
628 internal_ssl_cleanup(ssl_data_loc); 1411 internal_ssl_cleanup(ssl_data_loc);
629 free(ssl_data_loc); 1412 free(ssl_data_loc);
630 debug_info("GnuTLS reported something wrong."); 1413 debug_info("GnuTLS reported something wrong: %s", gnutls_strerror(return_me));
631 gnutls_perror(return_me);
632 debug_info("oh.. errno says %s", strerror(errno)); 1414 debug_info("oh.. errno says %s", strerror(errno));
633 } else { 1415 } else {
634 connection->ssl_data = ssl_data_loc; 1416 connection->ssl_data = ssl_data_loc;
635 ret = IDEVICE_E_SUCCESS; 1417 ret = IDEVICE_E_SUCCESS;
636 debug_info("SSL mode enabled"); 1418 debug_info("SSL mode enabled");
637 } 1419 }
1420#elif defined(HAVE_MBEDTLS)
1421 key_data_t root_cert = { NULL, 0 };
1422 key_data_t root_privkey = { NULL, 0 };
1423
1424 pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert);
1425 pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_privkey);
1426
1427 plist_free(pair_record);
1428
1429 ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
1430
1431 mbedtls_ssl_init(&ssl_data_loc->ctx);
1432 mbedtls_ssl_config_init(&ssl_data_loc->config);
1433 mbedtls_entropy_init(&ssl_data_loc->entropy);
1434 mbedtls_ctr_drbg_init(&ssl_data_loc->ctr_drbg);
1435
1436 int r = mbedtls_ctr_drbg_seed(&ssl_data_loc->ctr_drbg, mbedtls_entropy_func, &ssl_data_loc->entropy, NULL, 0);
1437 if (r != 0) {
1438 debug_info("ERROR: [mbedtls] mbedtls_ctr_drbg_seed failed: %d", r);
1439 return ret;
1440 }
1441
1442 if (mbedtls_ssl_config_defaults(&ssl_data_loc->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
1443 debug_info("ERROR: [mbedtls] Failed to set config defaults");
1444 return ret;
1445 }
1446
1447 mbedtls_ssl_conf_rng(&ssl_data_loc->config, mbedtls_ctr_drbg_random, &ssl_data_loc->ctr_drbg);
1448
1449 mbedtls_ssl_conf_dbg(&ssl_data_loc->config, _mbedtls_log_cb, NULL);
1450
1451 mbedtls_ssl_conf_verify(&ssl_data_loc->config, cert_verify_cb, NULL);
1452
1453 mbedtls_ssl_setup(&ssl_data_loc->ctx, &ssl_data_loc->config);
1454
1455 mbedtls_ssl_set_bio(&ssl_data_loc->ctx, connection, (mbedtls_ssl_send_t*)&internal_ssl_write, (mbedtls_ssl_recv_t*)&internal_ssl_read, NULL);
1456
1457 mbedtls_x509_crt_init(&ssl_data_loc->certificate);
1458
1459 int crterr = mbedtls_x509_crt_parse(&ssl_data_loc->certificate, root_cert.data, root_cert.size);
1460 if (crterr < 0) {
1461 debug_info("ERROR: [mbedtls] parsing root cert failed: %d", crterr);
1462 return ret;
1463 }
1464
1465 mbedtls_ssl_conf_ca_chain(&ssl_data_loc->config, &ssl_data_loc->certificate, NULL);
1466
1467 mbedtls_pk_init(&ssl_data_loc->root_privkey);
1468
1469#if MBEDTLS_VERSION_NUMBER >= 0x03000000
1470 int pkerr = mbedtls_pk_parse_key(&ssl_data_loc->root_privkey, root_privkey.data, root_privkey.size, NULL, 0, &_mbedtls_f_rng, NULL);
1471#else
1472 int pkerr = mbedtls_pk_parse_key(&ssl_data_loc->root_privkey, root_privkey.data, root_privkey.size, NULL, 0);
1473#endif
1474 if (pkerr < 0) {
1475 debug_info("ERROR: [mbedtls] parsing private key failed: %d (size=%d)", pkerr, root_privkey.size);
1476 return ret;
1477 }
1478
1479 mbedtls_ssl_conf_own_cert(&ssl_data_loc->config, &ssl_data_loc->certificate, &ssl_data_loc->root_privkey);
1480
1481 int return_me = 0;
1482 do {
1483 return_me = mbedtls_ssl_handshake(&ssl_data_loc->ctx);
1484 } while (return_me == MBEDTLS_ERR_SSL_WANT_READ || return_me == MBEDTLS_ERR_SSL_WANT_WRITE);
1485
1486 if (return_me != 0) {
1487 debug_info("ERROR during SSL handshake: %d", return_me);
1488 internal_ssl_cleanup(ssl_data_loc);
1489 free(ssl_data_loc);
1490 } else {
1491 connection->ssl_data = ssl_data_loc;
1492 ret = IDEVICE_E_SUCCESS;
1493 debug_info("SSL mode enabled, %s, cipher: %s", mbedtls_ssl_get_version(&ssl_data_loc->ctx), mbedtls_ssl_get_ciphersuite(&ssl_data_loc->ctx));
1494 debug_info("SSL mode enabled");
1495 }
1496#endif
638 return ret; 1497 return ret;
639} 1498}
640 1499
641/**
642 * Disable SSL for the given connection.
643 *
644 * @param connection The connection to disable SSL for.
645 *
646 * @return IDEVICE_E_SUCCESS on success, IDEVICE_E_INVALID_ARG when connection
647 * is NULL. This function also returns IDEVICE_E_SUCCESS when SSL is not
648 * enabled and does no further error checking on cleanup.
649 */
650idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection) 1500idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection)
651{ 1501{
1502 return idevice_connection_disable_bypass_ssl(connection, 0);
1503}
1504
1505idevice_error_t idevice_connection_disable_bypass_ssl(idevice_connection_t connection, uint8_t sslBypass)
1506{
652 if (!connection) 1507 if (!connection)
653 return IDEVICE_E_INVALID_ARG; 1508 return IDEVICE_E_INVALID_ARG;
654 if (!connection->ssl_data) { 1509 if (!connection->ssl_data) {
655 /* ignore if ssl is not enabled */ 1510 /* ignore if ssl is not enabled */
656 return IDEVICE_E_SUCCESS; 1511 return IDEVICE_E_SUCCESS;
657 } 1512 }
658 1513
659 if (connection->ssl_data->session) { 1514 // some services require plain text communication after SSL handshake
660 gnutls_bye(connection->ssl_data->session, GNUTLS_SHUT_RDWR); 1515 // sending out SSL_shutdown will cause bytes
1516 if (!sslBypass) {
1517#if defined(HAVE_OPENSSL)
1518 if (connection->ssl_data->session) {
1519 /* see: https://www.openssl.org/docs/ssl/SSL_shutdown.html#RETURN_VALUES */
1520 if (SSL_shutdown(connection->ssl_data->session) == 0) {
1521 /* Only try bidirectional shutdown if we know it can complete */
1522 int ssl_error;
1523 if ((ssl_error = SSL_get_error(connection->ssl_data->session, 0)) == SSL_ERROR_NONE) {
1524 SSL_shutdown(connection->ssl_data->session);
1525 } else {
1526 debug_info("Skipping bidirectional SSL shutdown. SSL error code: %i", ssl_error);
1527 }
1528 }
1529 }
1530#elif defined(HAVE_GNUTLS)
1531 if (connection->ssl_data->session) {
1532 gnutls_bye(connection->ssl_data->session, GNUTLS_SHUT_RDWR);
1533 }
1534#elif defined(HAVE_MBEDTLS)
1535 mbedtls_ssl_close_notify(&connection->ssl_data->ctx);
1536#endif
661 } 1537 }
1538
662 internal_ssl_cleanup(connection->ssl_data); 1539 internal_ssl_cleanup(connection->ssl_data);
663 free(connection->ssl_data); 1540 free(connection->ssl_data);
664 connection->ssl_data = NULL; 1541 connection->ssl_data = NULL;
@@ -667,4 +1544,3 @@ idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection)
667 1544
668 return IDEVICE_E_SUCCESS; 1545 return IDEVICE_E_SUCCESS;
669} 1546}
670