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